Added support for loading DCLN files and displaying them in the World Editor
This commit is contained in:
parent
19b3ae59be
commit
07d7f14dc7
|
@ -19,7 +19,7 @@ void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 AssetIndex, float Dista
|
|||
Intersection.Distance = Distance;
|
||||
}
|
||||
|
||||
SRayIntersection CRayCollisionTester::TestNodes()
|
||||
SRayIntersection CRayCollisionTester::TestNodes(ERenderOptions options)
|
||||
{
|
||||
// Sort nodes by distance from ray
|
||||
mBoxIntersectList.sort(
|
||||
|
@ -43,7 +43,7 @@ SRayIntersection CRayCollisionTester::TestNodes()
|
|||
|
||||
// Otherwise, more intersection tests...
|
||||
CSceneNode *pNode = Intersection.pNode;
|
||||
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex);
|
||||
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex, options);
|
||||
|
||||
if (MidResult.Hit)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "CVector3f.h"
|
||||
#include "SRayIntersection.h"
|
||||
#include "types.h"
|
||||
#include <Core/ERenderOptions.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
|
@ -21,7 +22,7 @@ public:
|
|||
~CRayCollisionTester();
|
||||
const CRay& Ray() const;
|
||||
void AddNode(CSceneNode *pNode, u32 AssetIndex, float Distance);
|
||||
SRayIntersection TestNodes();
|
||||
SRayIntersection TestNodes(ERenderOptions options);
|
||||
};
|
||||
|
||||
inline const CRay& CRayCollisionTester::Ray() const
|
||||
|
|
|
@ -262,12 +262,7 @@ std::pair<bool,float> RayTriangleIntersection(const CRay& Ray,
|
|||
if (!AllowBackfaces)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
else if (denom < - std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
if (false)
|
||||
return std::pair<bool,float>(false, 0);
|
||||
}
|
||||
else
|
||||
else if (denom >= - std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
// Parallel or triangle area is close to zero when
|
||||
// the plane normal not normalised.
|
||||
|
|
|
@ -20,7 +20,8 @@ u32 CRenderer::sNumRenderers = 0;
|
|||
// ************ INITIALIZATION ************
|
||||
CRenderer::CRenderer()
|
||||
{
|
||||
mOptions = eEnableUVScroll | eEnableBackfaceCull;
|
||||
mOptions = eDrawWorld | eDrawObjects | eDrawLights | eDrawSky |
|
||||
eEnableUVScroll | eEnableBackfaceCull;
|
||||
mBloomMode = eNoBloom;
|
||||
mDrawGrid = true;
|
||||
mInitialized = false;
|
||||
|
@ -53,9 +54,45 @@ void CRenderer::Init()
|
|||
}
|
||||
|
||||
// ************ GETTERS/SETTERS ************
|
||||
bool CRenderer::IsUVAnimationOn()
|
||||
ERenderOptions CRenderer::RenderOptions()
|
||||
{
|
||||
return ((mOptions & eUVScroll) != 0);
|
||||
return mOptions;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleWorld(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawWorld;
|
||||
else mOptions &= ~eDrawWorld;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleWorldCollision(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawWorldCollision;
|
||||
else mOptions &= ~eDrawWorldCollision;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleObjects(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawObjects;
|
||||
else mOptions &= ~eDrawObjects;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleObjectCollision(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawObjectCollision;
|
||||
else mOptions &= ~eDrawObjectCollision;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleLights(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawLights;
|
||||
else mOptions &= ~eDrawLights;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleSky(bool b)
|
||||
{
|
||||
if (b) mOptions |= eDrawSky;
|
||||
else mOptions &= ~eDrawSky;
|
||||
}
|
||||
|
||||
void CRenderer::ToggleBackfaceCull(bool b)
|
||||
|
|
|
@ -53,7 +53,13 @@ public:
|
|||
void Init();
|
||||
|
||||
// Getters/Setters
|
||||
bool IsUVAnimationOn();
|
||||
ERenderOptions RenderOptions();
|
||||
void ToggleWorld(bool b);
|
||||
void ToggleWorldCollision(bool b);
|
||||
void ToggleObjects(bool b);
|
||||
void ToggleObjectCollision(bool b);
|
||||
void ToggleLights(bool b);
|
||||
void ToggleSky(bool b);
|
||||
void ToggleBackfaceCull(bool b);
|
||||
void ToggleUVAnimation(bool b);
|
||||
void ToggleGrid(bool b);
|
||||
|
|
|
@ -150,6 +150,7 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
|
|||
else if (type == "STRG") Res = CStringLoader::LoadSTRG(mem);
|
||||
else if (type == "FONT") Res = CFontLoader::LoadFONT(mem);
|
||||
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
|
||||
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(mem);
|
||||
else SupportedFormat = false;
|
||||
|
||||
// Log errors
|
||||
|
@ -201,6 +202,7 @@ CResource* CResCache::GetResource(std::string ResPath)
|
|||
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
|
||||
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
|
||||
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
|
||||
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
|
||||
else SupportedFormat = false;
|
||||
|
||||
if (!Res) Res = new CResource(); // Default for unsupported formats
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
*/
|
||||
CSceneManager::CSceneManager()
|
||||
{
|
||||
mShowTerrain = true;
|
||||
mShowCollision = false;
|
||||
mShowObjects = true;
|
||||
mShowLights = true;
|
||||
mSplitTerrain = true;
|
||||
mNodeCount = 0;
|
||||
mpSceneRootNode = new CRootNode(this, nullptr);
|
||||
|
@ -56,7 +52,7 @@ CStaticNode* CSceneManager::AddStaticModel(CStaticModel *mdl)
|
|||
return node;
|
||||
}
|
||||
|
||||
CCollisionNode* CSceneManager::AddCollision(CCollisionMesh *mesh)
|
||||
CCollisionNode* CSceneManager::AddCollision(CCollisionMeshGroup *mesh)
|
||||
{
|
||||
if (mesh == nullptr) return nullptr;
|
||||
|
||||
|
@ -143,7 +139,7 @@ void CSceneManager::SetActiveArea(CGameArea* _area)
|
|||
switch (pObj->ObjectTypeID())
|
||||
{
|
||||
case 0x4E: // MP1 AreaAttributes ID
|
||||
case 0x52454141: // MP2 AreaAttributes ID ("REAA")
|
||||
case 0x52454141: // MP2/MP3/DKCR AreaAttributes ID ("REAA")
|
||||
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
|
||||
break;
|
||||
}
|
||||
|
@ -221,7 +217,9 @@ void CSceneManager::ClearScene()
|
|||
|
||||
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
|
||||
{
|
||||
if (mShowTerrain)
|
||||
ERenderOptions options = pRenderer->RenderOptions();
|
||||
|
||||
if (options & eDrawWorld)
|
||||
{
|
||||
for (u32 n = 0; n < mModelNodes.size(); n++)
|
||||
if (mModelNodes[n]->IsVisible())
|
||||
|
@ -232,29 +230,29 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
|
|||
mStaticNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowCollision)
|
||||
if (options & eDrawWorldCollision)
|
||||
{
|
||||
for (u32 n = 0; n < mCollisionNodes.size(); n++)
|
||||
if (mCollisionNodes[n]->IsVisible())
|
||||
mCollisionNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowObjects)
|
||||
{
|
||||
for (u32 n = 0; n < mScriptNodes.size(); n++)
|
||||
if (mScriptNodes[n]->IsVisible())
|
||||
mScriptNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if (mShowLights)
|
||||
if (options & eDrawLights)
|
||||
{
|
||||
for (u32 n = 0; n < mLightNodes.size(); n++)
|
||||
if (mLightNodes[n]->IsVisible())
|
||||
mLightNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
|
||||
if ((options & eDrawObjects) || (options & eDrawObjectCollision))
|
||||
{
|
||||
for (u32 n = 0; n < mScriptNodes.size(); n++)
|
||||
if (mScriptNodes[n]->IsVisible())
|
||||
mScriptNodes[n]->AddToRenderer(pRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
|
||||
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, ERenderOptions renderOptions)
|
||||
{
|
||||
// Terribly hacky stuff to avoid having tons of redundant code
|
||||
// because I'm too lazy to rewrite CSceneManager right now and fix it
|
||||
|
@ -267,7 +265,8 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
|
|||
reinterpret_cast<std::vector<CSceneNode*>*>(&mLightNodes),
|
||||
};
|
||||
bool NodesVisible[5] = {
|
||||
true, mShowTerrain, mShowCollision, mShowObjects, mShowLights
|
||||
true, ((renderOptions & eDrawWorld) != 0), ((renderOptions & eDrawWorldCollision) != 0),
|
||||
((renderOptions & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0), ((renderOptions & eDrawLights) != 0)
|
||||
};
|
||||
|
||||
// Less hacky stuff
|
||||
|
@ -284,7 +283,7 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
|
|||
vec[iNode]->RayAABoxIntersectTest(Tester);
|
||||
}
|
||||
|
||||
return Tester.TestNodes();
|
||||
return Tester.TestNodes(renderOptions);
|
||||
}
|
||||
|
||||
void CSceneManager::PickEnvironmentObjects()
|
||||
|
@ -343,43 +342,3 @@ CGameArea* CSceneManager::GetActiveArea()
|
|||
{
|
||||
return mpArea;
|
||||
}
|
||||
|
||||
void CSceneManager::SetWorld(bool on)
|
||||
{
|
||||
mShowTerrain = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetCollision(bool on)
|
||||
{
|
||||
mShowCollision = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetLights(bool on)
|
||||
{
|
||||
mShowLights = on;
|
||||
}
|
||||
|
||||
void CSceneManager::SetObjects(bool on)
|
||||
{
|
||||
mShowObjects = on;
|
||||
}
|
||||
|
||||
bool CSceneManager::IsTerrainEnabled()
|
||||
{
|
||||
return mShowTerrain;
|
||||
}
|
||||
|
||||
bool CSceneManager::IsCollisionEnabled()
|
||||
{
|
||||
return mShowCollision;
|
||||
}
|
||||
|
||||
bool CSceneManager::AreLightsEnabled()
|
||||
{
|
||||
return mShowLights;
|
||||
}
|
||||
|
||||
bool CSceneManager::AreScriptObjectsEnabled()
|
||||
{
|
||||
return mShowObjects;
|
||||
}
|
||||
|
|
|
@ -21,10 +21,6 @@
|
|||
|
||||
class CSceneManager
|
||||
{
|
||||
bool mShowTerrain;
|
||||
bool mShowCollision;
|
||||
bool mShowObjects;
|
||||
bool mShowLights;
|
||||
bool mSplitTerrain;
|
||||
|
||||
u32 mNodeCount;
|
||||
|
@ -55,14 +51,14 @@ public:
|
|||
// Scene Management
|
||||
CModelNode* AddModel(CModel *mdl);
|
||||
CStaticNode* AddStaticModel(CStaticModel *mdl);
|
||||
CCollisionNode* AddCollision(CCollisionMesh *mesh);
|
||||
CCollisionNode* AddCollision(CCollisionMeshGroup *mesh);
|
||||
CScriptNode* AddScriptObject(CScriptObject *obj);
|
||||
CLightNode* AddLight(CLight *Light);
|
||||
void SetActiveArea(CGameArea *_area);
|
||||
void SetActiveWorld(CWorld *_world);
|
||||
void ClearScene();
|
||||
void AddSceneToRenderer(CRenderer *pRenderer);
|
||||
SRayIntersection SceneRayCast(const CRay& Ray);
|
||||
SRayIntersection SceneRayCast(const CRay& Ray, ERenderOptions renderOptions);
|
||||
void PickEnvironmentObjects();
|
||||
CScriptNode* ScriptNodeByID(u32 InstanceID);
|
||||
CScriptNode* NodeForObject(CScriptObject *pObj);
|
||||
|
@ -71,17 +67,6 @@ public:
|
|||
// Setters/Getters
|
||||
CModel* GetActiveSkybox();
|
||||
CGameArea* GetActiveArea();
|
||||
|
||||
void SetBackfaceCulling(bool on);
|
||||
void SetWorld(bool on);
|
||||
void SetCollision(bool on);
|
||||
void SetObjects(bool on);
|
||||
void SetLights(bool on);
|
||||
bool IsBackfaceCullEnabled();
|
||||
bool IsTerrainEnabled();
|
||||
bool IsCollisionEnabled();
|
||||
bool AreLightsEnabled();
|
||||
bool AreScriptObjectsEnabled();
|
||||
};
|
||||
|
||||
#endif // CSCENEMANAGER_H
|
||||
|
|
|
@ -5,12 +5,18 @@
|
|||
|
||||
enum ERenderOptions
|
||||
{
|
||||
eEnableUVScroll = 0x1,
|
||||
eEnableBackfaceCull = 0x2,
|
||||
eEnableOccluders = 0x4,
|
||||
eNoMaterialSetup = 0x8,
|
||||
eEnableBloom = 0x10,
|
||||
eNoAlpha = 0x20
|
||||
eDrawWorld = 0x1,
|
||||
eDrawWorldCollision = 0x2,
|
||||
eDrawObjects = 0x4,
|
||||
eDrawObjectCollision = 0x8,
|
||||
eDrawLights = 0x10,
|
||||
eDrawSky = 0x20,
|
||||
eEnableUVScroll = 0x40,
|
||||
eEnableBackfaceCull = 0x80,
|
||||
eEnableOccluders = 0x100,
|
||||
eNoMaterialSetup = 0x200,
|
||||
eEnableBloom = 0x400,
|
||||
eNoAlpha = 0x800
|
||||
};
|
||||
DEFINE_ENUM_FLAGS(ERenderOptions)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "CCollisionMesh.h"
|
||||
#include <Core/CRenderer.h>
|
||||
|
||||
CCollisionMesh::CCollisionMesh() : CResource()
|
||||
CCollisionMesh::CCollisionMesh()
|
||||
{
|
||||
mVBO.SetVertexDesc(ePosition);
|
||||
mVertexCount = 0;
|
||||
|
@ -21,11 +21,6 @@ CCollisionMesh::~CCollisionMesh()
|
|||
}
|
||||
}
|
||||
|
||||
EResType CCollisionMesh::Type()
|
||||
{
|
||||
return eCollisionMesh;
|
||||
}
|
||||
|
||||
void CCollisionMesh::BufferGL()
|
||||
{
|
||||
if (mBuffered)
|
||||
|
@ -88,7 +83,7 @@ void CCollisionMesh::Draw()
|
|||
mVBO.Unbind();
|
||||
}
|
||||
|
||||
void CCollisionMesh::DrawLines()
|
||||
void CCollisionMesh::DrawWireframe()
|
||||
{
|
||||
if (!mBuffered) BufferGL();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <OpenGL/CIndexBuffer.h>
|
||||
#include "CResource.h"
|
||||
|
||||
class CCollisionMesh : public CResource
|
||||
class CCollisionMesh
|
||||
{
|
||||
friend class CCollisionLoader;
|
||||
|
||||
|
@ -79,11 +79,10 @@ class CCollisionMesh : public CResource
|
|||
public:
|
||||
CCollisionMesh();
|
||||
~CCollisionMesh();
|
||||
EResType Type();
|
||||
|
||||
void BufferGL();
|
||||
void Draw();
|
||||
void DrawLines();
|
||||
void DrawWireframe();
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONMESH_H
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#include "CCollisionMeshGroup.h"
|
||||
|
||||
CCollisionMeshGroup::CCollisionMeshGroup()
|
||||
{
|
||||
}
|
||||
|
||||
CCollisionMeshGroup::~CCollisionMeshGroup()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
EResType CCollisionMeshGroup::Type()
|
||||
{
|
||||
return eCollisionMeshGroup;
|
||||
}
|
||||
|
||||
u32 CCollisionMeshGroup::NumMeshes()
|
||||
{
|
||||
return mMeshes.size();
|
||||
}
|
||||
|
||||
CCollisionMesh* CCollisionMeshGroup::MeshByIndex(u32 index)
|
||||
{
|
||||
return mMeshes[index];
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::AddMesh(CCollisionMesh *pMesh)
|
||||
{
|
||||
mMeshes.push_back(pMesh);
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::Draw()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
(*it)->Draw();
|
||||
}
|
||||
|
||||
void CCollisionMeshGroup::DrawWireframe()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
(*it)->DrawWireframe();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef CCOLLISIONMESHGROUP_H
|
||||
#define CCOLLISIONMESHGROUP_H
|
||||
|
||||
#include "CResource.h"
|
||||
#include "CCollisionMesh.h"
|
||||
#include <Core/CToken.h>
|
||||
#include <vector>
|
||||
|
||||
class CCollisionMeshGroup : public CResource
|
||||
{
|
||||
std::vector<CCollisionMesh*> mMeshes;
|
||||
|
||||
public:
|
||||
CCollisionMeshGroup();
|
||||
~CCollisionMeshGroup();
|
||||
EResType Type();
|
||||
|
||||
u32 NumMeshes();
|
||||
CCollisionMesh* MeshByIndex(u32 index);
|
||||
void AddMesh(CCollisionMesh *pMesh);
|
||||
void Draw();
|
||||
void DrawWireframe();
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONMESHGROUP_H
|
|
@ -135,7 +135,7 @@ CStaticModel* CGameArea::GetStaticModel(u32 mdl)
|
|||
return mStaticTerrainModels[mdl];
|
||||
}
|
||||
|
||||
CCollisionMesh* CGameArea::GetCollision()
|
||||
CCollisionMeshGroup* CGameArea::GetCollision()
|
||||
{
|
||||
return mCollision;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef CGAMEAREA_H
|
||||
#define CGAMEAREA_H
|
||||
|
||||
#include "CCollisionMesh.h"
|
||||
#include "CCollisionMeshGroup.h"
|
||||
#include "CLight.h"
|
||||
#include "CMaterialSet.h"
|
||||
#include "model/CModel.h"
|
||||
|
@ -32,7 +32,7 @@ class CGameArea : public CResource
|
|||
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
||||
|
||||
// Collision
|
||||
CCollisionMesh *mCollision;
|
||||
CCollisionMeshGroup *mCollision;
|
||||
// Lights
|
||||
std::vector<std::vector<CLight*>> mLightLayers;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
u32 GetStaticModelCount();
|
||||
CModel* GetTerrainModel(u32 mdl);
|
||||
CStaticModel* GetStaticModel(u32 mdl);
|
||||
CCollisionMesh* GetCollision();
|
||||
CCollisionMeshGroup* GetCollision();
|
||||
u32 GetScriptLayerCount();
|
||||
CScriptLayer* GetScriptLayer(u32 index);
|
||||
CScriptLayer* GetGeneratorLayer();
|
||||
|
|
|
@ -72,7 +72,7 @@ EResType CResource::ResTypeForExtension(CFourCC Extension)
|
|||
if (Extension == "CSMP") return eAudioSample;
|
||||
if (Extension == "CSNG") return eMidi;
|
||||
if (Extension == "CTWK") return eTweak;
|
||||
if (Extension == "DCLN") return eCollisionMesh;
|
||||
if (Extension == "DCLN") return eCollisionMeshGroup;
|
||||
if (Extension == "DGRP") return eDependencyGroup;
|
||||
if (Extension == "DSP ") return eMusicTrack;
|
||||
if (Extension == "DUMB") return eDataDump;
|
||||
|
|
|
@ -13,7 +13,7 @@ enum EResType
|
|||
eAudioStream = 7,
|
||||
eAudioTable = 8,
|
||||
eCharacter = 9,
|
||||
eCollisionMesh = 10,
|
||||
eCollisionMeshGroup = 10,
|
||||
eCollisionResponse = 11,
|
||||
eDataDump = 12,
|
||||
eDecal = 13,
|
||||
|
|
|
@ -262,8 +262,15 @@ void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp, const std::stri
|
|||
|
||||
for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++)
|
||||
{
|
||||
std::string type = (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams ? "animparams" : "model");
|
||||
std::string source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property");
|
||||
std::string type;
|
||||
|
||||
switch (it->AssetType)
|
||||
{
|
||||
case CScriptTemplate::SEditorAsset::eModel: type = "model"; break;
|
||||
case CScriptTemplate::SEditorAsset::eAnimParams: type = "animparams"; break;
|
||||
case CScriptTemplate::SEditorAsset::eCollision: type = "collision"; break;
|
||||
}
|
||||
|
||||
s32 force = -1;
|
||||
if (it->AssetSource == CScriptTemplate::SEditorAsset::eAnimParams) force = it->ForceNodeIndex;
|
||||
|
|
|
@ -6,131 +6,213 @@ CCollisionLoader::CCollisionLoader()
|
|||
{
|
||||
}
|
||||
|
||||
CCollisionMesh* CCollisionLoader::LoadAreaCollision(CInputStream& MREA)
|
||||
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(CInputStream&)
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::ParseOctreeBranch(CInputStream&)
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(CInputStream&)
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CCollisionLoader::ParseOBBNode(CInputStream& DCLN)
|
||||
{
|
||||
bool b = false;
|
||||
|
||||
while (b == false)
|
||||
{
|
||||
DCLN.Seek(0x3C, SEEK_CUR);
|
||||
b = (DCLN.ReadByte() == 1);
|
||||
if (!b) ParseOBBNode(DCLN);
|
||||
}
|
||||
|
||||
u32 numFaces = DCLN.ReadLong();
|
||||
DCLN.Seek(numFaces * 2, SEEK_CUR);
|
||||
}
|
||||
|
||||
void CCollisionLoader::ReadPropertyFlags(CInputStream& src)
|
||||
{
|
||||
CCollisionMesh::SCollisionProperties property;
|
||||
|
||||
if (mVersion == ePrime)
|
||||
{
|
||||
u32 flag = src.ReadLong();
|
||||
property.Invert = (flag >> 25) & 0x1;
|
||||
}
|
||||
|
||||
if (mVersion == eEchoes)
|
||||
{
|
||||
u64 flag = src.ReadLongLong();
|
||||
property.Invert = (flag >> 24) & 0x1;
|
||||
}
|
||||
|
||||
mProperties.push_back(property);
|
||||
}
|
||||
|
||||
void CCollisionLoader::LoadCollisionIndices(CInputStream &file, bool buildAABox)
|
||||
{
|
||||
// Properties
|
||||
u32 propSetCount = file.ReadLong();
|
||||
for (u32 iProp = 0; iProp < propSetCount; iProp++)
|
||||
ReadPropertyFlags(file);
|
||||
|
||||
// Property indices for vertices/lines/faces
|
||||
u32 vtxIndexCount = file.ReadLong();
|
||||
std::vector<u8> vtxIndices(vtxIndexCount);
|
||||
file.ReadBytes(vtxIndices.data(), vtxIndices.size());
|
||||
|
||||
u32 lineIndexCount = file.ReadLong();
|
||||
std::vector<u8> lineIndices(lineIndexCount);
|
||||
file.ReadBytes(lineIndices.data(), lineIndices.size());
|
||||
|
||||
u32 faceIndexCount = file.ReadLong();
|
||||
std::vector<u8> faceIndices(faceIndexCount);
|
||||
file.ReadBytes(faceIndices.data(), faceIndices.size());
|
||||
|
||||
// Lines
|
||||
mpMesh->mLineCount = file.ReadLong();
|
||||
mpMesh->mCollisionLines.resize(mpMesh->mLineCount);
|
||||
for (u32 iLine = 0; iLine < mpMesh->mLineCount; iLine++)
|
||||
{
|
||||
CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine];
|
||||
pLine->Vertices[0] = file.ReadShort();
|
||||
pLine->Vertices[1] = file.ReadShort();
|
||||
pLine->Properties = mProperties[lineIndices[iLine]];
|
||||
}
|
||||
|
||||
// Faces
|
||||
mpMesh->mFaceCount = file.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
|
||||
mpMesh->mCollisionFaces.resize(mpMesh->mFaceCount);
|
||||
|
||||
for (u32 iFace = 0; iFace < mpMesh->mFaceCount; iFace++)
|
||||
{
|
||||
CCollisionMesh::CCollisionFace *pFace = &mpMesh->mCollisionFaces[iFace];
|
||||
pFace->Lines[0] = file.ReadShort();
|
||||
pFace->Lines[1] = file.ReadShort();
|
||||
pFace->Lines[2] = file.ReadShort();
|
||||
pFace->Properties = mProperties[faceIndices[iFace]];
|
||||
}
|
||||
|
||||
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
|
||||
if (mVersion == eEchoes)
|
||||
{
|
||||
u32 unknownCount = file.ReadLong();
|
||||
file.Seek(unknownCount * 2, SEEK_CUR);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
mpMesh->mVertexCount = file.ReadLong();
|
||||
mpMesh->mCollisionVertices.resize(mpMesh->mVertexCount);
|
||||
CAABox bounds;
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mpMesh->mVertexCount; iVtx++)
|
||||
{
|
||||
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
|
||||
pVtx->Pos = CVector3f(file);
|
||||
pVtx->Properties = mProperties[vtxIndices[iVtx]];
|
||||
if (buildAABox) bounds.ExpandBounds(pVtx->Pos);
|
||||
}
|
||||
if (buildAABox) mpMesh->mAABox = bounds;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(CInputStream& MREA)
|
||||
{
|
||||
if (!MREA.IsValid()) return nullptr;
|
||||
CCollisionLoader loader;
|
||||
|
||||
MREA.Seek(0x8, SEEK_CUR);
|
||||
u32 deafbabe = MREA.ReadLong();
|
||||
if (deafbabe != 0xdeafbabe)
|
||||
if (deafbabe != 0xDEAFBABE)
|
||||
{
|
||||
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 version = MREA.ReadLong();
|
||||
loader.version = ECollisionVersion(version);
|
||||
if ((loader.version != Prime) && (loader.version != Echoes))
|
||||
loader.mVersion = GetFormatVersion(version);
|
||||
if ((loader.mVersion != ePrime) && (loader.mVersion != eEchoes))
|
||||
{
|
||||
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
loader.mesh = new CCollisionMesh;
|
||||
CCollisionMesh *cmesh = loader.mesh;
|
||||
loader.mpGroup = new CCollisionMeshGroup;
|
||||
loader.mpMesh = new CCollisionMesh;
|
||||
|
||||
// Octree - structure is known, but not coding this right now
|
||||
cmesh->mAABox = CAABox(MREA);
|
||||
loader.mpMesh->mAABox = CAABox(MREA);
|
||||
MREA.Seek(0x4, SEEK_CUR);
|
||||
u32 octreeSize = MREA.ReadLong();
|
||||
MREA.Seek(octreeSize, SEEK_CUR); // Skipping the octree for now
|
||||
cmesh->mOctreeLoaded = false;
|
||||
loader.mpMesh->mOctreeLoaded = false;
|
||||
|
||||
// Properties
|
||||
u32 propertySetCount = MREA.ReadLong();
|
||||
for (u32 p = 0; p < propertySetCount; p++)
|
||||
loader.readPropertyFlags(MREA);
|
||||
|
||||
// Property indices for vertices/lines/faces
|
||||
u32 vtxIndexCount = MREA.ReadLong();
|
||||
std::vector<u8> vtxIndices(vtxIndexCount);
|
||||
MREA.ReadBytes(vtxIndices.data(), vtxIndices.size());
|
||||
|
||||
u32 lineIndexCount = MREA.ReadLong();
|
||||
std::vector<u8> lineIndices(lineIndexCount);
|
||||
MREA.ReadBytes(lineIndices.data(), lineIndices.size());
|
||||
|
||||
u32 faceIndexCount = MREA.ReadLong();
|
||||
std::vector<u8> faceIndices(faceIndexCount);
|
||||
MREA.ReadBytes(faceIndices.data(), faceIndices.size());
|
||||
|
||||
// Lines
|
||||
cmesh->mLineCount = MREA.ReadLong();
|
||||
cmesh->mCollisionLines.resize(cmesh->mLineCount);
|
||||
for (u32 l = 0; l < cmesh->mLineCount; l++)
|
||||
{
|
||||
CCollisionMesh::CCollisionLine *Line = &cmesh->mCollisionLines[l];
|
||||
Line->Vertices[0] = MREA.ReadShort();
|
||||
Line->Vertices[1] = MREA.ReadShort();
|
||||
Line->Properties = loader.properties[lineIndices[l]];
|
||||
// Read collision indices and return
|
||||
loader.LoadCollisionIndices(MREA, false);
|
||||
loader.mpGroup->AddMesh(loader.mpMesh);
|
||||
return loader.mpGroup;
|
||||
}
|
||||
|
||||
// Faces
|
||||
cmesh->mFaceCount = MREA.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
|
||||
cmesh->mCollisionFaces.resize(cmesh->mFaceCount);
|
||||
for (u32 f = 0; f < cmesh->mFaceCount; f++)
|
||||
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(CInputStream &DCLN)
|
||||
{
|
||||
CCollisionMesh::CCollisionFace *face = &cmesh->mCollisionFaces[f];
|
||||
face->Lines[0] = MREA.ReadShort();
|
||||
face->Lines[1] = MREA.ReadShort();
|
||||
face->Lines[2] = MREA.ReadShort();
|
||||
face->Properties = loader.properties[faceIndices[f]];
|
||||
}
|
||||
if (!DCLN.IsValid()) return nullptr;
|
||||
|
||||
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
|
||||
if (loader.version == Echoes)
|
||||
CCollisionLoader loader;
|
||||
loader.mpGroup = new CCollisionMeshGroup;
|
||||
|
||||
u32 numMeshes = DCLN.ReadLong();
|
||||
|
||||
for (u32 iMesh = 0; iMesh < numMeshes; iMesh++)
|
||||
{
|
||||
u32 unknown_count = MREA.ReadLong();
|
||||
MREA.Seek(unknown_count * 2, SEEK_CUR);
|
||||
}
|
||||
u32 deafbabe = DCLN.ReadLong();
|
||||
|
||||
// Vertices
|
||||
cmesh->mVertexCount = MREA.ReadLong();
|
||||
cmesh->mCollisionVertices.resize(cmesh->mVertexCount);
|
||||
for (u32 v = 0; v < cmesh->mVertexCount; v++)
|
||||
if (deafbabe != 0xDEAFBABE)
|
||||
{
|
||||
CCollisionMesh::CCollisionVertex *vtx = &cmesh->mCollisionVertices[v];
|
||||
vtx->Pos = CVector3f(MREA);
|
||||
vtx->Properties = loader.properties[vtxIndices[v]];
|
||||
}
|
||||
|
||||
return cmesh;
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionOctree* CCollisionLoader::parseOctree(CInputStream&)
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
|
||||
delete loader.mpGroup;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::parseOctreeBranch(CInputStream&)
|
||||
u32 version = DCLN.ReadLong();
|
||||
loader.mVersion = GetFormatVersion(version);
|
||||
|
||||
if ((loader.mVersion != ePrime) && (loader.mVersion != eEchoes))
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::parseOctreeLeaf(CInputStream&)
|
||||
{
|
||||
// Not using: Parameter 1 (CInputStream& - src)
|
||||
return nullptr;
|
||||
loader.mpMesh = new CCollisionMesh;
|
||||
loader.mpMesh->mOctreeLoaded = false;
|
||||
|
||||
// Read indices and return
|
||||
DCLN.Seek(0x4, SEEK_CUR);
|
||||
loader.LoadCollisionIndices(DCLN, true);
|
||||
loader.mpGroup->AddMesh(loader.mpMesh);
|
||||
|
||||
// Parse OBB tree
|
||||
loader.ParseOBBNode(DCLN);
|
||||
}
|
||||
return loader.mpGroup;
|
||||
}
|
||||
|
||||
void CCollisionLoader::readPropertyFlags(CInputStream& src)
|
||||
EGame CCollisionLoader::GetFormatVersion(u32 version)
|
||||
{
|
||||
CCollisionMesh::SCollisionProperties property;
|
||||
|
||||
if (version == Prime)
|
||||
switch (version)
|
||||
{
|
||||
u32 flag = src.ReadLong();
|
||||
property.Invert = (flag >> 25) & 0x1;
|
||||
case 0x2: return ePrime;
|
||||
case 0x3: return ePrime;
|
||||
case 0x4: return eEchoes;
|
||||
case 0x5: return eReturns;
|
||||
default: return eUnknownVersion;
|
||||
}
|
||||
|
||||
if (version == Echoes)
|
||||
{
|
||||
u64 flag = src.ReadLongLong();
|
||||
property.Invert = (flag >> 24) & 0x1;
|
||||
}
|
||||
|
||||
properties.push_back(property);
|
||||
}
|
||||
|
|
|
@ -2,30 +2,28 @@
|
|||
#define CCOLLISIONLOADER_H
|
||||
|
||||
#include "../CCollisionMesh.h"
|
||||
#include "../CCollisionMeshGroup.h"
|
||||
#include "../EFormatVersion.h"
|
||||
|
||||
class CCollisionLoader
|
||||
{
|
||||
enum ECollisionVersion;
|
||||
|
||||
CCollisionMesh *mesh;
|
||||
ECollisionVersion version;
|
||||
std::vector<CCollisionMesh::SCollisionProperties> properties;
|
||||
|
||||
enum ECollisionVersion
|
||||
{
|
||||
Prime = 0x3,
|
||||
Echoes = 0x4,
|
||||
DonkeyKongCountryReturns = 0x5
|
||||
};
|
||||
CCollisionMeshGroup *mpGroup;
|
||||
CCollisionMesh *mpMesh;
|
||||
EGame mVersion;
|
||||
std::vector<CCollisionMesh::SCollisionProperties> mProperties;
|
||||
|
||||
CCollisionLoader();
|
||||
CCollisionMesh::CCollisionOctree* parseOctree(CInputStream& src);
|
||||
CCollisionMesh::CCollisionOctree::SBranch* parseOctreeBranch(CInputStream& src);
|
||||
CCollisionMesh::CCollisionOctree::SLeaf* parseOctreeLeaf(CInputStream& src);
|
||||
void readPropertyFlags(CInputStream& src);
|
||||
CCollisionMesh::CCollisionOctree* ParseOctree(CInputStream& src);
|
||||
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(CInputStream& src);
|
||||
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(CInputStream& src);
|
||||
void ParseOBBNode(CInputStream& DCLN);
|
||||
void ReadPropertyFlags(CInputStream& src);
|
||||
void LoadCollisionIndices(CInputStream& file, bool buildAABox);
|
||||
|
||||
public:
|
||||
static CCollisionMesh* LoadAreaCollision(CInputStream& MREA);
|
||||
static CCollisionMeshGroup* LoadAreaCollision(CInputStream& MREA);
|
||||
static CCollisionMeshGroup* LoadDCLN(CInputStream& DCLN);
|
||||
static EGame GetFormatVersion(u32 version);
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONLOADER_H
|
||||
|
|
|
@ -221,6 +221,8 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(tinyxml2::XMLDocument *pDoc
|
|||
asset.AssetType = CScriptTemplate::SEditorAsset::eAnimParams;
|
||||
else if (strcmp(pAsset->Name(), "model") == 0)
|
||||
asset.AssetType = CScriptTemplate::SEditorAsset::eModel;
|
||||
else if (strcmp(pAsset->Name(), "collision") == 0)
|
||||
asset.AssetType = CScriptTemplate::SEditorAsset::eCollision;
|
||||
else
|
||||
{
|
||||
pAsset = pAsset->NextSiblingElement();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <Common/Math.h>
|
||||
#include <Core/CDrawUtil.h>
|
||||
|
||||
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThreshold)
|
||||
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, bool allowBackfaces, float LineThreshold)
|
||||
{
|
||||
bool Hit = false;
|
||||
float HitDist;
|
||||
|
@ -61,7 +61,7 @@ std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThresho
|
|||
}
|
||||
|
||||
// Intersection test
|
||||
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC);
|
||||
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC, allowBackfaces);
|
||||
|
||||
if (TriResult.first)
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ struct SSurface
|
|||
TriangleCount = 0;
|
||||
}
|
||||
|
||||
std::pair<bool,float> IntersectsRay(const CRay& Ray, float LineThreshold = 0.02f);
|
||||
std::pair<bool,float> IntersectsRay(const CRay& Ray, bool allowBackfaces = false, float LineThreshold = 0.02f);
|
||||
};
|
||||
|
||||
#endif // SSURFACE_H
|
||||
|
|
|
@ -9,6 +9,8 @@ CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemp
|
|||
mpLayer = pLayer;
|
||||
mpProperties = nullptr;
|
||||
mpTemplate->AddObject(this);
|
||||
mpDisplayModel = nullptr;
|
||||
mpCollision = nullptr;
|
||||
}
|
||||
|
||||
CScriptObject::~CScriptObject()
|
||||
|
@ -35,6 +37,7 @@ void CScriptObject::EvaluateProperties()
|
|||
mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
|
||||
mVolumeShape = mpTemplate->VolumeShape(this);
|
||||
EvaluateDisplayModel();
|
||||
EvaluateCollisionModel();
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateDisplayModel()
|
||||
|
@ -43,6 +46,12 @@ void CScriptObject::EvaluateDisplayModel()
|
|||
mModelToken = CToken(mpDisplayModel);
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateCollisionModel()
|
||||
{
|
||||
mpCollision = mpTemplate->FindCollision(mpProperties);
|
||||
mCollisionToken = CToken(mpCollision);
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
CPropertyBase* CScriptObject::PropertyByIndex(u32 index) const
|
||||
{
|
||||
|
@ -189,6 +198,11 @@ CModel* CScriptObject::GetDisplayModel() const
|
|||
return mpDisplayModel;
|
||||
}
|
||||
|
||||
CCollisionMeshGroup* CScriptObject::GetCollision() const
|
||||
{
|
||||
return mpCollision;
|
||||
}
|
||||
|
||||
EVolumeShape CScriptObject::VolumeShape() const
|
||||
{
|
||||
return mVolumeShape;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "CPropertyTemplate.h"
|
||||
#include "CScriptTemplate.h"
|
||||
#include "../model/CModel.h"
|
||||
#include "../CCollisionMeshGroup.h"
|
||||
|
||||
class CGameArea;
|
||||
class CScriptLayer;
|
||||
|
@ -31,7 +32,9 @@ class CScriptObject
|
|||
CBoolProperty *mpActive;
|
||||
CPropertyStruct *mpLightParameters;
|
||||
CModel *mpDisplayModel;
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
CToken mModelToken;
|
||||
CToken mCollisionToken;
|
||||
EVolumeShape mVolumeShape;
|
||||
|
||||
public:
|
||||
|
@ -41,6 +44,7 @@ public:
|
|||
void CopyFromTemplate(CScriptTemplate *pTemp, u32 propCount);
|
||||
void EvaluateProperties();
|
||||
void EvaluateDisplayModel();
|
||||
void EvaluateCollisionModel();
|
||||
|
||||
CScriptTemplate* Template() const;
|
||||
CMasterTemplate* MasterTemplate() const;
|
||||
|
@ -69,6 +73,7 @@ public:
|
|||
void SetActive(bool isActive);
|
||||
CPropertyStruct* LightParameters() const;
|
||||
CModel* GetDisplayModel() const;
|
||||
CCollisionMeshGroup* GetCollision() const;
|
||||
EVolumeShape VolumeShape() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -242,6 +242,39 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties)
|
||||
{
|
||||
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
|
||||
{
|
||||
CResource *pRes = nullptr;
|
||||
|
||||
// File
|
||||
if (it->AssetSource == SEditorAsset::eFile)
|
||||
{
|
||||
std::string path = "../resources/" + it->AssetLocation;
|
||||
pRes = gResCache.GetResource(path);
|
||||
}
|
||||
|
||||
// Property
|
||||
else
|
||||
{
|
||||
CPropertyBase *pProp = pProperties->PropertyByIDString(it->AssetLocation);
|
||||
|
||||
if (pProp->Type() == eFileProperty)
|
||||
{
|
||||
CFileProperty *pFile = static_cast<CFileProperty*>(pProp);
|
||||
pRes = pFile->Get();
|
||||
}
|
||||
}
|
||||
|
||||
// Verify resource exists + is correct type
|
||||
if (pRes && (pRes->Type() == eCollisionMeshGroup))
|
||||
return static_cast<CCollisionMeshGroup*>(pRes);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CScriptTemplate::HasPosition()
|
||||
{
|
||||
return (!mPositionIDString.empty());
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <vector>
|
||||
#include <tinyxml2.h>
|
||||
#include <Resource/model/CModel.h>
|
||||
#include <Resource/CCollisionMeshGroup.h>
|
||||
|
||||
class CMasterTemplate;
|
||||
class CScriptObject;
|
||||
|
@ -47,7 +48,7 @@ private:
|
|||
struct SEditorAsset
|
||||
{
|
||||
enum {
|
||||
eModel, eAnimParams
|
||||
eModel, eAnimParams, eCollision
|
||||
} AssetType;
|
||||
|
||||
enum {
|
||||
|
@ -114,6 +115,7 @@ public:
|
|||
CBoolProperty* FindActive(CPropertyStruct *pProperties);
|
||||
CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties);
|
||||
CModel* FindDisplayModel(CPropertyStruct *pProperties);
|
||||
CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties);
|
||||
bool HasPosition();
|
||||
|
||||
// Object Tracking
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
#include <Core/CGraphics.h>
|
||||
#include <Core/CRenderer.h>
|
||||
|
||||
CCollisionNode::CCollisionNode(CSceneManager *pScene, CSceneNode *pParent, CCollisionMesh *pMesh)
|
||||
CCollisionNode::CCollisionNode(CSceneManager *pScene, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
|
||||
: CSceneNode(pScene, pParent)
|
||||
{
|
||||
mpMesh = pMesh;
|
||||
mMeshToken = CToken(pMesh);
|
||||
SetCollision(pCollision);
|
||||
SetName("Collision");
|
||||
}
|
||||
|
||||
|
@ -18,7 +17,7 @@ ENodeType CCollisionNode::NodeType()
|
|||
|
||||
void CCollisionNode::AddToRenderer(CRenderer *pRenderer)
|
||||
{
|
||||
if (!mpMesh) return;
|
||||
if (!mpCollision) return;
|
||||
|
||||
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
|
||||
|
||||
|
@ -29,7 +28,7 @@ void CCollisionNode::AddToRenderer(CRenderer *pRenderer)
|
|||
void CCollisionNode::Draw(ERenderOptions)
|
||||
{
|
||||
// Not using parameter 1 (ERenderOptions - Options)
|
||||
if (!mpMesh) return;
|
||||
if (!mpCollision) return;
|
||||
|
||||
LoadModelMatrix();
|
||||
|
||||
|
@ -38,9 +37,9 @@ void CCollisionNode::Draw(ERenderOptions)
|
|||
glDepthMask(GL_TRUE);
|
||||
|
||||
CDrawUtil::UseCollisionShader();
|
||||
mpMesh->Draw();
|
||||
mpCollision->Draw();
|
||||
CDrawUtil::UseColorShader(CColor::skTransparentBlack);
|
||||
mpMesh->DrawLines();
|
||||
mpCollision->DrawWireframe();
|
||||
}
|
||||
|
||||
void CCollisionNode::DrawAsset(ERenderOptions, u32)
|
||||
|
@ -49,10 +48,16 @@ void CCollisionNode::DrawAsset(ERenderOptions, u32)
|
|||
// Not using parameter 2 (u32 - asset)
|
||||
}
|
||||
|
||||
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
||||
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
|
||||
{
|
||||
// todo
|
||||
SRayIntersection Result;
|
||||
Result.Hit = false;
|
||||
return Result;
|
||||
}
|
||||
|
||||
void CCollisionNode::SetCollision(CCollisionMeshGroup *pCollision)
|
||||
{
|
||||
mpCollision = pCollision;
|
||||
mCollisionToken = CToken(pCollision);
|
||||
}
|
||||
|
|
|
@ -2,20 +2,21 @@
|
|||
#define CCOLLISIONNODE_H
|
||||
|
||||
#include "CSceneNode.h"
|
||||
#include <Resource/CCollisionMesh.h>
|
||||
#include <Resource/CCollisionMeshGroup.h>
|
||||
|
||||
class CCollisionNode : public CSceneNode
|
||||
{
|
||||
CCollisionMesh *mpMesh;
|
||||
CToken mMeshToken;
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
CToken mCollisionToken;
|
||||
|
||||
public:
|
||||
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMesh *pMesh = 0);
|
||||
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
|
||||
ENodeType NodeType();
|
||||
void AddToRenderer(CRenderer *pRenderer);
|
||||
void Draw(ERenderOptions Options);
|
||||
void DrawAsset(ERenderOptions Options, u32 asset);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
|
||||
void SetCollision(CCollisionMeshGroup *pCollision);
|
||||
};
|
||||
|
||||
#endif // CCOLLISIONNODE_H
|
||||
|
|
|
@ -57,10 +57,12 @@ void CLightNode::DrawAsset(ERenderOptions, u32)
|
|||
// Not using parameter 2 (u32 - asset)
|
||||
}
|
||||
|
||||
SRayIntersection CLightNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
||||
SRayIntersection CLightNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
|
||||
{
|
||||
// Needs redo if I ever make these look like something other than boxes
|
||||
if (AABox().IsPointInBox(Ray.Origin()))
|
||||
bool allowBackfaces = ((options & eEnableBackfaceCull) == 0);
|
||||
|
||||
if (!allowBackfaces && (AABox().IsPointInBox(Ray.Origin())))
|
||||
return SRayIntersection(false, 0.f, nullptr, 0);
|
||||
|
||||
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
void AddToRenderer(CRenderer *pRenderer);
|
||||
void Draw(ERenderOptions Options);
|
||||
void DrawAsset(ERenderOptions Options, u32 asset);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
|
||||
CLight* Light();
|
||||
};
|
||||
|
||||
|
|
|
@ -105,14 +105,14 @@ void CModelNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
|
|||
}
|
||||
}
|
||||
|
||||
SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
||||
SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
|
||||
{
|
||||
SRayIntersection out;
|
||||
out.pNode = this;
|
||||
out.AssetIndex = AssetID;
|
||||
|
||||
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
|
||||
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay);
|
||||
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
|
||||
|
||||
if (Result.first)
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
virtual void Draw(ERenderOptions Options);
|
||||
virtual void DrawAsset(ERenderOptions Options, u32 asset);
|
||||
virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester);
|
||||
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
|
||||
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
|
||||
|
||||
void SetModel(CModel *pModel);
|
||||
void SetMatSet(u32 MatSet);
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
inline void DrawAsset(ERenderOptions, u32) {}
|
||||
inline void RayAABoxIntersectTest(CRayCollisionTester &) {}
|
||||
|
||||
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32) {
|
||||
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, ERenderOptions) {
|
||||
return SRayIntersection(false, 0.f, nullptr, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
virtual void DrawAsset(ERenderOptions options, u32 asset) = 0;
|
||||
virtual void DrawSelection();
|
||||
virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester);
|
||||
virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID) = 0;
|
||||
virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID, ERenderOptions options) = 0;
|
||||
virtual bool IsVisible() const;
|
||||
|
||||
void Unparent();
|
||||
|
|
|
@ -16,12 +16,14 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
|
|||
// Evaluate instance
|
||||
mpInstance = pObject;
|
||||
mpActiveModel = nullptr;
|
||||
mpCollisionNode = new CCollisionNode(pScene, this);
|
||||
mpCollisionNode->SetInheritance(true, true, false);
|
||||
|
||||
if (mpInstance)
|
||||
{
|
||||
CScriptTemplate *pTemp = mpInstance->Template();
|
||||
|
||||
mpActiveModel = mpInstance->GetDisplayModel();
|
||||
// Determine transform
|
||||
mPosition = mpInstance->Position();
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
SetName("[" + pTemp->TemplateName(mpInstance->NumProperties()) + "] " + mpInstance->InstanceName());
|
||||
|
@ -31,10 +33,16 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
|
|||
|
||||
MarkTransformChanged();
|
||||
|
||||
// Determine display assets
|
||||
mpActiveModel = mpInstance->GetDisplayModel();
|
||||
mModelToken = CToken(mpActiveModel);
|
||||
|
||||
mpCollisionNode->SetCollision(mpInstance->GetCollision());
|
||||
|
||||
// Create preview volume node
|
||||
mHasValidPosition = pTemp->HasPosition();
|
||||
mHasVolumePreview = (pTemp->ScaleType() == CScriptTemplate::eScaleVolume);
|
||||
|
||||
// Create volume preview node
|
||||
if (mHasVolumePreview)
|
||||
{
|
||||
EVolumeShape shape = mpInstance->VolumeShape();
|
||||
|
@ -87,7 +95,13 @@ std::string CScriptNode::PrefixedName() const
|
|||
void CScriptNode::AddToRenderer(CRenderer *pRenderer)
|
||||
{
|
||||
if (!mpInstance) return;
|
||||
ERenderOptions options = pRenderer->RenderOptions();
|
||||
|
||||
if (options & eDrawObjectCollision)
|
||||
mpCollisionNode->AddToRenderer(pRenderer);
|
||||
|
||||
if (options & eDrawObjects)
|
||||
{
|
||||
if (!mpActiveModel)
|
||||
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
|
||||
|
||||
|
@ -112,8 +126,9 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSelected())
|
||||
if (IsSelected() && (options & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0)
|
||||
{
|
||||
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection);
|
||||
|
||||
|
@ -217,15 +232,18 @@ void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
|
|||
}
|
||||
}
|
||||
|
||||
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
||||
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
|
||||
{
|
||||
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
|
||||
|
||||
SRayIntersection out;
|
||||
out.pNode = this;
|
||||
out.AssetIndex = AssetID;
|
||||
|
||||
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
|
||||
if (options & eDrawObjects)
|
||||
{
|
||||
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
|
||||
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay);
|
||||
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
|
||||
|
||||
if (Result.first)
|
||||
{
|
||||
|
@ -238,6 +256,8 @@ SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
|||
|
||||
else
|
||||
out.Hit = false;
|
||||
}
|
||||
else out.Hit = false;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
#include "CSceneNode.h"
|
||||
#include "CModelNode.h"
|
||||
#include "CCollisionNode.h"
|
||||
#include <Resource/script/CScriptObject.h>
|
||||
|
||||
class CScriptNode : public CSceneNode
|
||||
{
|
||||
CScriptObject *mpInstance;
|
||||
CModel *mpActiveModel;
|
||||
CToken mModelToken;
|
||||
CCollisionNode *mpCollisionNode;
|
||||
|
||||
bool mHasValidPosition;
|
||||
bool mHasVolumePreview;
|
||||
|
@ -23,7 +26,7 @@ public:
|
|||
void DrawAsset(ERenderOptions Options, u32 Asset);
|
||||
void DrawSelection();
|
||||
void RayAABoxIntersectTest(CRayCollisionTester &Tester);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
|
||||
bool IsVisible() const;
|
||||
CScriptObject* Object();
|
||||
CModel* ActiveModel();
|
||||
|
|
|
@ -88,14 +88,14 @@ void CStaticNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
|
|||
}
|
||||
}
|
||||
|
||||
SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID)
|
||||
SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
|
||||
{
|
||||
SRayIntersection out;
|
||||
out.pNode = this;
|
||||
out.AssetIndex = AssetID;
|
||||
|
||||
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
|
||||
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay);
|
||||
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
|
||||
|
||||
if (Result.first)
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
void Draw(ERenderOptions Options);
|
||||
void DrawAsset(ERenderOptions Options, u32 asset);
|
||||
void RayAABoxIntersectTest(CRayCollisionTester &Tester);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
|
||||
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
|
||||
};
|
||||
|
||||
#endif // CSTATICNODE_H
|
||||
|
|
|
@ -77,7 +77,7 @@ void CSceneViewport::SceneRayCast(const CRay& ray)
|
|||
return;
|
||||
}
|
||||
|
||||
SRayIntersection result = mpScene->SceneRayCast(ray);
|
||||
SRayIntersection result = mpScene->SceneRayCast(ray, mpRenderer->RenderOptions());
|
||||
|
||||
if (result.Hit)
|
||||
{
|
||||
|
|
|
@ -329,22 +329,22 @@ void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
|
|||
// These functions are from "Go to slot" in the designer
|
||||
void CWorldEditor::on_ActionDrawWorld_triggered()
|
||||
{
|
||||
mScene.SetWorld(ui->ActionDrawWorld->isChecked());
|
||||
ui->MainViewport->Renderer()->ToggleWorld(ui->ActionDrawWorld->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionDrawCollision_triggered()
|
||||
{
|
||||
mScene.SetCollision(ui->ActionDrawCollision->isChecked());
|
||||
ui->MainViewport->Renderer()->ToggleWorldCollision(ui->ActionDrawCollision->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionDrawObjects_triggered()
|
||||
{
|
||||
mScene.SetObjects(ui->ActionDrawObjects->isChecked());
|
||||
ui->MainViewport->Renderer()->ToggleObjects(ui->ActionDrawObjects->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionDrawLights_triggered()
|
||||
{
|
||||
mScene.SetLights(ui->ActionDrawLights->isChecked());
|
||||
ui->MainViewport->Renderer()->ToggleLights(ui->ActionDrawLights->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionDrawSky_triggered()
|
||||
|
@ -470,3 +470,8 @@ void CWorldEditor::on_ActionDecrementGizmo_triggered()
|
|||
{
|
||||
mGizmo.DecrementSize();
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionDrawObjectCollision_triggered()
|
||||
{
|
||||
ui->MainViewport->Renderer()->ToggleObjectCollision(ui->ActionDrawObjectCollision->isChecked());
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ private slots:
|
|||
void on_ActionEditLayers_triggered();
|
||||
void on_ActionIncrementGizmo_triggered();
|
||||
void on_ActionDecrementGizmo_triggered();
|
||||
void on_ActionDrawObjectCollision_triggered();
|
||||
};
|
||||
|
||||
#endif // CWORLDEDITOR_H
|
||||
|
|
|
@ -270,8 +270,9 @@
|
|||
<addaction name="ActionZoomOnSelection"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="ActionDrawWorld"/>
|
||||
<addaction name="ActionDrawCollision"/>
|
||||
<addaction name="ActionDrawObjects"/>
|
||||
<addaction name="ActionDrawCollision"/>
|
||||
<addaction name="ActionDrawObjectCollision"/>
|
||||
<addaction name="ActionDrawLights"/>
|
||||
<addaction name="ActionDrawSky"/>
|
||||
<addaction name="separator"/>
|
||||
|
@ -535,7 +536,7 @@
|
|||
<string>Collision</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>2</string>
|
||||
<string>3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionDrawObjects">
|
||||
|
@ -549,7 +550,7 @@
|
|||
<string>Objects</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>3</string>
|
||||
<string>2</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionDrawLights">
|
||||
|
@ -563,7 +564,7 @@
|
|||
<string>Lights</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>4</string>
|
||||
<string>5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionDrawSky">
|
||||
|
@ -577,7 +578,7 @@
|
|||
<string>Sky</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>5</string>
|
||||
<string>6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionNoLighting">
|
||||
|
@ -705,6 +706,17 @@
|
|||
<enum>Qt::WindowShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionDrawObjectCollision">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Object Collision</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>4</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
|
@ -176,17 +176,17 @@ void CWorldEditorWindow::on_actionBackface_culling_triggered()
|
|||
|
||||
void CWorldEditorWindow::on_actionWorld_triggered()
|
||||
{
|
||||
mpSceneManager->SetWorld(ui->actionWorld->isChecked());
|
||||
mpRenderer->ToggleWorld(ui->actionWorld->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditorWindow::on_actionCollision_triggered()
|
||||
{
|
||||
mpSceneManager->SetCollision(ui->actionCollision->isChecked());
|
||||
mpRenderer->ToggleWorldCollision(ui->actionCollision->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditorWindow::on_actionObjects_triggered()
|
||||
{
|
||||
mpSceneManager->SetObjects(ui->actionObjects->isChecked());
|
||||
mpRenderer->ToggleObjects(ui->actionObjects->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditorWindow::setupInstanceViewLayers()
|
||||
|
@ -233,7 +233,7 @@ void CWorldEditorWindow::on_actionMaterial_Animations_triggered()
|
|||
|
||||
void CWorldEditorWindow::on_actionLights_triggered()
|
||||
{
|
||||
mpSceneManager->SetLights(ui->actionLights->isChecked());
|
||||
mpRenderer->ToggleLights(ui->actionLights->isChecked());
|
||||
}
|
||||
|
||||
void CWorldEditorWindow::on_actionLightingNone_triggered()
|
||||
|
|
|
@ -97,15 +97,6 @@ void WInstancesTab::OnTreeClick(QModelIndex Index)
|
|||
}
|
||||
}
|
||||
|
||||
// Show/Hide Node Type
|
||||
else if (mpTypesModel->IndexType(Index) == CTypesInstanceModel::eNodeTypeIndex)
|
||||
{
|
||||
CTypesInstanceModel::ENodeType type = mpTypesModel->IndexNodeType(Index);
|
||||
|
||||
if (type == CTypesInstanceModel::eScriptType)
|
||||
mpScene->SetObjects(!mpScene->AreScriptObjectsEnabled());
|
||||
}
|
||||
|
||||
if (sender() == ui->LayersTreeView)
|
||||
ui->LayersTreeView->update(Index);
|
||||
else if (sender() == ui->TypesTreeView)
|
||||
|
|
Loading…
Reference in New Issue