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