diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index 5b4914e21..6e57805a9 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -6,9 +6,39 @@ namespace urde { static logvisor::Module Log("URDE::ProjectManager"); +CToken ProjectResourcePool::GetObj(char const* name) +{ + CToken ret = CSimplePool::GetObj(name); + if (ret) + return ret; + + hecl::ProjectPath path(*m_parent.project(), name); + SObjectTag tag = static_cast(x30_factory). + TagFromPath(path, hecl::SharedBlenderToken); + if (tag) + return CSimplePool::GetObj(tag); + + return {}; +} + +CToken ProjectResourcePool::GetObj(char const* name, const CVParamTransfer& pvxfer) +{ + CToken ret = CSimplePool::GetObj(name, pvxfer); + if (ret) + return ret; + + hecl::ProjectPath path(*m_parent.project(), name); + SObjectTag tag = static_cast(x30_factory). + TagFromPath(path, hecl::SharedBlenderToken); + if (tag) + return CSimplePool::GetObj(tag, pvxfer); + + return {}; +} + bool ProjectManager::m_registeredSpecs = false; ProjectManager::ProjectManager(ViewManager &vm) -: m_vm(vm), m_clientProc(1), m_factoryMP1(m_clientProc), m_objStore(m_factoryMP1) +: m_vm(vm), m_clientProc(1), m_factoryMP1(m_clientProc), m_objStore(m_factoryMP1, *this) { if (!m_registeredSpecs) { diff --git a/Editor/ProjectManager.hpp b/Editor/ProjectManager.hpp index 014ab2f2d..21ccc9965 100644 --- a/Editor/ProjectManager.hpp +++ b/Editor/ProjectManager.hpp @@ -14,6 +14,16 @@ class ViewManager; using ConfigReader = athena::io::YAMLDocReader; using ConfigWriter = athena::io::YAMLDocWriter; +class ProjectResourcePool : public CSimplePool +{ + class ProjectManager& m_parent; +public: + ProjectResourcePool(IFactory& factory, ProjectManager& parent) + : CSimplePool(factory), m_parent(parent) {} + CToken GetObj(char const*); + CToken GetObj(char const*, const CVParamTransfer&); +}; + class ProjectManager { ViewManager& m_vm; @@ -21,7 +31,7 @@ class ProjectManager static bool m_registeredSpecs; hecl::ClientProcess m_clientProc; ProjectResourceFactoryMP1 m_factoryMP1; - urde::CSimplePool m_objStore; + ProjectResourcePool m_objStore; public: ProjectManager(ViewManager& vm); diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 8445712f0..39aaa08e5 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -82,6 +82,17 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveCatalogs(const hecl::Pr } } +static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, + const SObjectTag& pathTag, const hecl::ProjectPath& path) +{ + char idStr[9]; + snprintf(idStr, 9, "%08X", uint32_t(pathTag.id)); + cacheWriter.enterSubVector(idStr); + cacheWriter.writeString(nullptr, pathTag.type.toString().c_str()); + cacheWriter.writeString(nullptr, path.getRelativePathUTF8().c_str()); + cacheWriter.leaveSubVector(); +} + void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::ProjectPath& dir, athena::io::YAMLDocWriter& cacheWriter, athena::io::YAMLDocWriter& nameWriter, @@ -115,17 +126,34 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec { std::unique_lock lk(m_backgroundIndexMutex); m_tagToPath[pathTag] = path; - char idStr[9]; - snprintf(idStr, 9, "%08X", uint32_t(pathTag.id)); - cacheWriter.enterSubVector(idStr); - cacheWriter.writeString(nullptr, pathTag.type.toString().c_str()); - cacheWriter.writeString(nullptr, path.getRelativePathUTF8().c_str()); - cacheWriter.leaveSubVector(); + WriteTag(cacheWriter, pathTag, path); #if 1 fprintf(stderr, "%s %08X %s\n", pathTag.type.toString().c_str(), uint32_t(pathTag.id), path.getRelativePathUTF8().c_str()); #endif + + /* Special multi-resource intermediates */ + if (pathTag.type == SBIG('CMDL')) + { + hecl::ProjectPath subPath(path, ".|skin"); + SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender); + if (pathTag) + { + m_tagToPath[pathTag] = path; + WriteTag(cacheWriter, pathTag, path); + } + } + else if (pathTag.type == SBIG('ANCS')) + { + hecl::ProjectPath subPath(path, ".|layout"); + SObjectTag pathTag = TagFromPath(subPath, m_backgroundBlender); + if (pathTag) + { + m_tagToPath[pathTag] = path; + WriteTag(cacheWriter, pathTag, path); + } + } } } diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index a21caf8c3..b66c2669e 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -16,6 +16,7 @@ namespace urde class ProjectResourceFactoryBase : public urde::IFactory { + friend class ProjectResourcePool; hecl::ClientProcess& m_clientProc; protected: std::unordered_map m_tagToPath; diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index 03b6491b3..68d290c31 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -47,8 +47,16 @@ SObjectTag ProjectResourceFactoryMP1::TagFromPath(const hecl::ProjectPath& path, switch (conn.getBlendType()) { case hecl::BlenderConnection::BlendType::Mesh: + if (!path.getAuxInfo().compare(_S("skin"))) + { + if (!conn.getRigged()) + return {}; + return {SBIG('CSKR'), path.hash().val32()}; + } return {SBIG('CMDL'), path.hash().val32()}; case hecl::BlenderConnection::BlendType::Actor: + if (!path.getAuxInfo().compare(_S("layout"))) + return {SBIG('CINF'), path.hash().val32()}; return {SBIG('ANCS'), path.hash().val32()}; case hecl::BlenderConnection::BlendType::Area: return {SBIG('MREA'), path.hash().val32()}; diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 0b97b9c87..bae77a148 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -20,7 +20,8 @@ namespace urde void ViewManager::BuildTestPART(urde::IObjectStore& objStore) { - m_modelTest = objStore.GetObj("CMDL_GameCube"); + m_modelTest = objStore.GetObj("MP1/SamusGun/CMDL_0EF58656.blend"); + //m_modelTest = objStore.GetObj("CMDL_GameCube"); m_modelTest.Lock(); //m_partGenDesc = objStore.GetObj({hecl::FOURCC('PART'), 0x972A5CD2}); @@ -67,8 +68,9 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ) flags.m_extendedShaderIdx = 1; m_theta += 0.01f; - CGraphics::SetModelMatrix(zeus::CTransform::RotateZ(m_theta)); - CGraphics::SetViewPointMatrix(zeus::CTransform::Identity() + zeus::CVector3f(0.f, -10.f, 0.f)); + CGraphics::SetModelMatrix(zeus::CTransform::RotateZ(m_theta) * zeus::CTransform::Scale(10.f)); + //CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CGraphics::SetViewPointMatrix(zeus::lookAt(zeus::CVector3f{0.f, -10.f, 4.f}, {0.f, 0.f, 0.f})); boo::SWindowRect windowRect = m_vm.m_mainWindow->getWindowFrame(); float aspect = windowRect.size[0] / float(windowRect.size[1]); CGraphics::SetPerspective(55.0, aspect, 0.001f, 1000.f); diff --git a/Runtime/CSimplePool.cpp b/Runtime/CSimplePool.cpp index 2cb76d4fc..7b1c9bec8 100644 --- a/Runtime/CSimplePool.cpp +++ b/Runtime/CSimplePool.cpp @@ -38,6 +38,8 @@ CToken CSimplePool::GetObj(char const* resourceName) CToken CSimplePool::GetObj(char const* resourceName, const CVParamTransfer& paramXfer) { const SObjectTag* tag = x30_factory.GetResourceIdByName(resourceName); + if (!tag) + return {}; return GetObj(*tag, paramXfer); } diff --git a/Runtime/CSimplePool.hpp b/Runtime/CSimplePool.hpp index b2ee91024..b08cdfb66 100644 --- a/Runtime/CSimplePool.hpp +++ b/Runtime/CSimplePool.hpp @@ -13,6 +13,7 @@ class CObjectReference; class CSimplePool : public IObjectStore { +protected: std::list> x4_resources; //std::unordered_map x4_resources; IFactory& x30_factory; diff --git a/Runtime/Character/CCharLayoutInfo.hpp b/Runtime/Character/CCharLayoutInfo.hpp index e69de29bb..c7b837e08 100644 --- a/Runtime/Character/CCharLayoutInfo.hpp +++ b/Runtime/Character/CCharLayoutInfo.hpp @@ -0,0 +1,13 @@ +#ifndef __PSHAG_CCHARLAYOUTINFO_HPP__ +#define __PSHAG_CCHARLAYOUTINFO_HPP__ + +namespace urde +{ + +class CCharLayoutInfo +{ +}; + +} + +#endif // __PSHAG_CCHARLAYOUTINFO_HPP__ diff --git a/Runtime/Character/CMakeLists.txt b/Runtime/Character/CMakeLists.txt index 0e3256c5d..fbe71ad74 100644 --- a/Runtime/Character/CMakeLists.txt +++ b/Runtime/Character/CMakeLists.txt @@ -9,4 +9,7 @@ add_library(RuntimeCommonCharacter CAnimationDatabaseGame.hpp CTransitionDatabase.hpp CTransitionDatabaseGame.hpp - CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp) + CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp + CPoseAsTransforms.hpp CPoseAsTransforms.cpp + CSkinRules.hpp CSkinRules.cpp + CVirtualBone.hpp CVirtualBone.cpp) diff --git a/Runtime/Character/CPoseAsTransforms.cpp b/Runtime/Character/CPoseAsTransforms.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Runtime/Character/CPoseAsTransforms.hpp b/Runtime/Character/CPoseAsTransforms.hpp new file mode 100644 index 000000000..f56f39b7b --- /dev/null +++ b/Runtime/Character/CPoseAsTransforms.hpp @@ -0,0 +1,13 @@ +#ifndef __PSHAG_CPOSEASTRANSFORMS_HPP__ +#define __PSHAG_CPOSEASTRANSFORMS_HPP__ + +namespace urde +{ + +class CPoseAsTransforms +{ +}; + +} + +#endif // __PSHAG_CPOSEASTRANSFORMS_HPP__ diff --git a/Runtime/Character/CSkinRules.cpp b/Runtime/Character/CSkinRules.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Runtime/Character/CSkinRules.hpp b/Runtime/Character/CSkinRules.hpp new file mode 100644 index 000000000..cc5ea397d --- /dev/null +++ b/Runtime/Character/CSkinRules.hpp @@ -0,0 +1,13 @@ +#ifndef __PSHAG_CSKINRULES_HPP__ +#define __PSHAG_CSKINRULES_HPP__ + +namespace urde +{ + +class CSkinRules +{ +}; + +} + +#endif // __PSHAG_CSKINRULES_HPP__ diff --git a/Runtime/Character/CVirtualBone.cpp b/Runtime/Character/CVirtualBone.cpp new file mode 100644 index 000000000..12c0c0166 --- /dev/null +++ b/Runtime/Character/CVirtualBone.cpp @@ -0,0 +1,11 @@ +#include "CVirtualBone.hpp" + +namespace urde +{ + +CVirtualBone::CVirtualBone(CInputStream& in) +{ + +} + +} diff --git a/Runtime/Character/CVirtualBone.hpp b/Runtime/Character/CVirtualBone.hpp new file mode 100644 index 000000000..207002b94 --- /dev/null +++ b/Runtime/Character/CVirtualBone.hpp @@ -0,0 +1,17 @@ +#ifndef __PSHAG_CVIRTUALBONE_HPP__ +#define __PSHAG_CVIRTUALBONE_HPP__ + +#include "IOStreams.hpp" + +namespace urde +{ + +class CVirtualBone +{ +public: + CVirtualBone(CInputStream& in); +}; + +} + +#endif // __PSHAG_CVIRTUALBONE_HPP__ diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index 782668fe8..780e6e650 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -365,6 +365,31 @@ void CGraphics::SetViewportResolution(const zeus::CVector2i& res) g_ViewportResolutionHalf = {res.x / 2, res.y / 2}; } +static boo::SWindowRect CachedVP; +static float CachedDepthRange[2] = {0.f, 1.f}; + +void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height) +{ + CachedVP.location[0] = leftOff; + CachedVP.location[1] = bottomOff; + CachedVP.size[0] = width; + CachedVP.size[1] = height; + g_BooMainCommandQueue->setViewport(CachedVP, CachedDepthRange[0], CachedDepthRange[1]); +} + +void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height) +{ + boo::SWindowRect rect(leftOff, bottomOff, width, height); + g_BooMainCommandQueue->setScissor(rect); +} + +void CGraphics::SetDepthRange(float znear, float zfar) +{ + CachedDepthRange[0] = znear; + CachedDepthRange[1] = zfar; + g_BooMainCommandQueue->setViewport(CachedVP, CachedDepthRange[0], CachedDepthRange[1]); +} + CTimeProvider* CGraphics::g_ExternalTimeProvider = nullptr; float CGraphics::g_DefaultSeconds; diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index 23e38766d..853697de7 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -213,7 +213,11 @@ public: static SClipScreenRect ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); static SClipScreenRect ClipScreenRectFromVS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point); + static void SetViewportResolution(const zeus::CVector2i& res); + static void SetViewport(int leftOff, int bottomOff, int width, int height); + static void SetScissor(int leftOff, int bottomOff, int width, int height); + static void SetDepthRange(float near, float far); static CTimeProvider* g_ExternalTimeProvider; static float g_DefaultSeconds; diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index 43ba811a2..5f7449610 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -15,7 +15,9 @@ add_library(RuntimeCommonGraphics CLight.hpp CLight.cpp CTexture.hpp CTextureBoo.cpp CModel.hpp CModelBoo.cpp + CSkinnedModel.hpp CSkinnedModel.cpp CModelShaders.hpp CModelShadersGLSL.cpp + CVertexMorphEffect.hpp CVertexMorphEffect.cpp CMoviePlayer.hpp CMoviePlayer.cpp CGraphicsPalette.hpp CGraphicsPalette.cpp CGraphics.hpp CGraphics.cpp diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 142774113..aa76be3a3 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -76,7 +76,6 @@ private: CBooSurface* x3c_firstSortedSurface = nullptr; bool x40_24_texturesLoaded : 1; bool x40_25_ : 1; - u8 x41_shortNormals; struct UVAnimationBuffer { @@ -103,8 +102,7 @@ private: public: CBooModel(std::vector* surfaces, SShader& shader, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, - size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb, - u8 shortNormals, bool texturesLoaded); + size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb); static void MakeTexuresFromMats(const MaterialSet& matSet, std::vector>& toksOut, @@ -129,8 +127,9 @@ public: class CModel { - std::unique_ptr x0_data; - u32 x4_dataLen; + //std::unique_ptr x0_data; + //u32 x4_dataLen; + zeus::CAABox m_aabb; std::vector x8_surfaces; std::vector x18_matSets; std::unique_ptr x28_modelInst; @@ -156,6 +155,7 @@ public: bool IsLoaded(int shaderIdx) const; CBooModel& GetInstance() {return *x28_modelInst;} + std::unique_ptr MakeNewInstance(int shaderIdx); }; CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 297af0879..7081e464d 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -16,12 +16,11 @@ static std::experimental::optional g_ModelShaders; CBooModel::CBooModel(std::vector* surfaces, SShader& shader, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo, - size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb, u8 shortNormals, - bool texturesLoaded) + size_t weightVecCount, size_t skinBankCount, const zeus::CAABox& aabb) : x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), m_pipelines(&shader.m_shaders), m_vtxFmt(vtxFmt), x8_vbo(vbo), xc_ibo(ibo), m_weightVecCount(weightVecCount), m_skinBankCount(skinBankCount), x1c_textures(&shader.x0_textures), x20_aabb(aabb), - x40_24_texturesLoaded(texturesLoaded), x40_25_(0), x41_shortNormals(shortNormals) + x40_24_texturesLoaded(false), x40_25_(0) { for (CBooSurface& surf : *x0_surfaces) surf.m_parent = this; @@ -502,19 +501,28 @@ static const u8* MemoryFromPartData(const u8*& dataCur, const s32*& secSizeCur) return ret; } -CModel::CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store) -: x0_data(std::move(in)), x4_dataLen(dataLen) +std::unique_ptr CModel::MakeNewInstance(int shaderIdx) { - u32 version = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x4)); - u32 flags = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x8)); + if (shaderIdx >= x18_matSets.size()) + shaderIdx = 0; + return std::make_unique(&x8_surfaces, x18_matSets[shaderIdx], + m_vtxFmt, m_vbo, m_ibo, 0, 0, m_aabb); +} + +CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* store) +{ + std::unique_ptr data = std::move(in); + + u32 version = hecl::SBig(*reinterpret_cast(data.get() + 0x4)); + u32 flags = hecl::SBig(*reinterpret_cast(data.get() + 0x8)); if (version != 0x10002) Log.report(logvisor::Fatal, "invalid CMDL for loading with boo"); - u32 secCount = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x24)); - u32 matSetCount = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x28)); + u32 secCount = hecl::SBig(*reinterpret_cast(data.get() + 0x24)); + u32 matSetCount = hecl::SBig(*reinterpret_cast(data.get() + 0x28)); x18_matSets.reserve(matSetCount); - const u8* dataCur = x0_data.get() + ROUND_UP_32(0x2c + secCount * 4); - const s32* secSizeCur = reinterpret_cast(x0_data.get() + 0x2c); + const u8* dataCur = data.get() + ROUND_UP_32(0x2c + secCount * 4); + const s32* secSizeCur = reinterpret_cast(data.get() + 0x2c); for (u32 i=0 ; i&& in, u32 dataLen, IObjectStore* store) surf.m_data.read(r); } - const float* aabbPtr = reinterpret_cast(x0_data.get() + 0xc); - zeus::CAABox aabb(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), - hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); - x28_modelInst = std::make_unique(&x8_surfaces, x18_matSets[0], - m_vtxFmt, m_vbo, m_ibo, 0, 0, - aabb, flags & 0x2, false); + const float* aabbPtr = reinterpret_cast(data.get() + 0xc); + m_aabb = zeus::CAABox(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), + hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); + x28_modelInst = MakeNewInstance(0); } void CBooModel::SShader::UnlockTextures() diff --git a/Runtime/Graphics/CSkinnedModel.cpp b/Runtime/Graphics/CSkinnedModel.cpp new file mode 100644 index 000000000..63c66069e --- /dev/null +++ b/Runtime/Graphics/CSkinnedModel.cpp @@ -0,0 +1,18 @@ +#include "CSkinnedModel.hpp" + +namespace urde +{ + +CSkinnedModel::CSkinnedModel(const TLockedToken& model, + const TLockedToken& skinRules, + const TLockedToken& layoutInfo) +{ + +} + +void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, + const std::experimental::optional&) +{ +} + +} diff --git a/Runtime/Graphics/CSkinnedModel.hpp b/Runtime/Graphics/CSkinnedModel.hpp new file mode 100644 index 000000000..10e6c8df0 --- /dev/null +++ b/Runtime/Graphics/CSkinnedModel.hpp @@ -0,0 +1,31 @@ +#ifndef __PSHAG_CSKINNEDMODEL_HPP__ +#define __PSHAG_CSKINNEDMODEL_HPP__ + +#include "CToken.hpp" +#include "CModel.hpp" +#include "optional.hpp" + +namespace urde +{ +class CModel; +class CSkinRules; +class CCharLayoutInfo; +class CPoseAsTransforms; +class CVertexMorphEffect; +class IObjectStore; + +class CSkinnedModel +{ + std::unique_ptr m_modelInst; +public: + CSkinnedModel(const TLockedToken& model, + const TLockedToken& skinRules, + const TLockedToken& layoutInfo); + CSkinnedModel(IObjectStore& store, TResId model, TResId skinRules, TResId layoutInfo); + + void Calculate(const CPoseAsTransforms& pose, const std::experimental::optional&); +}; + +} + +#endif // __PSHAG_CSKINNEDMODEL_HPP__ diff --git a/Runtime/Graphics/CVertexMorphEffect.cpp b/Runtime/Graphics/CVertexMorphEffect.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Runtime/Graphics/CVertexMorphEffect.hpp b/Runtime/Graphics/CVertexMorphEffect.hpp new file mode 100644 index 000000000..1e9806408 --- /dev/null +++ b/Runtime/Graphics/CVertexMorphEffect.hpp @@ -0,0 +1,13 @@ +#ifndef __PSHAG_CVERTEXMORPHEFFECT_HPP__ +#define __PSHAG_CVERTEXMORPHEFFECT_HPP__ + +namespace urde +{ + +class CVertexMorphEffect +{ +}; + +} + +#endif // __PSHAG_CVERTEXMORPHEFFECT_HPP__ diff --git a/hecl b/hecl index a50a7ac36..97a5fb2af 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit a50a7ac3685ebaf5bd5c7a5c31493710a8f8f125 +Subproject commit 97a5fb2af2b16283af8c9bb619111a49d2869c7d diff --git a/specter b/specter index a8ae3714d..ff3410b26 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit a8ae3714d2983d9faa9123151d71259c1fb9e111 +Subproject commit ff3410b26607bca871dc15e464235c67b47770a2