1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     main.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 //------------------------------------------------------------------
19 // デモ: animShare
20 //
21 // 概要
22 //   アニメーション共有のデモです。
23 //
24 //   animShare.clan ファイルでは、ペイン「Picture_00」にのみアニメーションが
25 //   設定されており、このアニメーションをグループ「Group_00」に登録されている
26 //   各ペインで共有するようにアニメーション共有設定が行われています。
27 //   グループ「Group_00」には、全てのPictureペイン(Picture_00 ~ Picture_11)が
28 //   登録されています。
29 //
30 // 操作
31 //   十字ボタンの操作でクロスラインが移動します。
32 //   クロスラインのクロスしている部分がペイン上にくると、
33 //   そのペインが拡大するアニメーションが動作します。
34 //   拡大しているときに、クロスしている部分が離れると
35 //   しだいに縮小して元の大きさに戻ります。
36 //
37 //------------------------------------------------------------------
38 
39 #include <GLES2/gl2.h>
40 #include <nw/lyt.h>
41 #include <nw/demo.h>
42 
43 namespace
44 {
45 
46 typedef nw::ut::MoveArray<u8> File;
47 
48 /*---------------------------------------------------------------------------*
49   @brief 描画の初期設定を行います。
50 
51   @param width  画面の幅。
52   @param height  画面の高さ。
53  *---------------------------------------------------------------------------*/
54 void
InitDraw(int width,int height)55 InitDraw(int width, int height)
56 {
57     // カラーバッファ情報
58     // LCDの向きに合わせて、幅と高さを入れ替えています。
59     const nw::font::ColorBufferInfo colBufInfo =
60     {
61         height, width, PICA_DATA_DEPTH24_STENCIL8_EXT
62     };
63 
64     const u32 commands[] =
65     {
66         // ビューポートの設定
67         NW_FONT_CMD_SET_VIEWPORT(0, 0, colBufInfo.width, colBufInfo.height),
68 
69         // シザー処理を無効
70         NW_FONT_CMD_SET_DISABLE_SCISSOR(colBufInfo),
71 
72         // wバッファの無効化
73         // デプスレンジの設定
74         // ポリゴンオフセットの無効化
75         NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
76             0.0f,           // wScale : 0.0 でWバッファが無効
77             0.0f,           // depth range near
78             1.0f,           // depth range far
79             0,              // polygon offset units : 0.0 で ポリゴンオフセットが無効
80             colBufInfo),
81     };
82 
83     nngxAdd3DCommand(commands, sizeof(commands), true);
84 
85     static const u32 constCommands[] =
86     {
87         // カリングを無効
88         NW_FONT_CMD_SET_CULL_FACE(NW_FONT_CMD_CULL_FACE_DISABLE),
89 
90         // ステンシルテストを無効
91         NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
92 
93         // デプステストを無効
94         // カラーバッファの全ての成分を書き込み可
95         NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
96             false,  // isDepthTestEnabled
97             0,      // depthFunc
98             true,   // depthMask
99             true,   // red
100             true,   // green
101             true,   // blue
102             true),  // alpha
103 
104         // アーリーデプステストを無効
105         NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false),
106 
107         // フレームバッファアクセス制御
108         NW_FONT_CMD_SET_FBACCESS(
109             true,   // colorRead
110             true,   // colorWrite
111             false,  // depthRead
112             false,  // depthWrite
113             false,  // stencilRead
114             false), // stencilWrite
115     };
116 
117     nngxAdd3DCommand(constCommands, sizeof(constCommands), true);
118 }
119 
120 /*---------------------------------------------------------------------------*
121   @brief  モデルビュー行列と射影行列を設定します。
122 
123   @param drawInfo  描画情報です。
124   @param layout  レイアウトです。
125  *---------------------------------------------------------------------------*/
126 void
SetupCamera(nw::lyt::DrawInfo & drawInfo,const nw::lyt::Layout & layout)127 SetupCamera(nw::lyt::DrawInfo& drawInfo, const nw::lyt::Layout& layout)
128 {
129     nw::ut::Rect layoutRect = layout.GetLayoutRect();
130 
131     f32 znear = 0.f;
132     f32 zfar = 500.f;
133 
134     // 射影行列を正射影に設定
135     // (Layoutデータは横向きなので向きを変換する)
136     nw::math::MTX44 projMtx;
137     nw::math::MTX44Ortho(
138         &projMtx,
139         layoutRect.bottom,  // left
140         layoutRect.top,     // right
141         -layoutRect.right,  // bottom
142         -layoutRect.left,   // top
143         znear,
144         zfar);
145     drawInfo.SetProjectionMtx(projMtx);
146 
147     // モデルビュー行列を設定
148     // (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向)
149     nw::math::VEC3 pos(0, 0, 1);
150     nw::math::VEC3 up(-1, 0, 0);
151     nw::math::VEC3 target(0, 0, 0);
152 
153     nw::math::MTX34 viewMtx;
154     nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
155     drawInfo.SetViewMtx(viewMtx);
156 }
157 
158 /*---------------------------------------------------------------------------*
159   @brief カーソルの位置をレイアウトに反映します。
160 
161   @param layout  レイアウトへの参照です。
162 
163   @return Layoutの座標系におけるカーソル位置を返します。
164  *---------------------------------------------------------------------------*/
165 nw::math::VEC2
GetCursorPosition(nw::lyt::Layout & layout)166 GetCursorPosition(nw::lyt::Layout& layout)
167 {
168     const nw::ut::Rect& layoutRect = layout.GetLayoutRect();
169     const nw::math::VEC2 center(
170         (layoutRect.left  + layoutRect.right ) / 2,
171         (layoutRect.top   + layoutRect.bottom) / 2
172         );
173 
174     nw::math::VEC2 curPos;
175 
176     // カーソルの座標系をレイアウトの座標系に変換します。
177     const nw::ut::Rect cursorRect(-0.5, 0.5, 0.5, -0.5); // LTRB
178     nw::demo::Pad& pad = *nw::demo::PadFactory::GetPad();
179     const nw::math::VEC2 stick = pad.GetAnalogStick();
180     curPos.x = center.x + stick.x / (cursorRect.right - cursorRect.left  ) * (layoutRect.right - layoutRect.left  );
181     curPos.y = center.y + stick.y / (cursorRect.top   - cursorRect.bottom) * (layoutRect.top   - layoutRect.bottom);
182     // NW_LOG("curPos %f, %f\n", curPos.x, curPos.y);
183 
184     return curPos;
185 }
186 
187 /*---------------------------------------------------------------------------*
188   @brief カーソルの位置をレイアウトに反映します。
189 
190   @param layout レイアウトへの参照です。
191   @param curPos レイアウトの座標系におけるカーソルの位置です。
192  *---------------------------------------------------------------------------*/
193 void
ApplyCursorPosition(nw::lyt::Layout & layout,const nw::math::VEC2 & curPos)194 ApplyCursorPosition(nw::lyt::Layout& layout, const nw::math::VEC2& curPos)
195 {
196     nw::lyt::Pane* pCrossBar = layout.GetRootPane()->FindPaneByName("CrossBar", true);
197     if (pCrossBar)
198     {
199         pCrossBar->SetTranslate(curPos);
200     }
201 }
202 
203 /*---------------------------------------------------------------------------*
204   @brief AnimationLinkを検索します。
205 
206   @details
207   指定したアニメーションリソースをペインやマテリアルにバインドしている
208   nw::lyt::AnimationLink を検索し、最初に見つかったものを返します。
209   指定されたペインの子孫を含めて検索します。
210 
211   @param pPane  検索対象のルートとなるペインです。
212   @param animRes  アニメーションリソースです。
213 
214   @return
215   見つかった場合は、nw::lyt::AnimationLink のポインタを返します。
216   見つからなかった場合は、NULL を返します。
217  *---------------------------------------------------------------------------*/
218 nw::lyt::AnimationLink*
FindLayoutAnimationLink(nw::lyt::Pane * pPane,const nw::lyt::AnimResource & animRes)219 FindLayoutAnimationLink(
220     nw::lyt::Pane*                pPane,
221     const nw::lyt::AnimResource&  animRes
222 )
223 {
224     // ペインアニメーションの検索
225     if (nw::lyt::AnimationLink *const pAnimLink = pPane->FindAnimationLinkSelf(animRes))
226     {
227         return pAnimLink;
228     }
229 
230     // マテリアルアニメーションの設定
231     const u8 materialNum = pPane->GetMaterialNum();
232     for (u8 i = 0; i < materialNum; ++i)
233     {
234         if (nw::lyt::AnimationLink *const pAnimLink = pPane->GetMaterial(i)->FindAnimationLink(animRes))
235         {
236             return pAnimLink;
237         }
238     }
239 
240     // 再帰的に検索します。
241     for (nw::lyt::PaneList::Iterator it = pPane->GetChildList().GetBeginIter(); it != pPane->GetChildList().GetEndIter(); ++it)
242     {
243         if (nw::lyt::AnimationLink* pAnimLink = FindLayoutAnimationLink(&(*it), animRes))
244         {
245             return pAnimLink;
246         }
247     }
248 
249     return NULL;
250 }
251 
252 /*---------------------------------------------------------------------------*
253   @brief アニメーションリソースのフレーム値を設定します。
254 
255   @details
256   指定したアニメーションリソースの現在のフレーム値を全て同じに設定します。
257   指定されたペインの子孫を含めて行います。
258 
259   @param pPane  対象となるペインのルートとなるペインです。
260   @param animRes  アニメーションリソースです。
261   @param frame  設定するフレーム値です。
262  *---------------------------------------------------------------------------*/
263 void
SetAnimationFrame(nw::lyt::Pane * pPane,const nw::lyt::AnimResource & animRes,f32 frame)264 SetAnimationFrame(
265     nw::lyt::Pane*                pPane,
266     const nw::lyt::AnimResource&  animRes,
267     f32                           frame
268 )
269 {
270     // ペインアニメーションの設定
271     if (nw::lyt::AnimationLink *const pAnimLink = pPane->FindAnimationLinkSelf(animRes))
272     {
273         pAnimLink->GetAnimTransform()->SetFrame(frame);
274     }
275 
276     // マテリアルアニメーションの設定
277     const u8 materialNum = pPane->GetMaterialNum();
278     for (u8 i = 0; i < materialNum; ++i)
279     {
280         if (nw::lyt::AnimationLink *const pAnimLink = pPane->GetMaterial(i)->FindAnimationLink(animRes))
281         {
282             pAnimLink->GetAnimTransform()->SetFrame(frame);
283         }
284     }
285 
286     // 再帰的に行います。
287     for (nw::lyt::PaneList::Iterator it = pPane->GetChildList().GetBeginIter(); it != pPane->GetChildList().GetEndIter(); ++it)
288     {
289         SetAnimationFrame(&(*it), animRes, frame);
290     }
291 }
292 
293 /*---------------------------------------------------------------------------*
294   @brief アニメーションの状態を更新します。
295 
296   @details
297   十字カーソルでポイントされているかどうかでアニメーションの状態を更新します。
298 
299   @param pPane  アニメーションを更新するペイン階層のルートとなるペインです。
300   @param animRes  アニメーションリソースオブジェクトです。
301   @param bContain  十字カーソルでポイントされていたら真を指定します。
302  *---------------------------------------------------------------------------*/
303 void
UpdateAnimationFrame(nw::lyt::Pane * pPane,const nw::lyt::AnimResource & animRes,bool bContain)304 UpdateAnimationFrame(
305     nw::lyt::Pane*                pPane,
306     const nw::lyt::AnimResource&  animRes,
307     bool                          bContain
308 )
309 {
310     // 指定した アニメーションリソースをリンクする nw::lyt::AnimationLink を探します。
311     // 最初に見つかったものが返ります。
312     nw::lyt::AnimationLink *const pAnimationLink = FindLayoutAnimationLink(pPane, animRes);
313     if (! pAnimationLink)
314     {
315         return;
316     }
317 
318     // nw::lyt::AnimationLink から nw::lyt::AnimTransform 取得して、
319     // 現在のフレーム値と最大フレームを取得します。
320     nw::lyt::AnimTransform *const pAnimTrans = pAnimationLink->GetAnimTransform();
321     f32 animFrame = pAnimTrans->GetFrame();                     // 現在のフレーム
322     const f32 animFrameMax = static_cast<f32>(pAnimTrans->GetFrameSize() - 1);    // フレームの最大値
323 
324     if (bContain)
325     {
326         // ポイントされている場合は、
327         // アニメーションのフレーム値を前に進めます。
328         const f32 step = 2.f;
329         if (animFrame < animFrameMax)
330         {
331             animFrame = nw::ut::Min(animFrameMax, animFrame + step);
332             // pPane以下の全てのペイン、マテリアルのアニメーションフレームを同じ値に設定します。
333             SetAnimationFrame(pPane, animRes, animFrame);
334         }
335     }
336     else
337     {
338         // ポイントされていない場合は、
339         // アニメーションのフレーム値を戻していきます。
340         const f32 step = 1.f;
341         if (animFrame > 0.f)        // 現在のフレームが0でない場合
342         {
343             animFrame = nw::ut::Max(0.f, animFrame - step);
344             // pPane以下の全てのペイン、マテリアルのアニメーションフレームを同じ値に設定します。
345             SetAnimationFrame(pPane, animRes, animFrame);
346         }
347     }
348 }
349 
350 /*---------------------------------------------------------------------------*
351   @brief 各ペインの状態を更新します。
352 
353   @param pos  カーソル位置です。
354   @param pGroup  更新する対象のペインが登録されているグループです。
355   @param animRes  アニメーションリソースオブジェクトです。
356  *---------------------------------------------------------------------------*/
357 void
UpdatePane(const nw::math::VEC2 & pos,nw::lyt::Group * pGroup,const nw::lyt::AnimResource & animRes)358 UpdatePane(
359     const nw::math::VEC2&         pos,
360     nw::lyt::Group*               pGroup,
361     const nw::lyt::AnimResource&  animRes
362 )
363 {
364     // グループに登録されているペインごとの処理
365     nw::lyt::PaneLinkList& paneList = pGroup->GetPaneList();
366     for (nw::lyt::PaneLinkList::Iterator it = paneList.GetBeginIter(); it != paneList.GetEndIter(); ++it)
367     {
368         // グループに登録されているペイン
369         nw::lyt::Pane *const pPane = it->target;
370 
371         // 十字カーソルでポイントされているかどうかでアニメーションの状態を更新します。
372         const bool bContain = nw::lyt::IsContain(pPane, pos);
373         UpdateAnimationFrame(
374             pPane,
375             animRes,
376             bContain);
377     }
378 }
379 
380 }   // namespace
381 
382 /*---------------------------------------------------------------------------*
383   @brief サンプルのメイン関数です。
384  *---------------------------------------------------------------------------*/
385 void
nnMain()386 nnMain()
387 {
388     nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance();
389     demoApp.Initialize();
390 
391     nw::lyt::Initialize(&demoApp.GetAllocator(), &demoApp.GetDeviceAllocator());
392 
393     nw::lyt::Layout* pLayout = new nw::lyt::Layout();
394 
395     // レイアウトのバイナリリソース(アーカイブ)を読み込み。
396     File fileLayout = nw::demo::Utility::LoadFile(
397         &demoApp.GetDeviceAllocator(), NW_DEMO_FILE_PATH(L"layout.arc"), 128);
398 
399     if (fileLayout.empty())
400     {
401         NW_FATAL_ERROR("can not open layout archive.\n");
402     }
403 
404     // バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。
405     nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor;
406     if (!pResAccessor->Attach(fileLayout.begin(), "."))
407     {
408         NW_FATAL_ERROR("can not attach layout archive.\n");
409     }
410 
411     // レイアウトリソースの読み込み
412     {
413         const void* lytRes = pResAccessor->GetResource(0, "animShare.bclyt");
414         NW_NULL_ASSERT(lytRes);
415         pLayout->Build(lytRes, pResAccessor);
416     }
417 
418     nw::lyt::AnimResource animRes;
419     nw::lyt::AnimTransform* pAnimTrans = 0;
420     // アニメーションリソースの読み込み
421     {
422         const void* lpaRes = pResAccessor->GetResource(0, "animShare_focus.bclan");
423         NW_NULL_ASSERT(lpaRes);
424         animRes.Set(lpaRes);
425     }
426 
427     // アニメーション共有設定、アニメーション区間タグの関連グループを
428     // 考慮したアニメーションのバインドを行います。
429     pLayout->BindAnimationAuto(animRes, pResAccessor);
430 
431     // Layout::BindAnimationAuto() でバインドしたアニメーションは無効になっています。
432     // このサンプルの場合は個別にアニメーションの有効/無効を
433     // 切り替える必要が無いため、全体でアニメーションを有効にします。
434     pLayout->GetRootPane()->SetAnimationEnable(animRes, true/*bEnable*/, true/*bRecursive*/);
435 
436     // ピクチャペインが登録されているグループのポインタを取得します。
437     nw::lyt::Group *const pGroup_00 = pLayout->GetGroupContainer()->FindGroupByName("Group_00");
438 
439     f32 animFrame = 0;
440 
441     nw::lyt::GraphicsResource graphicsResource;
442     // グローバルなリソースファイルを読み込みます。
443     {
444         graphicsResource.StartSetup();
445         const wchar_t* resourcePath = 0;
446         for (int i = 0;
447              (resourcePath = graphicsResource.GetResourcePath(i)) != NULL;
448              ++i)
449         {
450             File file = nw::demo::Utility::LoadFile(&demoApp.GetAllocator(), resourcePath);
451 
452             if (file.empty())
453             {
454                 NW_FATAL_ERROR("can not open lyt resource file.");
455             }
456 
457             graphicsResource.SetResource(i, file.begin(), file.size(), false);
458         }
459 
460         graphicsResource.FinishSetup();
461     }
462 
463     nw::lyt::DrawInfo drawInfo;
464     drawInfo.SetGraphicsResource(&graphicsResource);
465     nw::math::VEC2 curPos(0.f, 0.f);
466 
467     nw::lyt::Drawer drawer;
468     drawer.Initialize(graphicsResource);
469 
470     const nw::ut::FloatColor clearColor(0.3f, 0.3f, 0.3f, 1.0f);
471     const f32 clearDepth = 0.0f;
472 
473     bool loop = true;
474     while (loop)
475     {
476         nw::demo::PadFactory::GetPad()->Update();
477 
478         demoApp.SetRenderingTarget(demoApp.DISPLAY0);
479         {
480             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
481 
482             InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
483 
484             SetupCamera(drawInfo, *pLayout);
485 
486             pLayout->CalculateMtx(drawInfo);
487 
488             drawer.DrawBegin(drawInfo);
489             drawer.Draw(pLayout, drawInfo);
490             drawer.DrawEnd(drawInfo);
491 
492             curPos = GetCursorPosition(*pLayout);
493 
494             // カーソルの位置をペインに反映します。
495             ApplyCursorPosition(*pLayout, curPos);
496 
497             // カーソル位置をレイアウト座標系からビュー座標系に変換します。
498             {
499                 nw::math::VEC3 tmp(curPos.x, curPos.y, 0.0f);
500                 nw::math::VEC3Transform(&tmp, &drawInfo.GetViewMtx(), &tmp);
501                 curPos = nw::math::VEC2(tmp.x, tmp.y);
502             }
503 
504             // カーソルに応じて、ペインの状態を更新します。
505             UpdatePane(curPos, pGroup_00, animRes);
506 
507             pLayout->Animate();
508 
509         }
510 
511         demoApp.SetRenderingTarget(demoApp.DISPLAY1);
512         {
513             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
514         }
515 
516         demoApp.SwapBuffer(demoApp.DISPLAY_BOTH);
517     }
518 
519     delete pLayout;
520     delete pResAccessor;
521 }
522 
523