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