/*---------------------------------------------------------------------------* Project: NintendoWare File: main.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 23867 $ *---------------------------------------------------------------------------*/ //------------------------------------------------------------------ // デモ: bounding // // 概要 // boudingペインによるヒットチェックを行うデモです。 // // 操作 // 十字ボタンの操作でクロスラインが移動します。 // クロスラインのクロスしている部分をペインに移動させると、 // そのペインのみ異なるアニメーションをします。 // //------------------------------------------------------------------ #include #include namespace { typedef nw::ut::MoveArray File; /*---------------------------------------------------------------------------* @brief 描画の初期設定を行います。 @param width 画面の幅。 @param height 画面の高さ。 *---------------------------------------------------------------------------*/ void InitDraw(int width, int height) { // カラーバッファ情報 // LCDの向きに合わせて、幅と高さを入れ替えています。 const nw::font::ColorBufferInfo colBufInfo = { height, width, PICA_DATA_DEPTH24_STENCIL8_EXT }; const u32 commands[] = { // ビューポートの設定 NW_FONT_CMD_SET_VIEWPORT(0, 0, colBufInfo.width, colBufInfo.height), // シザー処理を無効 NW_FONT_CMD_SET_DISABLE_SCISSOR(colBufInfo), // wバッファの無効化 // デプスレンジの設定 // ポリゴンオフセットの無効化 NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET( 0.0f, // wScale : 0.0 でWバッファが無効 0.0f, // depth range near 1.0f, // depth range far 0, // polygon offset units : 0.0 で ポリゴンオフセットが無効 colBufInfo), }; nngxAdd3DCommand(commands, sizeof(commands), true); static const u32 constCommands[] = { // カリングを無効 NW_FONT_CMD_SET_CULL_FACE(NW_FONT_CMD_CULL_FACE_DISABLE), // ステンシルテストを無効 NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(), // デプステストを無効 // カラーバッファの全ての成分を書き込み可 NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( false, // isDepthTestEnabled 0, // depthFunc true, // depthMask true, // red true, // green true, // blue true), // alpha // アーリーデプステストを無効 NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false), // フレームバッファアクセス制御 NW_FONT_CMD_SET_FBACCESS( true, // colorRead true, // colorWrite false, // depthRead false, // depthWrite false, // stencilRead false), // stencilWrite }; nngxAdd3DCommand(constCommands, sizeof(constCommands), true); } /*---------------------------------------------------------------------------* @brief モデルビュー行列と射影行列を設定します。 @param pDrawInfo 描画情報です。 @param layout レイアウトです。 *---------------------------------------------------------------------------*/ void SetupCamera(nw::lyt::DrawInfo& drawInfo, const nw::lyt::Layout& layout) { nw::ut::Rect layoutRect = layout.GetLayoutRect(); f32 znear = 0.f; f32 zfar = 500.f; // 射影行列を正射影に設定 // (Layoutデータは横向きなので向きを変換する) nw::math::MTX44 projMtx; nw::math::MTX44Ortho( &projMtx, layoutRect.bottom, // left layoutRect.top, // right -layoutRect.right, // bottom -layoutRect.left, // top znear, zfar); drawInfo.SetProjectionMtx(projMtx); // モデルビュー行列を設定 // (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向) nw::math::VEC3 pos(0, 0, 1); nw::math::VEC3 up(-1, 0, 0); nw::math::VEC3 target(0, 0, 0); nw::math::MTX34 viewMtx; nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target); drawInfo.SetViewMtx(viewMtx); } /*---------------------------------------------------------------------------* @brief カーソルの位置をレイアウトの座標系で取得します。 @param pLayout レイアウトです。 @return カーソル位置を返します。 *---------------------------------------------------------------------------*/ const nw::math::VEC2 GetCursorPosition(nw::lyt::Layout* pLayout) { const nw::ut::Rect& layoutRect = pLayout->GetLayoutRect(); const nw::math::VEC2 center( (layoutRect.left + layoutRect.right ) / 2, (layoutRect.top + layoutRect.bottom) / 2 ); nw::math::VEC2 curPos; // カーソルの座標系をレイアウトの座標系に変換します。 const nw::ut::Rect cursorRect(-0.5, 0.5, 0.5, -0.5); // LTRB nw::demo::Pad& pad = *nw::demo::PadFactory::GetPad(); const nw::math::VEC2 stick = pad.GetAnalogStick(); curPos.x = center.x + stick.x / (cursorRect.right - cursorRect.left ) * (layoutRect.right - layoutRect.left ); curPos.y = center.y + stick.y / (cursorRect.top - cursorRect.bottom) * (layoutRect.top - layoutRect.bottom); // NW_LOG("curPos %f, %f\n", curPos.x, curPos.y); return curPos; } /*---------------------------------------------------------------------------* @brief カーソルの位置をレイアウトに反映します。 @param pLayout レイアウトです。 @param curPos レイアウトの座標系におけるカーソルの位置です。 *---------------------------------------------------------------------------*/ void ApplyCursorPosition(nw::lyt::Layout* pLayout, const nw::math::VEC2& curPos) { nw::lyt::Pane* pCrossBar = pLayout->GetRootPane()->FindPaneByName("CrossBar", true); if (pCrossBar) { pCrossBar->SetTranslate(curPos); } } } // namespace /*---------------------------------------------------------------------------* @brief サンプルのメイン関数です。 *---------------------------------------------------------------------------*/ void nnMain() { nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance(); demoApp.Initialize(); nw::lyt::Initialize(&demoApp.GetAllocator(), &demoApp.GetDeviceAllocator()); nw::lyt::Layout* pLayout = new nw::lyt::Layout(); // レイアウトのバイナリリソース(アーカイブ)を読み込み。 File fileLayout = nw::demo::Utility::LoadFile( &demoApp.GetDeviceAllocator(), NW_DEMO_FILE_PATH(L"layout.arc"), 128); if (fileLayout.empty()) { NW_FATAL_ERROR("can not open layout archive.\n"); } // バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。 nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor; if (!pResAccessor->Attach(fileLayout.begin(), ".")) { NW_FATAL_ERROR("can not attach layout archive.\n"); } // レイアウトリソースの読み込み { const void* lytRes = pResAccessor->GetResource(0, "bounding.bclyt"); NW_NULL_ASSERT(lytRes); pLayout->Build(lytRes, pResAccessor); } const int BoundPaneNum = 6; static const char *const paneNames[] = { "picture_0", "picture_1", "picture_2", "picture_3", "picture_4", "picture_5" }; enum { ANIMTYPE_UNSELECT, ANIMTYPE_SELECT, ANIMTYPE_MAX }; nw::lyt::AnimTransform* pAnimTrans[ANIMTYPE_MAX]; const void* rlanRes = pResAccessor->GetResource(0, "bounding_unselect.bclan"); NW_NULL_ASSERT(rlanRes); pAnimTrans[ANIMTYPE_UNSELECT] = pLayout->CreateAnimTransform(rlanRes, pResAccessor); rlanRes = pResAccessor->GetResource(0, "bounding_select.bclan"); NW_NULL_ASSERT(rlanRes); pAnimTrans[ANIMTYPE_SELECT] = pLayout->CreateAnimTransform(rlanRes, pResAccessor); for (int i = 0; i < BoundPaneNum; ++i) { // 特定のペイン(とその子供)に対してアニメーションを設定する if (nw::lyt::Pane* pPane = pLayout->GetRootPane()->FindPaneByName(paneNames[i])) { pPane->BindAnimation(pAnimTrans[ANIMTYPE_UNSELECT]); pPane->BindAnimation(pAnimTrans[ANIMTYPE_SELECT]); } } f32 animFrame[ANIMTYPE_MAX]; for (int i = 0; i < ANIMTYPE_MAX; ++i) { animFrame[i] = 0.f; } nw::lyt::GraphicsResource graphicsResource; // グローバルなリソースファイルを読み込みます。 { graphicsResource.StartSetup(); const wchar_t* resourcePath = 0; for (int i = 0; (resourcePath = graphicsResource.GetResourcePath(i)) != NULL; ++i) { File file = nw::demo::Utility::LoadFile(&demoApp.GetAllocator(), resourcePath); if (file.empty()) { NW_FATAL_ERROR("can not read lyt resource file."); } graphicsResource.SetResource(i, file.begin(), file.size(), false); } graphicsResource.FinishSetup(); } nw::lyt::DrawInfo drawInfo; drawInfo.SetGraphicsResource(&graphicsResource); #if ! defined(NW_RELEASE) drawInfo.SetDebugDrawMode(true); #endif nw::lyt::Drawer drawer; drawer.Initialize(graphicsResource); nw::lyt::Pane* pHitPane = 0; nw::math::VEC2 curPos(0.f, 0.f); const nw::ut::FloatColor clearColor(0.3f, 0.3f, 0.3f, 1.0f); const f32 clearDepth = 0.0f; bool loop = true; while (loop) { nw::demo::PadFactory::GetPad()->Update(); demoApp.SetRenderingTarget(demoApp.DISPLAY0); { demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth); InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT); SetupCamera(drawInfo, *pLayout); // 子供のアニメーション for (nw::lyt::PaneList::Iterator it = pLayout->GetRootPane()->GetChildList().GetBeginIter(); it != pLayout->GetRootPane()->GetChildList().GetEndIter(); ++it) { // ヒットしているペインの親ペイン(ピクチャペイン)は選択アニメを有効にする。 // それ以外の親ペインのアニメは非選択アニメを有効にする。 const bool bSelected = pHitPane && &(*it) == pHitPane->GetParent(); it->SetAnimationEnable(pAnimTrans[ANIMTYPE_UNSELECT], ! bSelected); it->SetAnimationEnable(pAnimTrans[ANIMTYPE_SELECT] , bSelected); } // フレームの更新 for (int i = 0; i < ANIMTYPE_MAX; ++i) { animFrame[i] += 1.0f; while (animFrame[i] >= pAnimTrans[i]->GetFrameSize()) { animFrame[i] -= pAnimTrans[i]->GetFrameSize(); } pAnimTrans[i]->SetFrame(animFrame[i]); } pLayout->Animate(); pLayout->CalculateMtx(drawInfo); curPos = GetCursorPosition(pLayout); ApplyCursorPosition(pLayout, curPos); // カーソル位置をレイアウト座標系からビュー座標系に変換。 { nw::math::VEC3 tmp(curPos.x, curPos.y, 0.0f); nw::math::VEC3Transform(&tmp, &drawInfo.GetViewMtx(), &tmp); curPos = nw::math::VEC2(tmp.x, tmp.y); } // 行列を利用するため、CalculateMtx()の後に行う pHitPane = nw::lyt::FindHitPane(pLayout, curPos); drawer.DrawBegin(drawInfo); drawer.Draw(pLayout, drawInfo); drawer.DrawEnd(drawInfo); } demoApp.SetRenderingTarget(demoApp.DISPLAY1); { demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth); } demoApp.SwapBuffer(demoApp.DISPLAY_BOTH); } delete pLayout; delete pResAccessor; }