/*---------------------------------------------------------------------------* 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 $ *---------------------------------------------------------------------------*/ //------------------------------------------------------------------ // デモ: animShare // // 概要 // アニメーション共有のデモです。 // // animShare.clan ファイルでは、ペイン「Picture_00」にのみアニメーションが // 設定されており、このアニメーションをグループ「Group_00」に登録されている // 各ペインで共有するようにアニメーション共有設定が行われています。 // グループ「Group_00」には、全てのPictureペイン(Picture_00 ~ Picture_11)が // 登録されています。 // // 操作 // 十字ボタンの操作でクロスラインが移動します。 // クロスラインのクロスしている部分がペイン上にくると、 // そのペインが拡大するアニメーションが動作します。 // 拡大しているときに、クロスしている部分が離れると // しだいに縮小して元の大きさに戻ります。 // //------------------------------------------------------------------ #include #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 drawInfo 描画情報です。 @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 layout レイアウトへの参照です。 @return Layoutの座標系におけるカーソル位置を返します。 *---------------------------------------------------------------------------*/ nw::math::VEC2 GetCursorPosition(nw::lyt::Layout& layout) { const nw::ut::Rect& layoutRect = layout.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 layout レイアウトへの参照です。 @param curPos レイアウトの座標系におけるカーソルの位置です。 *---------------------------------------------------------------------------*/ void ApplyCursorPosition(nw::lyt::Layout& layout, const nw::math::VEC2& curPos) { nw::lyt::Pane* pCrossBar = layout.GetRootPane()->FindPaneByName("CrossBar", true); if (pCrossBar) { pCrossBar->SetTranslate(curPos); } } /*---------------------------------------------------------------------------* @brief AnimationLinkを検索します。 @details 指定したアニメーションリソースをペインやマテリアルにバインドしている nw::lyt::AnimationLink を検索し、最初に見つかったものを返します。 指定されたペインの子孫を含めて検索します。 @param pPane 検索対象のルートとなるペインです。 @param animRes アニメーションリソースです。 @return 見つかった場合は、nw::lyt::AnimationLink のポインタを返します。 見つからなかった場合は、NULL を返します。 *---------------------------------------------------------------------------*/ nw::lyt::AnimationLink* FindLayoutAnimationLink( nw::lyt::Pane* pPane, const nw::lyt::AnimResource& animRes ) { // ペインアニメーションの検索 if (nw::lyt::AnimationLink *const pAnimLink = pPane->FindAnimationLinkSelf(animRes)) { return pAnimLink; } // マテリアルアニメーションの設定 const u8 materialNum = pPane->GetMaterialNum(); for (u8 i = 0; i < materialNum; ++i) { if (nw::lyt::AnimationLink *const pAnimLink = pPane->GetMaterial(i)->FindAnimationLink(animRes)) { return pAnimLink; } } // 再帰的に検索します。 for (nw::lyt::PaneList::Iterator it = pPane->GetChildList().GetBeginIter(); it != pPane->GetChildList().GetEndIter(); ++it) { if (nw::lyt::AnimationLink* pAnimLink = FindLayoutAnimationLink(&(*it), animRes)) { return pAnimLink; } } return NULL; } /*---------------------------------------------------------------------------* @brief アニメーションリソースのフレーム値を設定します。 @details 指定したアニメーションリソースの現在のフレーム値を全て同じに設定します。 指定されたペインの子孫を含めて行います。 @param pPane 対象となるペインのルートとなるペインです。 @param animRes アニメーションリソースです。 @param frame 設定するフレーム値です。 *---------------------------------------------------------------------------*/ void SetAnimationFrame( nw::lyt::Pane* pPane, const nw::lyt::AnimResource& animRes, f32 frame ) { // ペインアニメーションの設定 if (nw::lyt::AnimationLink *const pAnimLink = pPane->FindAnimationLinkSelf(animRes)) { pAnimLink->GetAnimTransform()->SetFrame(frame); } // マテリアルアニメーションの設定 const u8 materialNum = pPane->GetMaterialNum(); for (u8 i = 0; i < materialNum; ++i) { if (nw::lyt::AnimationLink *const pAnimLink = pPane->GetMaterial(i)->FindAnimationLink(animRes)) { pAnimLink->GetAnimTransform()->SetFrame(frame); } } // 再帰的に行います。 for (nw::lyt::PaneList::Iterator it = pPane->GetChildList().GetBeginIter(); it != pPane->GetChildList().GetEndIter(); ++it) { SetAnimationFrame(&(*it), animRes, frame); } } /*---------------------------------------------------------------------------* @brief アニメーションの状態を更新します。 @details 十字カーソルでポイントされているかどうかでアニメーションの状態を更新します。 @param pPane アニメーションを更新するペイン階層のルートとなるペインです。 @param animRes アニメーションリソースオブジェクトです。 @param bContain 十字カーソルでポイントされていたら真を指定します。 *---------------------------------------------------------------------------*/ void UpdateAnimationFrame( nw::lyt::Pane* pPane, const nw::lyt::AnimResource& animRes, bool bContain ) { // 指定した アニメーションリソースをリンクする nw::lyt::AnimationLink を探します。 // 最初に見つかったものが返ります。 nw::lyt::AnimationLink *const pAnimationLink = FindLayoutAnimationLink(pPane, animRes); if (! pAnimationLink) { return; } // nw::lyt::AnimationLink から nw::lyt::AnimTransform 取得して、 // 現在のフレーム値と最大フレームを取得します。 nw::lyt::AnimTransform *const pAnimTrans = pAnimationLink->GetAnimTransform(); f32 animFrame = pAnimTrans->GetFrame(); // 現在のフレーム const f32 animFrameMax = static_cast(pAnimTrans->GetFrameSize() - 1); // フレームの最大値 if (bContain) { // ポイントされている場合は、 // アニメーションのフレーム値を前に進めます。 const f32 step = 2.f; if (animFrame < animFrameMax) { animFrame = nw::ut::Min(animFrameMax, animFrame + step); // pPane以下の全てのペイン、マテリアルのアニメーションフレームを同じ値に設定します。 SetAnimationFrame(pPane, animRes, animFrame); } } else { // ポイントされていない場合は、 // アニメーションのフレーム値を戻していきます。 const f32 step = 1.f; if (animFrame > 0.f) // 現在のフレームが0でない場合 { animFrame = nw::ut::Max(0.f, animFrame - step); // pPane以下の全てのペイン、マテリアルのアニメーションフレームを同じ値に設定します。 SetAnimationFrame(pPane, animRes, animFrame); } } } /*---------------------------------------------------------------------------* @brief 各ペインの状態を更新します。 @param pos カーソル位置です。 @param pGroup 更新する対象のペインが登録されているグループです。 @param animRes アニメーションリソースオブジェクトです。 *---------------------------------------------------------------------------*/ void UpdatePane( const nw::math::VEC2& pos, nw::lyt::Group* pGroup, const nw::lyt::AnimResource& animRes ) { // グループに登録されているペインごとの処理 nw::lyt::PaneLinkList& paneList = pGroup->GetPaneList(); for (nw::lyt::PaneLinkList::Iterator it = paneList.GetBeginIter(); it != paneList.GetEndIter(); ++it) { // グループに登録されているペイン nw::lyt::Pane *const pPane = it->target; // 十字カーソルでポイントされているかどうかでアニメーションの状態を更新します。 const bool bContain = nw::lyt::IsContain(pPane, pos); UpdateAnimationFrame( pPane, animRes, bContain); } } } // 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, "animShare.bclyt"); NW_NULL_ASSERT(lytRes); pLayout->Build(lytRes, pResAccessor); } nw::lyt::AnimResource animRes; nw::lyt::AnimTransform* pAnimTrans = 0; // アニメーションリソースの読み込み { const void* lpaRes = pResAccessor->GetResource(0, "animShare_focus.bclan"); NW_NULL_ASSERT(lpaRes); animRes.Set(lpaRes); } // アニメーション共有設定、アニメーション区間タグの関連グループを // 考慮したアニメーションのバインドを行います。 pLayout->BindAnimationAuto(animRes, pResAccessor); // Layout::BindAnimationAuto() でバインドしたアニメーションは無効になっています。 // このサンプルの場合は個別にアニメーションの有効/無効を // 切り替える必要が無いため、全体でアニメーションを有効にします。 pLayout->GetRootPane()->SetAnimationEnable(animRes, true/*bEnable*/, true/*bRecursive*/); // ピクチャペインが登録されているグループのポインタを取得します。 nw::lyt::Group *const pGroup_00 = pLayout->GetGroupContainer()->FindGroupByName("Group_00"); f32 animFrame = 0; 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 open lyt resource file."); } graphicsResource.SetResource(i, file.begin(), file.size(), false); } graphicsResource.FinishSetup(); } nw::lyt::DrawInfo drawInfo; drawInfo.SetGraphicsResource(&graphicsResource); nw::math::VEC2 curPos(0.f, 0.f); nw::lyt::Drawer drawer; drawer.Initialize(graphicsResource); 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); pLayout->CalculateMtx(drawInfo); drawer.DrawBegin(drawInfo); drawer.Draw(pLayout, drawInfo); drawer.DrawEnd(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); } // カーソルに応じて、ペインの状態を更新します。 UpdatePane(curPos, pGroup_00, animRes); pLayout->Animate(); } demoApp.SetRenderingTarget(demoApp.DISPLAY1); { demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth); } demoApp.SwapBuffer(demoApp.DISPLAY_BOTH); } delete pLayout; delete pResAccessor; }