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 // デモ: bounding
18 //
19 // 概要
20 //   boudingペインによるヒットチェックを行うデモです。
21 //
22 // 操作
23 //   十字ボタンの操作でクロスラインが移動します。
24 //   クロスラインのクロスしている部分をペインに移動させると、
25 //   そのペインのみ異なるアニメーションをします。
26 //
27 //------------------------------------------------------------------
28 
29 #include <nw/lyt.h>
30 #include <nw/demo.h>
31 
32 namespace
33 {
34 
35 typedef nw::ut::MoveArray<u8> File;
36 
37 /*---------------------------------------------------------------------------*
38   @brief 描画の初期設定を行います。
39 
40   @param width  画面の幅。
41   @param height  画面の高さ。
42  *---------------------------------------------------------------------------*/
43 void
InitDraw(int width,int height)44 InitDraw(int width, int height)
45 {
46     // カラーバッファ情報
47     // LCDの向きに合わせて、幅と高さを入れ替えています。
48     const nw::font::ColorBufferInfo colBufInfo =
49     {
50         height, width, PICA_DATA_DEPTH24_STENCIL8_EXT
51     };
52 
53     const u32 commands[] =
54     {
55         // ビューポートの設定
56         NW_FONT_CMD_SET_VIEWPORT(0, 0, colBufInfo.width, colBufInfo.height),
57 
58         // シザー処理を無効
59         NW_FONT_CMD_SET_DISABLE_SCISSOR(colBufInfo),
60 
61         // wバッファの無効化
62         // デプスレンジの設定
63         // ポリゴンオフセットの無効化
64         NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
65             0.0f,           // wScale : 0.0 でWバッファが無効
66             0.0f,           // depth range near
67             1.0f,           // depth range far
68             0,              // polygon offset units : 0.0 で ポリゴンオフセットが無効
69             colBufInfo),
70     };
71 
72     nngxAdd3DCommand(commands, sizeof(commands), true);
73 
74     static const u32 constCommands[] =
75     {
76         // カリングを無効
77         NW_FONT_CMD_SET_CULL_FACE(NW_FONT_CMD_CULL_FACE_DISABLE),
78 
79         // ステンシルテストを無効
80         NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
81 
82         // デプステストを無効
83         // カラーバッファの全ての成分を書き込み可
84         NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
85             false,  // isDepthTestEnabled
86             0,      // depthFunc
87             true,   // depthMask
88             true,   // red
89             true,   // green
90             true,   // blue
91             true),  // alpha
92 
93         // アーリーデプステストを無効
94         NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false),
95 
96         // フレームバッファアクセス制御
97         NW_FONT_CMD_SET_FBACCESS(
98             true,   // colorRead
99             true,   // colorWrite
100             false,  // depthRead
101             false,  // depthWrite
102             false,  // stencilRead
103             false), // stencilWrite
104     };
105 
106     nngxAdd3DCommand(constCommands, sizeof(constCommands), true);
107 }
108 
109 /*---------------------------------------------------------------------------*
110   @brief モデルビュー行列と射影行列を設定します。
111 
112   @param pDrawInfo 描画情報です。
113   @param layout レイアウトです。
114  *---------------------------------------------------------------------------*/
115 void
SetupCamera(nw::lyt::DrawInfo & drawInfo,const nw::lyt::Layout & layout)116 SetupCamera(nw::lyt::DrawInfo& drawInfo, const nw::lyt::Layout& layout)
117 {
118     nw::ut::Rect layoutRect = layout.GetLayoutRect();
119 
120     f32 znear = 0.f;
121     f32 zfar = 500.f;
122 
123     // 射影行列を正射影に設定
124     // (Layoutデータは横向きなので向きを変換する)
125     nw::math::MTX44 projMtx;
126     nw::math::MTX44Ortho(
127         &projMtx,
128         layoutRect.bottom,  // left
129         layoutRect.top,     // right
130         -layoutRect.right,  // bottom
131         -layoutRect.left,   // top
132         znear,
133         zfar);
134     drawInfo.SetProjectionMtx(projMtx);
135 
136     // モデルビュー行列を設定
137     // (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向)
138     nw::math::VEC3 pos(0, 0, 1);
139     nw::math::VEC3 up(-1, 0, 0);
140     nw::math::VEC3 target(0, 0, 0);
141 
142     nw::math::MTX34 viewMtx;
143     nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
144     drawInfo.SetViewMtx(viewMtx);
145 }
146 
147 /*---------------------------------------------------------------------------*
148   @brief カーソルの位置をレイアウトの座標系で取得します。
149 
150   @param pLayout  レイアウトです。
151 
152   @return カーソル位置を返します。
153  *---------------------------------------------------------------------------*/
154 const nw::math::VEC2
GetCursorPosition(nw::lyt::Layout * pLayout)155 GetCursorPosition(nw::lyt::Layout* pLayout)
156 {
157     const nw::ut::Rect& layoutRect = pLayout->GetLayoutRect();
158     const nw::math::VEC2 center(
159         (layoutRect.left  + layoutRect.right ) / 2,
160         (layoutRect.top   + layoutRect.bottom) / 2
161         );
162 
163     nw::math::VEC2 curPos;
164 
165     // カーソルの座標系をレイアウトの座標系に変換します。
166     const nw::ut::Rect cursorRect(-0.5, 0.5, 0.5, -0.5); // LTRB
167     nw::demo::Pad& pad = *nw::demo::PadFactory::GetPad();
168     const nw::math::VEC2 stick = pad.GetAnalogStick();
169     curPos.x = center.x + stick.x / (cursorRect.right - cursorRect.left  ) * (layoutRect.right - layoutRect.left  );
170     curPos.y = center.y + stick.y / (cursorRect.top   - cursorRect.bottom) * (layoutRect.top   - layoutRect.bottom);
171     // NW_LOG("curPos %f, %f\n", curPos.x, curPos.y);
172     return curPos;
173 }
174 
175 /*---------------------------------------------------------------------------*
176   @brief カーソルの位置をレイアウトに反映します。
177 
178   @param pLayout レイアウトです。
179   @param curPos レイアウトの座標系におけるカーソルの位置です。
180  *---------------------------------------------------------------------------*/
181 void
ApplyCursorPosition(nw::lyt::Layout * pLayout,const nw::math::VEC2 & curPos)182 ApplyCursorPosition(nw::lyt::Layout* pLayout, const nw::math::VEC2& curPos)
183 {
184     nw::lyt::Pane* pCrossBar = pLayout->GetRootPane()->FindPaneByName("CrossBar", true);
185     if (pCrossBar)
186     {
187         pCrossBar->SetTranslate(curPos);
188     }
189 }
190 
191 }   // namespace
192 
193 /*---------------------------------------------------------------------------*
194   @brief サンプルのメイン関数です。
195  *---------------------------------------------------------------------------*/
196 void
nnMain()197 nnMain()
198 {
199     nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance();
200     demoApp.Initialize();
201 
202     nw::lyt::Initialize(&demoApp.GetAllocator(), &demoApp.GetDeviceAllocator());
203 
204     nw::lyt::Layout* pLayout = new nw::lyt::Layout();
205 
206     // レイアウトのバイナリリソース(アーカイブ)を読み込み。
207     File fileLayout = nw::demo::Utility::LoadFile(
208         &demoApp.GetDeviceAllocator(), NW_DEMO_FILE_PATH(L"layout.arc"), 128);
209 
210     if (fileLayout.empty())
211     {
212         NW_FATAL_ERROR("can not open layout archive.\n");
213     }
214 
215     // バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。
216     nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor;
217     if (!pResAccessor->Attach(fileLayout.begin(), "."))
218     {
219         NW_FATAL_ERROR("can not attach layout archive.\n");
220     }
221 
222     // レイアウトリソースの読み込み
223     {
224         const void* lytRes = pResAccessor->GetResource(0, "bounding.bclyt");
225         NW_NULL_ASSERT(lytRes);
226         pLayout->Build(lytRes, pResAccessor);
227     }
228 
229     const int BoundPaneNum = 6;
230 
231     static const char *const paneNames[] = { "picture_0", "picture_1", "picture_2", "picture_3", "picture_4", "picture_5" };
232 
233     enum
234     {
235         ANIMTYPE_UNSELECT,
236         ANIMTYPE_SELECT,
237 
238         ANIMTYPE_MAX
239     };
240 
241     nw::lyt::AnimTransform* pAnimTrans[ANIMTYPE_MAX];
242 
243     const void* rlanRes = pResAccessor->GetResource(0, "bounding_unselect.bclan");
244     NW_NULL_ASSERT(rlanRes);
245     pAnimTrans[ANIMTYPE_UNSELECT] = pLayout->CreateAnimTransform(rlanRes, pResAccessor);
246     rlanRes = pResAccessor->GetResource(0, "bounding_select.bclan");
247     NW_NULL_ASSERT(rlanRes);
248     pAnimTrans[ANIMTYPE_SELECT] = pLayout->CreateAnimTransform(rlanRes, pResAccessor);
249 
250     for (int i = 0; i < BoundPaneNum; ++i)
251     {
252         // 特定のペイン(とその子供)に対してアニメーションを設定する
253         if (nw::lyt::Pane* pPane = pLayout->GetRootPane()->FindPaneByName(paneNames[i]))
254         {
255             pPane->BindAnimation(pAnimTrans[ANIMTYPE_UNSELECT]);
256             pPane->BindAnimation(pAnimTrans[ANIMTYPE_SELECT]);
257         }
258     }
259 
260     f32 animFrame[ANIMTYPE_MAX];
261     for (int i = 0; i < ANIMTYPE_MAX; ++i)
262     {
263         animFrame[i] = 0.f;
264     }
265 
266     nw::lyt::GraphicsResource graphicsResource;
267     // グローバルなリソースファイルを読み込みます。
268     {
269         graphicsResource.StartSetup();
270         const wchar_t* resourcePath = 0;
271         for (int i = 0;
272              (resourcePath = graphicsResource.GetResourcePath(i)) != NULL;
273              ++i)
274         {
275             File file = nw::demo::Utility::LoadFile(&demoApp.GetAllocator(), resourcePath);
276 
277             if (file.empty())
278             {
279                 NW_FATAL_ERROR("can not read lyt resource file.");
280             }
281 
282             graphicsResource.SetResource(i, file.begin(), file.size(), false);
283         }
284 
285         graphicsResource.FinishSetup();
286     }
287 
288     nw::lyt::DrawInfo drawInfo;
289     drawInfo.SetGraphicsResource(&graphicsResource);
290 #if ! defined(NW_RELEASE)
291     drawInfo.SetDebugDrawMode(true);
292 #endif
293 
294     nw::lyt::Drawer drawer;
295     drawer.Initialize(graphicsResource);
296 
297     nw::lyt::Pane* pHitPane = 0;
298     nw::math::VEC2 curPos(0.f, 0.f);
299 
300     const nw::ut::FloatColor clearColor(0.3f, 0.3f, 0.3f, 1.0f);
301     const f32 clearDepth = 0.0f;
302 
303     bool loop = true;
304     while (loop)
305     {
306         nw::demo::PadFactory::GetPad()->Update();
307 
308         demoApp.SetRenderingTarget(demoApp.DISPLAY0);
309         {
310             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
311 
312             InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
313 
314             SetupCamera(drawInfo, *pLayout);
315 
316             // 子供のアニメーション
317             for (nw::lyt::PaneList::Iterator it = pLayout->GetRootPane()->GetChildList().GetBeginIter(); it != pLayout->GetRootPane()->GetChildList().GetEndIter(); ++it)
318             {
319                 // ヒットしているペインの親ペイン(ピクチャペイン)は選択アニメを有効にする。
320                 // それ以外の親ペインのアニメは非選択アニメを有効にする。
321                 const bool bSelected = pHitPane && &(*it) == pHitPane->GetParent();
322                 it->SetAnimationEnable(pAnimTrans[ANIMTYPE_UNSELECT], ! bSelected);
323                 it->SetAnimationEnable(pAnimTrans[ANIMTYPE_SELECT]  ,   bSelected);
324             }
325 
326             // フレームの更新
327             for (int i = 0; i < ANIMTYPE_MAX; ++i)
328             {
329                 animFrame[i] += 1.0f;
330                 while (animFrame[i] >= pAnimTrans[i]->GetFrameSize())
331                 {
332                     animFrame[i] -= pAnimTrans[i]->GetFrameSize();
333                 }
334                 pAnimTrans[i]->SetFrame(animFrame[i]);
335             }
336 
337             pLayout->Animate();
338             pLayout->CalculateMtx(drawInfo);
339 
340             curPos = GetCursorPosition(pLayout);
341 
342             ApplyCursorPosition(pLayout, curPos);
343 
344             // カーソル位置をレイアウト座標系からビュー座標系に変換。
345             {
346                 nw::math::VEC3 tmp(curPos.x, curPos.y, 0.0f);
347                 nw::math::VEC3Transform(&tmp, &drawInfo.GetViewMtx(), &tmp);
348                 curPos = nw::math::VEC2(tmp.x, tmp.y);
349             }
350 
351             // 行列を利用するため、CalculateMtx()の後に行う
352             pHitPane = nw::lyt::FindHitPane(pLayout, curPos);
353 
354             drawer.DrawBegin(drawInfo);
355             drawer.Draw(pLayout, drawInfo);
356             drawer.DrawEnd(drawInfo);
357         }
358 
359         demoApp.SetRenderingTarget(demoApp.DISPLAY1);
360         {
361             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
362         }
363 
364         demoApp.SwapBuffer(demoApp.DISPLAY_BOTH);
365     }
366 
367     delete pLayout;
368 
369     delete pResAccessor;
370 }
371 
372