/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ParticleModel.h 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: 31829 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_PARTICLEMODEL_H_ #define NW_GFX_PARTICLEMODEL_H_ #include #include #include #include #include namespace nw { namespace gfx { class ParticleSet; //--------------------------------------------------------------------------- //! @brief ParticleSetが空か調べる関数オブジェクトです。 //--------------------------------------------------------------------------- class ParticleSetsAreEmpty { public: //! @brief コンストラクタです //! @param[in] result 結果を返すポインタです。 ParticleSetsAreEmpty(bool* result) { NW_NULL_ASSERT(result); m_Result = result; *m_Result = true; } //! @brief ParticleSetが空か調べるオペレータです //! @param[in] particleSet 調べるParticleSetです。 void operator()(const ParticleSet* particleSet); private: bool* m_Result; }; //--------------------------------------------------------------------------- //! @brief ParticleSetのデバッグ用のヒント情報をリセットする関数オブジェクトです。 //--------------------------------------------------------------------------- class ParticleSetsResetDebugHint { public: //! @brief ParticleSetのデバッグ用のヒント情報をリセットするオペレータです //! @param[in] particleSet 調べるParticleSetです。 void operator()(ParticleSet* particleSet); }; //--------------------------------------------------------------------------- //! @brief ParticleSetを空にする関数オブジェクトです。 //--------------------------------------------------------------------------- class ParticleSetsClear { public: //! @brief コンストラクタです ParticleSetsClear() {} //! @brief ParticleSetを空にするオペレータです //! @param[in] particleSet 空にするParticleSetです。 void operator()(ParticleSet* particleSet); }; //--------------------------------------------------------------------------- //! @brief パーティクル用のモデルのクラスです。 //--------------------------------------------------------------------------- class ParticleModel : public Model { private: NW_DISALLOW_COPY_AND_ASSIGN(ParticleModel); public: NW_UT_RUNTIME_TYPEINFO; //! @brief 設定内容です。 struct Description : public Model::Description { //! @brief コンストラクタです。 Description() : particleSetCount(0) {} uint particleSetCount; }; //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief モデルを生成します。 //! //! @param[in] parent 親のノードです。 //! @param[in] resource リソースです。 //! @param[in] modelDescription 設定内容です。 //! @param[in] mainAllocator メインメモリのアロケータです。 //! @param[in] deviceAllocator デバイスメモリのアロケータです。 //! //! @return 生成されたモデルです。 //! static ParticleModel* Create( SceneNode* parent, ResSceneObject resource, const ParticleModel::Description& modelDescription, os::IAllocator* mainAllocator, os::IAllocator* deviceAllocator); //! @brief 生成時に必要なメモリサイズを取得します。 //! @param[in] resource リソースです。 //! @param[in] description 設定内容です。 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 //! @return 必要なメモリサイズです。 static size_t GetMemorySize( ResParticleModel resource, const ParticleModel::Description& modelDescription, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size, resource, modelDescription); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeInternal( os::MemorySizeCalculator* pSize, ResParticleModel resource, const ParticleModel::Description& modelDescription); //! @brief 生成時に必要なデバイスメモリサイズを取得します。 //! @param[in] resource リソースです。 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 //! @return 必要なデバイスメモリサイズです。 static size_t GetDeviceMemorySize( ResParticleModel resource, const ParticleModel::Description& modelDescription, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetDeviceMemorySizeInternal(&size, resource, modelDescription); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetDeviceMemorySizeInternal( os::MemorySizeCalculator* pSize, ResParticleModel resource, const ParticleModel::Description& modelDescription); //@} //---------------------------------------- //! @name 更新 //@{ //! @brief ビジターを受け付けます。 //! //! @param[in] visitor ビジターです。 //! virtual void Accept(ISceneVisitor* visitor); //! フレームを更新します。 void UpdateParticleFrame() { m_ParticleAnimFrameController.UpdateFrame(); } //! @brief ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。 //! //! @tparam TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。 //! @param[in] function 適応する関数(オブジェクト)です。 //! template void ForeachParticleSet(TFunction function) { for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i) { ParticleSet* particleSet = this->GetParticleSets(i); function(particleSet); } } //! @brief ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。 //! //! @tparam TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。 //! @param[in] function 適応する関数(オブジェクト)です。 //! template void ForeachConstParticleSet(TFunction function) const { for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i) { const ParticleSet* particleSet = this->GetParticleSets(i); function(particleSet); } } //@} //---------------------------------------- //! @name リソース //@{ //! @brief リソースを取得します。 //! @return パーティクルモデルのリソースを返します。 ResParticleModel GetResModel() { return ResDynamicCast(this->GetResSceneObject()); } //! @brief リソースを取得します。 //! @return パーティクルモデルのリソースを返します。 const ResParticleModel GetResModel() const { return ResDynamicCast(this->GetResSceneObject()); } //@} //---------------------------------------- //! @name 取得/設定 //@{ //! @brief ParticleSetを追加します。 //! //! @param node 追加するパーティクルセットです。 //! @return 追加できた場合trueを返します。 bool AttachParticleSet(ParticleSet* node) { if (m_ParticleSetCount >= this->m_ParticleSets.size()) return false; this->m_ParticleSets[m_ParticleSetCount] = node; ++m_ParticleSetCount; return true; } //! @brief パーティクルセットの数を取得します。 //! @return パーティクルセットの数を返します。 u32 GetParticleSetsCount() const { return m_ParticleSetCount; } //! @brief パーティクルセットを取得します。 //! //! @param[in] index インデックスです。 //! @return パーティクルセットを返します。 ParticleSet* GetParticleSets(int index) { NW_ASSERT(index >= 0 && index < m_ParticleSetCount); return this->m_ParticleSets[index]; } //! @brief パーティクルセットを取得します。 //! //! @param[in] index インデックスです。 //! @return パーティクルセットを返します。 const ParticleSet* GetParticleSets(int index) const { NW_ASSERT(index >= 0 && index < m_ParticleSetCount); return this->m_ParticleSets[index]; } //! @brief ParticleShapeを追加します。 //! @param[in] node 追加するParticleShapeです。 //! @return 追加できた場合trueを返します。 bool AttachParticleShape(ParticleShape* node) { if (m_ParticleShapeCount >= this->m_ParticleShapes.size()) return false; this->m_ParticleShapes[m_ParticleSetCount] = node; ++m_ParticleShapeCount; return true; } //! @brief パーティクルシェイプの数を取得します。 //! @return パーティクルシェイプの数を返します。 u32 GetParticleShapesCount() const { return m_ParticleShapeCount; } //! @brief ParticleShapeを取得します。 //! //! @param[in] index インデックスです。 //! @return ParticleShapeを返します。 ParticleShape* GetParticleShapes(int index) { NW_ASSERT(index >= 0 && index < m_ParticleShapeCount); return this->m_ParticleShapes[index]; } //! @brief ParticleShapeを取得します。 //! //! @param[in] index インデックスです。 //! @return ParticleShapeを返します。 const ParticleShape* GetParticleShapes(int index) const { NW_ASSERT(index >= 0 && index < m_ParticleShapeCount); return this->m_ParticleShapes[index]; } //! @brief アニメーションフレーム制御情報を取得します。 //! @return アニメーションフレームコントローラを返します。 anim::AnimFrameController& ParticleAnimFrameController() { return m_ParticleAnimFrameController; } //! @brief アニメーションフレーム制御情報を取得します。 //! @return アニメーションフレームコントローラを返します。 const anim::AnimFrameController& ParticleAnimFrameController() const { return m_ParticleAnimFrameController; } //! @brief パーティクルの存在を取得します。 //! @return パーティクル粒子が存在すればtrueを返します。 bool HasParticle() const { bool result; ParticleSetsAreEmpty function(&result); this->ForeachConstParticleSet(function); return !result; } //! @brief 描画順序のデバッグ用のヒント情報を初期化します。 //! @details シーンからデタッチしたあとに再利用する場合などに呼び出してください。 void ResetDebugHint() { #ifdef NW_CHECK_PARTICLE_PROCESS ParticleSetsResetDebugHint function; this->ForeachParticleSet(function); #endif } //@} protected: virtual Result Initialize(os::IAllocator* allocator); //! @details :private static void GetMemorySizeForInitialize( os::MemorySizeCalculator* pSize, ResParticleModel resource, const ParticleModel::Description& modelDescription); //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! @brief コンストラクタです。 ParticleModel( os::IAllocator* allocator, ResTransformNode resource, const ParticleModel::Description& description) : Model( allocator, resource, description), m_MaximumParticleSet(description.particleSetCount), m_ParticleSetCount(0), m_ParticleShapeCount(0), m_ParticleAnimFrameController(0, 16777215, anim::PlayPolicy_Loop) {} //! @brief デストラクタです。 virtual ~ParticleModel() { for (int i = 0; i < m_ParticleShapes.size(); ++i) // TBD { SafeDestroy(m_ParticleShapes[i]); // m_ParticleSetはAttachChild()されているので、 // SceneNodeにより自動的に解放されます。 } } //@} private: uint m_MaximumParticleSet; int m_ParticleSetCount; ut::MoveArray m_ParticleSets; int m_ParticleShapeCount; ut::MoveArray m_ParticleShapes; anim::AnimFrameController m_ParticleAnimFrameController; }; } // namespace gfx } // namespace nw #endif // NW_GFX_PARTICLEMODEL_H_