mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-06-16 19:43:38 +00:00
Added support for loading and rendering skeletons, added character editor
This commit is contained in:
parent
f9a2d019e1
commit
2376a36f0b
@ -185,7 +185,10 @@ HEADERS += \
|
|||||||
Resource/Factory/CSectionMgrIn.h \
|
Resource/Factory/CSectionMgrIn.h \
|
||||||
Resource/Cooker/CScriptCooker.h \
|
Resource/Cooker/CScriptCooker.h \
|
||||||
ScriptExtra/CSplinePathExtra.h \
|
ScriptExtra/CSplinePathExtra.h \
|
||||||
Resource/Script/CLink.h
|
Resource/Script/CLink.h \
|
||||||
|
Resource/CSkeleton.h \
|
||||||
|
Resource/Factory/CSkeletonLoader.h \
|
||||||
|
Scene/CCharacterNode.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -263,4 +266,7 @@ SOURCES += \
|
|||||||
Resource/Factory/CPoiToWorldLoader.cpp \
|
Resource/Factory/CPoiToWorldLoader.cpp \
|
||||||
Resource/Cooker/CPoiToWorldCooker.cpp \
|
Resource/Cooker/CPoiToWorldCooker.cpp \
|
||||||
Resource/Cooker/CScriptCooker.cpp \
|
Resource/Cooker/CScriptCooker.cpp \
|
||||||
ScriptExtra/CSplinePathExtra.cpp
|
ScriptExtra/CSplinePathExtra.cpp \
|
||||||
|
Resource/CSkeleton.cpp \
|
||||||
|
Resource/Factory/CSkeletonLoader.cpp \
|
||||||
|
Scene/CCharacterNode.cpp
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "TResPtr.h"
|
#include "TResPtr.h"
|
||||||
#include "CResource.h"
|
#include "CResource.h"
|
||||||
|
#include "CSkeleton.h"
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include <Common/types.h>
|
#include <Common/types.h>
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ class CAnimSet : public CResource
|
|||||||
TString Name;
|
TString Name;
|
||||||
TResPtr<CModel> pModel;
|
TResPtr<CModel> pModel;
|
||||||
u32 SkinID;
|
u32 SkinID;
|
||||||
u32 SkelID;
|
TResPtr<CSkeleton> pSkeleton;
|
||||||
|
|
||||||
SNode() { pModel = nullptr; }
|
SNode() { pModel = nullptr; }
|
||||||
};
|
};
|
||||||
@ -28,9 +29,10 @@ class CAnimSet : public CResource
|
|||||||
public:
|
public:
|
||||||
CAnimSet() : CResource() {}
|
CAnimSet() : CResource() {}
|
||||||
|
|
||||||
u32 NumNodes() const { return mNodes.size(); }
|
u32 NumNodes() const { return mNodes.size(); }
|
||||||
TString NodeName(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].Name; }
|
TString NodeName(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].Name; }
|
||||||
CModel* NodeModel(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pModel; }
|
CModel* NodeModel(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pModel; }
|
||||||
|
CSkeleton* NodeSkeleton(u32 Index) { if (Index >= mNodes.size()) Index = 0; return mNodes[Index].pSkeleton; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CCHARACTERSET_H
|
#endif // CCHARACTERSET_H
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "Core/Resource/Factory/CModelLoader.h"
|
#include "Core/Resource/Factory/CModelLoader.h"
|
||||||
#include "Core/Resource/Factory/CPoiToWorldLoader.h"
|
#include "Core/Resource/Factory/CPoiToWorldLoader.h"
|
||||||
#include "Core/Resource/Factory/CScanLoader.h"
|
#include "Core/Resource/Factory/CScanLoader.h"
|
||||||
|
#include "Core/Resource/Factory/CSkeletonLoader.h"
|
||||||
#include "Core/Resource/Factory/CStringLoader.h"
|
#include "Core/Resource/Factory/CStringLoader.h"
|
||||||
#include "Core/Resource/Factory/CTextureDecoder.h"
|
#include "Core/Resource/Factory/CTextureDecoder.h"
|
||||||
#include "Core/Resource/Factory/CWorldLoader.h"
|
#include "Core/Resource/Factory/CWorldLoader.h"
|
||||||
@ -149,6 +150,7 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC Type)
|
|||||||
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(Mem);
|
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(Mem);
|
||||||
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(Mem);
|
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(Mem);
|
||||||
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(Mem);
|
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(Mem);
|
||||||
|
else if (Type == "CINF") pRes = CSkeletonLoader::LoadCINF(Mem);
|
||||||
else SupportedFormat = false;
|
else SupportedFormat = false;
|
||||||
|
|
||||||
// Log errors
|
// Log errors
|
||||||
@ -203,6 +205,7 @@ CResource* CResCache::GetResource(const TString& rkResPath)
|
|||||||
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(File);
|
else if (Type == "SCAN") pRes = CScanLoader::LoadSCAN(File);
|
||||||
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(File);
|
else if (Type == "DCLN") pRes = CCollisionLoader::LoadDCLN(File);
|
||||||
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(File);
|
else if (Type == "EGMC") pRes = CPoiToWorldLoader::LoadEGMC(File);
|
||||||
|
else if (Type == "CINF") pRes = CSkeletonLoader::LoadCINF(File);
|
||||||
else SupportedFormat = false;
|
else SupportedFormat = false;
|
||||||
|
|
||||||
if (!pRes) pRes = new CResource(); // Default for unsupported formats
|
if (!pRes) pRes = new CResource(); // Default for unsupported formats
|
||||||
|
55
src/Core/Resource/CSkeleton.cpp
Normal file
55
src/Core/Resource/CSkeleton.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "CSkeleton.h"
|
||||||
|
#include "Core/Render/CDrawUtil.h"
|
||||||
|
#include "Core/Render/CGraphics.h"
|
||||||
|
|
||||||
|
// ************ CBone ************
|
||||||
|
CBone::CBone(CSkeleton *pSkel)
|
||||||
|
: mpSkeleton(pSkel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ CSkeleton ************
|
||||||
|
CSkeleton::CSkeleton()
|
||||||
|
: mpRootBone(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CSkeleton::~CSkeleton()
|
||||||
|
{
|
||||||
|
for (u32 iBone = 0; iBone < mBones.size(); iBone++)
|
||||||
|
delete mBones[iBone];
|
||||||
|
}
|
||||||
|
|
||||||
|
CBone* CSkeleton::BoneByID(u32 BoneID) const
|
||||||
|
{
|
||||||
|
for (u32 iBone = 0; iBone < mBones.size(); iBone++)
|
||||||
|
{
|
||||||
|
if (mBones[iBone]->ID() == BoneID)
|
||||||
|
return mBones[iBone];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSkeleton::Draw(FRenderOptions /*Options*/)
|
||||||
|
{
|
||||||
|
for (u32 iBone = 0; iBone < mBones.size(); iBone++)
|
||||||
|
{
|
||||||
|
CBone *pBone = mBones[iBone];
|
||||||
|
|
||||||
|
// Draw bone
|
||||||
|
CTransform4f Transform;
|
||||||
|
Transform.Scale(0.01f);
|
||||||
|
Transform.Translate(pBone->Position());
|
||||||
|
CGraphics::sMVPBlock.ModelMatrix = Transform.ToMatrix4f();
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
CDrawUtil::DrawSphere(CColor::skWhite);
|
||||||
|
|
||||||
|
// Draw child links
|
||||||
|
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
|
||||||
|
CGraphics::UpdateMVPBlock();
|
||||||
|
|
||||||
|
for (u32 iChild = 0; iChild < pBone->NumChildren(); iChild++)
|
||||||
|
CDrawUtil::DrawLine(pBone->Position(), pBone->ChildByIndex(iChild)->Position());
|
||||||
|
}
|
||||||
|
}
|
49
src/Core/Resource/CSkeleton.h
Normal file
49
src/Core/Resource/CSkeleton.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef CSKELETON_H
|
||||||
|
#define CSKELETON_H
|
||||||
|
|
||||||
|
#include "CResource.h"
|
||||||
|
#include "Core/Render/FRenderOptions.h"
|
||||||
|
#include <Common/TString.h>
|
||||||
|
#include <Common/types.h>
|
||||||
|
#include <Math/CVector3f.h>
|
||||||
|
|
||||||
|
class CSkeleton;
|
||||||
|
|
||||||
|
class CBone
|
||||||
|
{
|
||||||
|
friend class CSkeletonLoader;
|
||||||
|
|
||||||
|
CSkeleton *mpSkeleton;
|
||||||
|
CBone *mpParent;
|
||||||
|
std::vector<CBone*> mChildren;
|
||||||
|
u32 mID;
|
||||||
|
CVector3f mPosition;
|
||||||
|
TString mName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CBone(CSkeleton *pSkel);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
inline u32 ID() const { return mID; }
|
||||||
|
inline CVector3f Position() const { return mPosition; }
|
||||||
|
inline u32 NumChildren() const { return mChildren.size(); }
|
||||||
|
inline CBone* ChildByIndex(u32 Index) const { return mChildren[Index]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSkeleton : public CResource
|
||||||
|
{
|
||||||
|
DECLARE_RESOURCE_TYPE(eSkeleton)
|
||||||
|
friend class CSkeletonLoader;
|
||||||
|
|
||||||
|
CBone *mpRootBone;
|
||||||
|
std::vector<CBone*> mBones;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSkeleton();
|
||||||
|
~CSkeleton();
|
||||||
|
|
||||||
|
CBone* BoneByID(u32 BoneID) const;
|
||||||
|
void Draw(FRenderOptions Options);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CSKELETON_H
|
@ -99,7 +99,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS)
|
|||||||
pNode->Name = rANCS.ReadString();
|
pNode->Name = rANCS.ReadString();
|
||||||
pNode->pModel = gResCache.GetResource(rANCS.ReadLong(), "CMDL");
|
pNode->pModel = gResCache.GetResource(rANCS.ReadLong(), "CMDL");
|
||||||
pNode->SkinID = rANCS.ReadLong();
|
pNode->SkinID = rANCS.ReadLong();
|
||||||
pNode->SkelID = rANCS.ReadLong();
|
pNode->pSkeleton = gResCache.GetResource(rANCS.ReadLong(), "CINF");
|
||||||
|
|
||||||
// Unfortunately that's all that's actually supported at the moment. Hope to expand later.
|
// Unfortunately that's all that's actually supported at the moment. Hope to expand later.
|
||||||
// Since there's no size value I have to actually read the rest of the node to reach the next one
|
// Since there's no size value I have to actually read the rest of the node to reach the next one
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "Core/Resource/CAnimSet.h"
|
#include "Core/Resource/CAnimSet.h"
|
||||||
#include "Core/Resource/EGame.h"
|
#include "Core/Resource/EGame.h"
|
||||||
#include "Core/Resource/CResCache.h"
|
|
||||||
|
|
||||||
class CAnimSetLoader
|
class CAnimSetLoader
|
||||||
{
|
{
|
||||||
|
90
src/Core/Resource/Factory/CSkeletonLoader.cpp
Normal file
90
src/Core/Resource/Factory/CSkeletonLoader.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "CSkeletonLoader.h"
|
||||||
|
#include <Common/Log.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
CSkeletonLoader::CSkeletonLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ STATIC ************
|
||||||
|
CSkeleton* CSkeletonLoader::LoadCINF(IInputStream& rCINF)
|
||||||
|
{
|
||||||
|
CSkeleton *pSkel = new CSkeleton();
|
||||||
|
|
||||||
|
u32 NumBones = rCINF.ReadLong();
|
||||||
|
pSkel->mBones.reserve(NumBones);
|
||||||
|
|
||||||
|
// Read bones
|
||||||
|
struct SBoneInfo
|
||||||
|
{
|
||||||
|
u32 ParentID;
|
||||||
|
std::vector<u32> ChildIDs;
|
||||||
|
};
|
||||||
|
std::vector<SBoneInfo> BoneInfo(NumBones);
|
||||||
|
|
||||||
|
for (u32 iBone = 0; iBone < NumBones; iBone++)
|
||||||
|
{
|
||||||
|
CBone *pBone = new CBone(pSkel);
|
||||||
|
pSkel->mBones.push_back(pBone);
|
||||||
|
|
||||||
|
pBone->mID = rCINF.ReadLong();
|
||||||
|
BoneInfo[iBone].ParentID = rCINF.ReadLong();
|
||||||
|
pBone->mPosition = CVector3f(rCINF);
|
||||||
|
|
||||||
|
u32 NumLinkedBones = rCINF.ReadLong();
|
||||||
|
|
||||||
|
for (u32 iLink = 0; iLink < NumLinkedBones; iLink++)
|
||||||
|
{
|
||||||
|
u32 LinkedID = rCINF.ReadLong();
|
||||||
|
|
||||||
|
if (LinkedID != BoneInfo[iBone].ParentID)
|
||||||
|
BoneInfo[iBone].ChildIDs.push_back(LinkedID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in bone info
|
||||||
|
for (u32 iBone = 0; iBone < NumBones; iBone++)
|
||||||
|
{
|
||||||
|
CBone *pBone = pSkel->mBones[iBone];
|
||||||
|
SBoneInfo& rInfo = BoneInfo[iBone];
|
||||||
|
|
||||||
|
pBone->mpParent = pSkel->BoneByID(rInfo.ParentID);
|
||||||
|
|
||||||
|
for (u32 iChild = 0; iChild < rInfo.ChildIDs.size(); iChild++)
|
||||||
|
{
|
||||||
|
u32 ChildID = rInfo.ChildIDs[iChild];
|
||||||
|
CBone *pChild = pSkel->BoneByID(ChildID);
|
||||||
|
|
||||||
|
if (pChild)
|
||||||
|
pBone->mChildren.push_back(pChild);
|
||||||
|
else
|
||||||
|
Log::FileError(rCINF.GetSourceString(), "Bone " + TString::FromInt32(pBone->mID, 0, 10) + " has invalid child ID: " + TString::FromInt32(ChildID, 0, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pBone->mpParent)
|
||||||
|
{
|
||||||
|
if (!pSkel->mpRootBone)
|
||||||
|
pSkel->mpRootBone = pBone;
|
||||||
|
else
|
||||||
|
Log::FileError(rCINF.GetSourceString(), "Multiple root bones?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip bone ID array
|
||||||
|
u32 NumBoneIDs = rCINF.ReadLong();
|
||||||
|
rCINF.Seek(NumBoneIDs * 4, SEEK_CUR);
|
||||||
|
|
||||||
|
// Read bone names
|
||||||
|
u32 NumBoneNames = rCINF.ReadLong();
|
||||||
|
|
||||||
|
for (u32 iName = 0; iName < NumBoneNames; iName++)
|
||||||
|
{
|
||||||
|
TString Name = rCINF.ReadString();
|
||||||
|
u32 BoneID = rCINF.ReadLong();
|
||||||
|
|
||||||
|
pSkel->BoneByID(BoneID)->mName = Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pSkel;
|
||||||
|
}
|
19
src/Core/Resource/Factory/CSkeletonLoader.h
Normal file
19
src/Core/Resource/Factory/CSkeletonLoader.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef CSKELETONLOADER_H
|
||||||
|
#define CSKELETONLOADER_H
|
||||||
|
|
||||||
|
#include "Core/Resource/CSkeleton.h"
|
||||||
|
#include "Core/Resource/EGame.h"
|
||||||
|
#include "Core/Resource/TResPtr.h"
|
||||||
|
|
||||||
|
class CSkeletonLoader
|
||||||
|
{
|
||||||
|
TResPtr<CSkeleton> mpSkeleton;
|
||||||
|
EGame mVersion;
|
||||||
|
|
||||||
|
CSkeletonLoader();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static CSkeleton* LoadCINF(IInputStream& rCINF);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CSKELETONLOADER_H
|
64
src/Core/Scene/CCharacterNode.cpp
Normal file
64
src/Core/Scene/CCharacterNode.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "CCharacterNode.h"
|
||||||
|
#include <Core/Render/CRenderer.h>
|
||||||
|
|
||||||
|
CCharacterNode::CCharacterNode(CScene *pScene, u32 NodeID, CAnimSet *pChar /*= 0*/, CSceneNode *pParent /*= 0*/)
|
||||||
|
: CSceneNode(pScene, NodeID, pParent)
|
||||||
|
{
|
||||||
|
SetCharacter(pChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENodeType CCharacterNode::NodeType()
|
||||||
|
{
|
||||||
|
return eCharacterNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterNode::PostLoad()
|
||||||
|
{
|
||||||
|
if (mpCharacter)
|
||||||
|
{
|
||||||
|
for (u32 iChar = 0; iChar < mpCharacter->NumNodes(); iChar++)
|
||||||
|
mpCharacter->NodeModel(iChar)->BufferGL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& /*rkViewInfo*/)
|
||||||
|
{
|
||||||
|
if (!mpCharacter) return;
|
||||||
|
|
||||||
|
if (mpCharacter->NodeSkeleton(mActiveCharSet))
|
||||||
|
{
|
||||||
|
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterNode::Draw(FRenderOptions Options, int /*ComponentIndex*/, const SViewInfo& /*rkViewInfo*/)
|
||||||
|
{
|
||||||
|
CSkeleton *pSkel = mpCharacter->NodeSkeleton(mActiveCharSet);
|
||||||
|
pSkel->Draw(Options);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRayIntersection CCharacterNode::RayNodeIntersectTest(const CRay& /*rkRay*/, u32 /*AssetID*/, const SViewInfo& /*rkViewInfo*/)
|
||||||
|
{
|
||||||
|
// Not currently doing any ray checks on character nodes so don't care about this right now.
|
||||||
|
return SRayIntersection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterNode::SetCharacter(CAnimSet *pChar)
|
||||||
|
{
|
||||||
|
mpCharacter = pChar;
|
||||||
|
SetActiveCharSet(0);
|
||||||
|
|
||||||
|
if (!mpCharacter)
|
||||||
|
mLocalAABox = CAABox::skOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterNode::SetActiveCharSet(u32 CharIndex)
|
||||||
|
{
|
||||||
|
mActiveCharSet = CharIndex;
|
||||||
|
|
||||||
|
if (mpCharacter)
|
||||||
|
{
|
||||||
|
mLocalAABox = mpCharacter->NodeModel(CharIndex)->AABox();
|
||||||
|
MarkTransformChanged();
|
||||||
|
}
|
||||||
|
}
|
27
src/Core/Scene/CCharacterNode.h
Normal file
27
src/Core/Scene/CCharacterNode.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef CCHARACTERNODE_H
|
||||||
|
#define CCHARACTERNODE_H
|
||||||
|
|
||||||
|
#include "CSceneNode.h"
|
||||||
|
#include "Core/Resource/CAnimSet.h"
|
||||||
|
|
||||||
|
class CCharacterNode : public CSceneNode
|
||||||
|
{
|
||||||
|
TResPtr<CAnimSet> mpCharacter;
|
||||||
|
u32 mActiveCharSet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CCharacterNode(CScene *pScene, u32 NodeID, CAnimSet *pChar = 0, CSceneNode *pParent = 0);
|
||||||
|
|
||||||
|
virtual ENodeType NodeType();
|
||||||
|
virtual void PostLoad();
|
||||||
|
virtual void AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
|
||||||
|
virtual void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& rkViewInfo);
|
||||||
|
virtual SRayIntersection RayNodeIntersectTest(const CRay& rkRay, u32 AssetID, const SViewInfo& rkViewInfo);
|
||||||
|
inline CAnimSet* Character() const { return mpCharacter; }
|
||||||
|
inline u32 ActiveCharSet() const { return mActiveCharSet; }
|
||||||
|
|
||||||
|
void SetCharacter(CAnimSet *pChar);
|
||||||
|
void SetActiveCharSet(u32 CharIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCHARACTERNODE_H
|
@ -7,12 +7,13 @@ enum ENodeType
|
|||||||
{
|
{
|
||||||
eRootNode = 0x0,
|
eRootNode = 0x0,
|
||||||
eModelNode = 0x1,
|
eModelNode = 0x1,
|
||||||
eStaticNode = 0x2,
|
eCharacterNode = 0x2,
|
||||||
eCollisionNode = 0x4,
|
eStaticNode = 0x4,
|
||||||
eScriptNode = 0x8,
|
eCollisionNode = 0x8,
|
||||||
eScriptExtraNode = 0x10,
|
eScriptNode = 0x10,
|
||||||
eLightNode = 0x20,
|
eScriptExtraNode = 0x20,
|
||||||
eAllNodeTypes = 0x3F
|
eLightNode = 0x40,
|
||||||
|
eAllNodeTypes = 0x7F
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_FLAGS(ENodeType, FNodeFlags)
|
DECLARE_FLAGS(ENodeType, FNodeFlags)
|
||||||
|
@ -21,8 +21,10 @@ CStartWindow::CStartWindow(QWidget *parent)
|
|||||||
mpWorld = nullptr;
|
mpWorld = nullptr;
|
||||||
mpWorldEditor = new CWorldEditor(0);
|
mpWorldEditor = new CWorldEditor(0);
|
||||||
mpModelEditor = new CModelEditorWindow(this);
|
mpModelEditor = new CModelEditorWindow(this);
|
||||||
|
mpCharEditor = new CCharacterEditor(this);
|
||||||
|
|
||||||
connect(ui->ActionAbout, SIGNAL(triggered()), this, SLOT(About()));
|
connect(ui->ActionAbout, SIGNAL(triggered()), this, SLOT(About()));
|
||||||
|
connect(ui->ActionCharacterEditor, SIGNAL(triggered()), this, SLOT(LaunchCharacterEditor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CStartWindow::~CStartWindow()
|
CStartWindow::~CStartWindow()
|
||||||
@ -30,6 +32,7 @@ CStartWindow::~CStartWindow()
|
|||||||
delete ui;
|
delete ui;
|
||||||
delete mpWorldEditor;
|
delete mpWorldEditor;
|
||||||
delete mpModelEditor;
|
delete mpModelEditor;
|
||||||
|
delete mpCharEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStartWindow::closeEvent(QCloseEvent *pEvent)
|
void CStartWindow::closeEvent(QCloseEvent *pEvent)
|
||||||
@ -237,6 +240,11 @@ void CStartWindow::on_actionExtract_PAK_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CStartWindow::LaunchCharacterEditor()
|
||||||
|
{
|
||||||
|
mpCharEditor->show();
|
||||||
|
}
|
||||||
|
|
||||||
void CStartWindow::About()
|
void CStartWindow::About()
|
||||||
{
|
{
|
||||||
CAboutDialog Dialog(this);
|
CAboutDialog Dialog(this);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "WorldEditor/CWorldEditor.h"
|
#include "WorldEditor/CWorldEditor.h"
|
||||||
#include "ModelEditor/CModelEditorWindow.h"
|
#include "ModelEditor/CModelEditorWindow.h"
|
||||||
|
#include "CharacterEditor/CCharacterEditor.h"
|
||||||
#include <Core/Resource/CWorld.h>
|
#include <Core/Resource/CWorld.h>
|
||||||
#include <Core/Resource/CResCache.h>
|
#include <Core/Resource/CResCache.h>
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ class CStartWindow : public QMainWindow
|
|||||||
|
|
||||||
CWorldEditor *mpWorldEditor;
|
CWorldEditor *mpWorldEditor;
|
||||||
CModelEditorWindow *mpModelEditor;
|
CModelEditorWindow *mpModelEditor;
|
||||||
|
CCharacterEditor *mpCharEditor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CStartWindow(QWidget *pParent = 0);
|
explicit CStartWindow(QWidget *pParent = 0);
|
||||||
@ -35,6 +37,8 @@ private slots:
|
|||||||
void on_LaunchWorldEditorButton_clicked();
|
void on_LaunchWorldEditorButton_clicked();
|
||||||
void on_actionLaunch_model_viewer_triggered();
|
void on_actionLaunch_model_viewer_triggered();
|
||||||
void on_actionExtract_PAK_triggered();
|
void on_actionExtract_PAK_triggered();
|
||||||
|
|
||||||
|
void LaunchCharacterEditor();
|
||||||
void About();
|
void About();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -229,6 +229,7 @@
|
|||||||
<string>Tools</string>
|
<string>Tools</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionLaunch_model_viewer"/>
|
<addaction name="actionLaunch_model_viewer"/>
|
||||||
|
<addaction name="ActionCharacterEditor"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -257,7 +258,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionLaunch_model_viewer">
|
<action name="actionLaunch_model_viewer">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Launch model viewer</string>
|
<string>Launch model editor</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="ActionAbout">
|
<action name="ActionAbout">
|
||||||
@ -265,6 +266,11 @@
|
|||||||
<string>About</string>
|
<string>About</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="ActionCharacterEditor">
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch character editor</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
75
src/Editor/CharacterEditor/CCharacterEditor.cpp
Normal file
75
src/Editor/CharacterEditor/CCharacterEditor.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "CCharacterEditor.h"
|
||||||
|
#include "ui_CCharacterEditor.h"
|
||||||
|
#include "Editor/UICommon.h"
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
CCharacterEditor::CCharacterEditor(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
, ui(new Ui::CCharacterEditor)
|
||||||
|
, mpScene(new CScene())
|
||||||
|
, mpCharNode(new CCharacterNode(mpScene, -1))
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->Viewport->SetNode(mpCharNode);
|
||||||
|
|
||||||
|
CCamera& rCamera = ui->Viewport->Camera();
|
||||||
|
rCamera.Snap(CVector3f(0, 3, 1));
|
||||||
|
rCamera.SetOrbit(CVector3f(0, 0, 1), 3.f);
|
||||||
|
rCamera.SetMoveSpeed(0.5f);
|
||||||
|
|
||||||
|
// Init UI
|
||||||
|
mpCharComboBox = new QComboBox(this);
|
||||||
|
mpCharComboBox->setMinimumWidth(175);
|
||||||
|
ui->ToolBar->addSeparator();
|
||||||
|
ui->ToolBar->addWidget(mpCharComboBox);
|
||||||
|
|
||||||
|
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
||||||
|
mRefreshTimer.start(0);
|
||||||
|
|
||||||
|
connect(mpCharComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetActiveCharacterIndex(int)));
|
||||||
|
connect(ui->ActionOpen, SIGNAL(triggered()), this, SLOT(Open()));
|
||||||
|
}
|
||||||
|
|
||||||
|
CCharacterEditor::~CCharacterEditor()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void CCharacterEditor::Open()
|
||||||
|
{
|
||||||
|
QString CharFilename = QFileDialog::getOpenFileName(this, "Open Character", "", "Animation Character Set (*.ANCS)");
|
||||||
|
if (CharFilename.isEmpty()) return;
|
||||||
|
|
||||||
|
TResPtr<CAnimSet> pSet = gResCache.GetResource(CharFilename.toStdString());
|
||||||
|
|
||||||
|
if (pSet)
|
||||||
|
{
|
||||||
|
mpCharNode->SetCharacter(pSet);
|
||||||
|
setWindowTitle("Prime World Editor - Character Editor: " + TO_QSTRING(pSet->Source()));
|
||||||
|
|
||||||
|
// Set up character combo box
|
||||||
|
mpCharComboBox->blockSignals(true);
|
||||||
|
mpCharComboBox->clear();
|
||||||
|
|
||||||
|
for (u32 iChar = 0; iChar < pSet->NumNodes(); iChar++)
|
||||||
|
mpCharComboBox->addItem( TO_QSTRING(pSet->NodeName(iChar)) );
|
||||||
|
|
||||||
|
SetActiveCharacterIndex(0);
|
||||||
|
mpCharComboBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
gResCache.Clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterEditor::RefreshViewport()
|
||||||
|
{
|
||||||
|
ui->Viewport->ProcessInput();
|
||||||
|
ui->Viewport->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterEditor::SetActiveCharacterIndex(int CharIndex)
|
||||||
|
{
|
||||||
|
mpCharNode->SetActiveCharSet((u32) CharIndex);
|
||||||
|
}
|
37
src/Editor/CharacterEditor/CCharacterEditor.h
Normal file
37
src/Editor/CharacterEditor/CCharacterEditor.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef CCHARACTEREDITOR_H
|
||||||
|
#define CCHARACTEREDITOR_H
|
||||||
|
|
||||||
|
#include "CCharacterEditorViewport.h"
|
||||||
|
#include <Core/Scene/CScene.h>
|
||||||
|
#include <Core/Scene/CCharacterNode.h>
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CCharacterEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CCharacterEditor : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Ui::CCharacterEditor *ui;
|
||||||
|
CScene *mpScene;
|
||||||
|
CCharacterNode *mpCharNode;
|
||||||
|
|
||||||
|
QComboBox *mpCharComboBox;
|
||||||
|
QTimer mRefreshTimer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CCharacterEditor(QWidget *parent = 0);
|
||||||
|
~CCharacterEditor();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void Open();
|
||||||
|
void RefreshViewport();
|
||||||
|
void SetActiveCharacterIndex(int CharIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCHARACTEREDITORWINDOW_H
|
93
src/Editor/CharacterEditor/CCharacterEditor.ui
Normal file
93
src/Editor/CharacterEditor/CCharacterEditor.ui
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CCharacterEditor</class>
|
||||||
|
<widget class="QMainWindow" name="CCharacterEditor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1054</width>
|
||||||
|
<height>634</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Prime World Editor - Character Editor</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="CentralWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="CCharacterEditorViewport" name="Viewport" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="MenuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1054</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="MenuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="ActionOpen"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="MenuFile"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="StatusBar"/>
|
||||||
|
<widget class="QToolBar" name="ToolBar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>toolBar</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="ActionOpen"/>
|
||||||
|
</widget>
|
||||||
|
<action name="ActionOpen">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../Icons.qrc">
|
||||||
|
<normaloff>:/icons/Open.png</normaloff>:/icons/Open.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+O</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CCharacterEditorViewport</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>Editor/CharacterEditor/CCharacterEditorViewport.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../Icons.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
45
src/Editor/CharacterEditor/CCharacterEditorViewport.cpp
Normal file
45
src/Editor/CharacterEditor/CCharacterEditorViewport.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "CCharacterEditorViewport.h"
|
||||||
|
|
||||||
|
CCharacterEditorViewport::CCharacterEditorViewport(QWidget *pParent /*= 0*/)
|
||||||
|
: CBasicViewport(pParent)
|
||||||
|
, mpCharNode(nullptr)
|
||||||
|
{
|
||||||
|
mpRenderer = new CRenderer();
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
mpRenderer->SetClearColor(CColor(0.3f, 0.3f, 0.3f));
|
||||||
|
mpRenderer->ToggleGrid(true);
|
||||||
|
|
||||||
|
mViewInfo.pRenderer = mpRenderer;
|
||||||
|
mViewInfo.pScene = nullptr;
|
||||||
|
mViewInfo.GameMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCharacterEditorViewport::~CCharacterEditorViewport()
|
||||||
|
{
|
||||||
|
delete mpRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterEditorViewport::SetNode(CCharacterNode *pNode)
|
||||||
|
{
|
||||||
|
mpCharNode = pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterEditorViewport::Paint()
|
||||||
|
{
|
||||||
|
mpRenderer->BeginFrame();
|
||||||
|
mCamera.LoadMatrices();
|
||||||
|
CDrawUtil::DrawGrid();
|
||||||
|
|
||||||
|
if (mpCharNode)
|
||||||
|
{
|
||||||
|
mpCharNode->AddToRenderer(mpRenderer, mViewInfo);
|
||||||
|
mpRenderer->RenderBuckets(mViewInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpRenderer->EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCharacterEditorViewport::OnResize()
|
||||||
|
{
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
}
|
20
src/Editor/CharacterEditor/CCharacterEditorViewport.h
Normal file
20
src/Editor/CharacterEditor/CCharacterEditorViewport.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef CCHARACTEREDITORVIEWPORT_H
|
||||||
|
#define CCHARACTEREDITORVIEWPORT_H
|
||||||
|
|
||||||
|
#include "Editor/CBasicViewport.h"
|
||||||
|
#include <Core/Scene/CCharacterNode.h>
|
||||||
|
|
||||||
|
class CCharacterEditorViewport : public CBasicViewport
|
||||||
|
{
|
||||||
|
CCharacterNode *mpCharNode;
|
||||||
|
CRenderer *mpRenderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CCharacterEditorViewport(QWidget *pParent = 0);
|
||||||
|
~CCharacterEditorViewport();
|
||||||
|
void SetNode(CCharacterNode *pNode);
|
||||||
|
void Paint();
|
||||||
|
void OnResize();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCHARACTEREDITORVIEWPORT_H
|
@ -156,7 +156,9 @@ HEADERS += \
|
|||||||
Undo/CPasteNodesCommand.h \
|
Undo/CPasteNodesCommand.h \
|
||||||
CPakToolDialog.h \
|
CPakToolDialog.h \
|
||||||
WorldEditor/CRepackInfoDialog.h \
|
WorldEditor/CRepackInfoDialog.h \
|
||||||
CAboutDialog.h
|
CAboutDialog.h \
|
||||||
|
CharacterEditor/CCharacterEditor.h \
|
||||||
|
CharacterEditor/CCharacterEditorViewport.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -213,7 +215,9 @@ SOURCES += \
|
|||||||
Undo/CCloneSelectionCommand.cpp \
|
Undo/CCloneSelectionCommand.cpp \
|
||||||
Undo/CPasteNodesCommand.cpp \
|
Undo/CPasteNodesCommand.cpp \
|
||||||
WorldEditor/CRepackInfoDialog.cpp \
|
WorldEditor/CRepackInfoDialog.cpp \
|
||||||
CAboutDialog.cpp
|
CAboutDialog.cpp \
|
||||||
|
CharacterEditor/CCharacterEditor.cpp \
|
||||||
|
CharacterEditor/CCharacterEditorViewport.cpp
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
@ -233,4 +237,5 @@ FORMS += \
|
|||||||
WorldEditor/CLinkDialog.ui \
|
WorldEditor/CLinkDialog.ui \
|
||||||
WorldEditor/CSelectInstanceDialog.ui \
|
WorldEditor/CSelectInstanceDialog.ui \
|
||||||
WorldEditor/CRepackInfoDialog.ui \
|
WorldEditor/CRepackInfoDialog.ui \
|
||||||
CAboutDialog.ui
|
CAboutDialog.ui \
|
||||||
|
CharacterEditor/CCharacterEditor.ui
|
||||||
|
Loading…
x
Reference in New Issue
Block a user