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