ctr_Repair/branches/CardCupForNBD/CardCup/Drawer.cpp
N2614 33771ff869 ロゴ表示が完了してからエラー表示アプレットを呼ぶように
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@468 385bec56-5757-e545-9c3a-d8741f4650f1
2011-11-01 01:31:51 +00:00

692 lines
22 KiB
C++

/*---------------------------------------------------------------------------*
Project: NintendoWare
File: main.cpp
Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. 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.
The content herein is highly confidential and should be handled accordingly.
$Revision$
*---------------------------------------------------------------------------*/
//------------------------------------------------------------------
// デモ: simple
//
// 概要
// レイアウトデータの表示とアニメーションの再生を行うデモです。
// レイアウトデータ、アニメーションデータは次のものが含まれています。
//
// simple.clyt ... レイアウトデータ
// simple.clan ... アニメーションデータ
// - ペインのSRTアニメーション
// - テクスチャパターンアニメーション
// - ビジビリティアニメーション
// - 頂点カラーアニメーション
// - マテリアルカラーアニメーション
// - テクスチャSRTアニメーション
//
//------------------------------------------------------------------
#include <GLES2/gl2.h>
#include <nn.h>
#include <nn/fs.h>
#include <nn/applet.h>
#include <nw/sdk.h>
#include <nw/demo.h>
#include <nw/lyt.h>
#include <nn/erreula.h>
void DrawThreadMain();
namespace
{
const size_t DRAWER_STACK_SIZE = 0x4000;
nn::os::Thread s_DrawerThread;
nn::os::StackBuffer<DRAWER_STACK_SIZE> s_DrawerThreadStack;
// 終了処理をしても良いかどうか
bool s_IsExpectedToFinalize = false;
// エラーコード表示が必要かどうか
bool s_NeedShowErrorCode = false;
// エラーコード
s32 s_ErrorCode;
enum LayoutType
{
LAYOUT_UPPER_LOGO,
LAYOUT_UPPER_FADE,
LAYOUT_MAX
};
enum DrawState
{
DRAW_STATE_START,
DRAW_STATE_FADE_IN,
DRAW_STATE_LOGO_FADE_IN,
DRAW_STATE_LOGO_DRAW,
DRAW_STATE_LOGO_FADE_OUT,
DRAW_STATE_FADE_OUT,
DRAW_STATE_MAX
};
struct LayoutAnimation
{
nw::lyt::Layout* pLayout;
nw::lyt::AnimTransform* pAnimTrans[5];
};
struct LayoutAnimationIndex
{
size_t layoutType;
size_t animIndex;
};
// 3DSロゴレイアウト用アニメーション
const char* s_LogoAnimName[] =
{ "U_Wait_Fade_IN.bclan", "U_Wait_3DS_Rogo.bclan", "U_Wait_Fade.bclan" };
// フェードイン・フェードアウトレイアウト用アニメーション
const char* s_FadeAnimName[] =
{ "Fade_Fade_Out_Black.bclan", "Fade_Fade_IN_Black.bclan", "Fade_Fade_IN.bclan", "Fade_Fade_Out.bclan" };
/*---------------------------------------------------------------------------*
@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 ファイルの読み込みを行うクラスです。
*---------------------------------------------------------------------------*/
class File
{
public:
//!
//! @brief コンストラクタです。
//!
File()
: m_Buffer(NULL), m_Size(0)
{
}
//!
//! @brief ファイルを読み込みます。
//!
//! @param fileName ファイル名です。
//! @param allocator メモリアロケータです。
//!
//! @return 読み込みに成功したら true を返します。
//!
bool Read(const wchar_t* fileName, nw::os::IAllocator& allocator)
{
NW_ASSERT(m_Buffer == NULL);
nn::fs::FileReader fileReader(fileName);
if (fileReader.GetSize() <= 0)
{
return false;
}
this->m_Size = static_cast<u32>(fileReader.GetSize());
this->m_Buffer = static_cast<u8*>(allocator.Alloc(this->m_Size, 128));
if (this->m_Buffer == NULL)
{
this->m_Size = 0;
return false;
}
fileReader.Read(this->m_Buffer, this->m_Size);
fileReader.Finalize();
return true;
}
//!
//! @brief ファイルの読み込まれたバッファを取得します。
//!
//! @return ポインタを返します。
//!
u8* Buffer()
{
return this->m_Buffer;
}
//!
//! @brief 読み込まれたファイルのサイズを取得します。
//!
//! @return 読み込まれたファイルのサイズを返します。
//!
u32 Size()
{
return this->m_Size;
}
private:
u8* m_Buffer;
u32 m_Size;
};
/*---------------------------------------------------------------------------*
@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::MTX44OrthoPivot(
&projMtx,
layoutRect.left, // left
layoutRect.right, // right
layoutRect.bottom, // bottom
layoutRect.top, // top
znear,
zfar,
nw::math::PIVOT_UPSIDE_TO_TOP);
drawInfo.SetProjectionMtx(projMtx);
// モデルビュー行列を設定
// (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向)
nw::math::VEC3 pos(0, 0, 1);
nw::math::VEC3 up(0, 1, 0);
nw::math::VEC3 target(0, 0, 0);
nw::math::MTX34 viewMtx;
nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
drawInfo.SetViewMtx(viewMtx);
}
void
SetupLowerCamera(nw::lyt::DrawInfo& drawInfo, const nw::lyt::Layout& layout)
{
nw::ut::Rect layoutRect = layout.GetLayoutRect();
f32 znear = 0.f;
f32 zfar = 500.f;
layoutRect.left = 80.f;
layoutRect.right = 120.f;
layoutRect.bottom = -120.f;
layoutRect.top = -80.f;
// 射影行列を正射影に設定
// (Layoutデータは横向きなので向きを変換する)
nw::math::MTX44 projMtx;
nw::math::MTX44OrthoPivot(
&projMtx,
layoutRect.left, // left
layoutRect.right, // right
layoutRect.bottom, // bottom
layoutRect.top, // top
znear,
zfar,
nw::math::PIVOT_UPSIDE_TO_TOP);
drawInfo.SetProjectionMtx(projMtx);
// モデルビュー行列を設定
// (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向)
nw::math::VEC3 pos(0, 0, 1);
nw::math::VEC3 up(0, 1, 0);
nw::math::VEC3 target(0, 0, 0);
nw::math::MTX34 viewMtx;
nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
drawInfo.SetViewMtx(viewMtx);
}
void SetupLytResource(LayoutAnimation& layoutAnim, nw::lyt::ArcResourceAccessor* pResAccessor, const char* layoutName,
const char* animName[], size_t animNum)
{
// レイアウトリソースの読み込み
{
const void* lytRes = pResAccessor->GetResource(0, layoutName);
NW_NULL_ASSERT(lytRes);
layoutAnim.pLayout->Build(lytRes, pResAccessor);
}
for (u32 i = 0; i < animNum; i++)
{
// アニメーションリソースの読み込み
const void* lpaRes = pResAccessor->GetResource(0, animName[i]);
NW_NULL_ASSERT(lpaRes);
layoutAnim.pAnimTrans[i] = layoutAnim.pLayout->CreateAnimTransform(lpaRes, pResAccessor);
}
}
void GetNextLayoutAnimationIndex(LayoutAnimationIndex& index, u32 state, nw::demo::SimpleApp::Display display)
{
if (display == nw::demo::SimpleApp::DISPLAY0)
{
switch (state)
{
case DRAW_STATE_START:
{
index.layoutType = LAYOUT_UPPER_FADE;
index.animIndex = 0;
}
break;
case DRAW_STATE_FADE_IN:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 0;
}
break;
case DRAW_STATE_LOGO_FADE_IN:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 1;
}
break;
case DRAW_STATE_LOGO_DRAW:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 2;
}
break;
case DRAW_STATE_LOGO_FADE_OUT:
{
index.layoutType = LAYOUT_UPPER_FADE;
index.animIndex = 1;
}
break;
}
}
else if(display == nw::demo::SimpleApp::DISPLAY1)
{
switch (state)
{
case DRAW_STATE_START:
{
index.layoutType = LAYOUT_UPPER_FADE;
index.animIndex = 0;
}
break;
case DRAW_STATE_FADE_IN:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 0;
}
break;
case DRAW_STATE_LOGO_FADE_IN:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 1;
}
break;
case DRAW_STATE_LOGO_DRAW:
{
index.layoutType = LAYOUT_UPPER_LOGO;
index.animIndex = 2;
}
break;
case DRAW_STATE_LOGO_FADE_OUT:
{
index.layoutType = LAYOUT_UPPER_FADE;
index.animIndex = 1;
}
break;
}
}
}
} // namespace {anonymous}
void StartDrawerThread()
{
s_DrawerThread.Start(DrawThreadMain, s_DrawerThreadStack);
}
void FinalizeDrawerThread()
{
if(s_DrawerThread.IsAlive())
{
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(0));
}
s_DrawerThread.Join();
s_DrawerThread.Finalize();
}
void RestoreGraphics()
{
// GPU レジスタ設定の復帰
nngxUpdateState(NN_GX_STATE_ALL);
nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
}
void NotifyFailed(s32 error)
{
s_ErrorCode = error;
s_NeedShowErrorCode = true;
}
void NotifyFinished()
{
s_IsExpectedToFinalize = true;
s_NeedShowErrorCode = false;
}
void ShowError()
{
NN_LOG("Show Error\n");
nn::applet::AppletWakeupState wstate;
nn::erreula::Parameter ere_param; // エラーEULAの設定構造体
// 設定構造体初期化
nn::erreula::InitializeConfig(&ere_param.config);
ere_param.config.errorType = nn::erreula::ERROR_TYPE_ERROR_CODE;
ere_param.config.errorCode = s_ErrorCode;
ere_param.config.upperScreenFlag = nn::erreula::UPPER_SCREEN_NORMAL;
ere_param.config.homeButton = true;
ere_param.config.softwareReset = false;
ere_param.config.appJump = false;
nn::erreula::StartErrEulaApplet(&wstate, &ere_param);
// GPU レジスタ設定の復帰
RestoreGraphics();
}
/*---------------------------------------------------------------------------*
@brief サンプルのメイン関数です。
*---------------------------------------------------------------------------*/
void
DrawThreadMain()
{
// アプリケーションの初期化。
nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance();
demoApp.Initialize();
// レイアウトライブラリの初期化。
nw::lyt::Initialize(&demoApp.GetAllocator(), &demoApp.GetDeviceAllocator());
// レイアウトのバイナリリソース(アーカイブ)を読み込み。
File fileLayout;
if (!fileLayout.Read(NW_DEMO_FILE_PATH(L"All.arc"), demoApp.GetDeviceAllocator()))
{
NW_FATAL_ERROR("can not open layout archive.\n");
}
// バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。
nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor;
if (!pResAccessor->Attach(fileLayout.Buffer(), "."))
{
NW_FATAL_ERROR("can not attach layout archive.\n");
}
LayoutAnimation layoutAnim[LAYOUT_MAX];
// 上画面ロゴ
{
layoutAnim[LAYOUT_UPPER_LOGO].pLayout = new nw::lyt::Layout();
SetupLytResource(layoutAnim[LAYOUT_UPPER_LOGO], pResAccessor, "U_Wait.bclyt", s_LogoAnimName,
sizeof(s_LogoAnimName) / sizeof(s_LogoAnimName[0]));
}
// フェードイン・フェードアウト
{
layoutAnim[LAYOUT_UPPER_FADE].pLayout = new nw::lyt::Layout();
SetupLytResource(layoutAnim[LAYOUT_UPPER_FADE], pResAccessor, "Fade.bclyt", s_FadeAnimName,
sizeof(s_FadeAnimName) / sizeof(s_FadeAnimName[0]));
}
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;
if (!file.Read(resourcePath, demoApp.GetAllocator()))
{
NW_FATAL_ERROR("can not read lyt resource file.");
}
graphicsResource.SetResource(i, file.Buffer(), file.Size());
}
graphicsResource.FinishSetup();
}
nw::lyt::DrawInfo drawInfo;
drawInfo.SetGraphicsResource(&graphicsResource);
nw::lyt::Drawer drawer;
drawer.Initialize(graphicsResource);
const nw::ut::FloatColor clearColor(0.0f, 0.0f, 0.0f, 1.0f);
const f32 clearDepth = 0.0f;
bool mainloop = true;
nn::hid::PadReader padReader;
nn::hid::PadStatus padStatus;
nw::lyt::Layout* pUpperLayout;
nw::lyt::Layout* pLowerLayout;
u32 drawState = DRAW_STATE_START;
LayoutAnimation* pUpperLayoutAnim;
LayoutAnimation* pLowerLayoutAnim;
LayoutAnimationIndex upperLayoutAnimIndex;
LayoutAnimationIndex lowerLayoutAnimIndex;
GetNextLayoutAnimationIndex(upperLayoutAnimIndex, drawState, demoApp.DISPLAY0);
GetNextLayoutAnimationIndex(lowerLayoutAnimIndex, drawState, demoApp.DISPLAY1);
pUpperLayoutAnim = &layoutAnim[upperLayoutAnimIndex.layoutType];
pLowerLayoutAnim = &layoutAnim[lowerLayoutAnimIndex.layoutType];
// ロゴ表示中の待ちフレーム数をカウント
u32 waitCounter = 0;
while (mainloop)
{
padReader.ReadLatest(&padStatus);
// 上画面描画
demoApp.SetRenderingTarget(demoApp.DISPLAY0);
pUpperLayout = pUpperLayoutAnim->pLayout;
pUpperLayout->UnbindAllAnimation();
pUpperLayout->BindAnimation(pUpperLayoutAnim->pAnimTrans[upperLayoutAnimIndex.animIndex]);
{
demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
SetupCamera(drawInfo, *pUpperLayout);
InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
pUpperLayout->Animate();
pUpperLayout->CalculateMtx(drawInfo);
drawer.DrawBegin(drawInfo);
drawer.Draw(pUpperLayout, drawInfo);
drawer.DrawEnd(drawInfo);
}
// 下画面描画
demoApp.SetRenderingTarget(demoApp.DISPLAY1);
if (drawState == DRAW_STATE_LOGO_DRAW)
{
const nw::ut::FloatColor white(1.0f, 1.0f, 1.0f, 1.0f);
demoApp.GetFrameBufferObject().ClearBuffer(white, clearDepth);
waitCounter++;
}
else
{
pLowerLayout = pLowerLayoutAnim->pLayout;
pLowerLayout->UnbindAllAnimation();
pLowerLayout->BindAnimation(pLowerLayoutAnim->pAnimTrans[lowerLayoutAnimIndex.animIndex]);
{
demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
if(DRAW_STATE_LOGO_FADE_IN <= drawState && drawState <= DRAW_STATE_LOGO_FADE_OUT)
{
SetupLowerCamera(drawInfo, *pLowerLayout);
}
else
{
SetupCamera(drawInfo, *pLowerLayout);
}
InitDraw(demoApp.DISPLAY1_WIDTH, demoApp.DISPLAY1_HEIGHT);
pLowerLayout->Animate();
pLowerLayout->CalculateMtx(drawInfo);
drawer.DrawBegin(drawInfo);
drawer.Draw(pLowerLayout, drawInfo);
drawer.DrawEnd(drawInfo);
}
}
// フレームの更新
f32 step = 1.0f;
if (animFrame < pUpperLayoutAnim->pAnimTrans[upperLayoutAnimIndex.animIndex]->GetFrameMax() &&
(drawState == DRAW_STATE_LOGO_FADE_OUT && animFrame < 10.0f))
{
animFrame = nw::ut::Min(pUpperLayoutAnim->pAnimTrans[upperLayoutAnimIndex.animIndex]->GetFrameMax(),
animFrame + step);
}
// 1アニメーション終了
else
{
if (drawState < DRAW_STATE_FADE_OUT)
{
// 次のアニメーションへ遷移
GetNextLayoutAnimationIndex(upperLayoutAnimIndex, drawState, demoApp.DISPLAY0);
GetNextLayoutAnimationIndex(lowerLayoutAnimIndex, drawState, demoApp.DISPLAY1);
pUpperLayoutAnim = &layoutAnim[upperLayoutAnimIndex.layoutType];
pLowerLayoutAnim = &layoutAnim[lowerLayoutAnimIndex.layoutType];
// 終了処理を依頼されたときのみロゴフェードアウト移行に進む
if (drawState < DRAW_STATE_LOGO_DRAW || s_IsExpectedToFinalize)
{
drawState++;
NN_LOG("State = %d\n", drawState);
NN_LOG(
"Upper: layout: %d, anim: %d\n", upperLayoutAnimIndex.layoutType, upperLayoutAnimIndex.animIndex);
NN_LOG(
"Lower: layout: %d, anim: %d\n\n", lowerLayoutAnimIndex.layoutType, lowerLayoutAnimIndex.animIndex);
}
if (drawState == DRAW_STATE_LOGO_FADE_IN)
{
animFrame = 11.f;
}
else
{
animFrame = 0;
}
}
else
{
// 終了処理へ
break;
}
}
pUpperLayoutAnim->pAnimTrans[upperLayoutAnimIndex.animIndex]->SetFrame(animFrame);
pLowerLayoutAnim->pAnimTrans[lowerLayoutAnimIndex.animIndex]->SetFrame(animFrame);
demoApp.SwapBuffer(demoApp.DISPLAY_BOTH);
// ロゴが表示されてからエラー表示を行う
if(s_NeedShowErrorCode && DRAW_STATE_LOGO_DRAW == drawState && 1 < waitCounter)
{
ShowError();
}
}
delete pResAccessor;
demoApp.GetDeviceAllocator().Free(fileLayout.Buffer());
}