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