Moved selection handling code to CNodeSelection, implemented instance spawning, half-implemented instance deleting (this build is buggy/crash prone)
This commit is contained in:
parent
b2699eb96f
commit
f02f7ada0f
|
@ -58,6 +58,8 @@ void Write(const TString& rkMessage)
|
||||||
fprintf(gpLogFile, "[%08.3f] %s\n", Time, *rkMessage);
|
fprintf(gpLogFile, "[%08.3f] %s\n", Time, *rkMessage);
|
||||||
fflush(gpLogFile);
|
fflush(gpLogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << rkMessage << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Error(const TString& rkMessage)
|
void Error(const TString& rkMessage)
|
||||||
|
@ -65,7 +67,6 @@ void Error(const TString& rkMessage)
|
||||||
TString FullMessage = "ERROR: " + rkMessage;
|
TString FullMessage = "ERROR: " + rkMessage;
|
||||||
Write(FullMessage);
|
Write(FullMessage);
|
||||||
gErrorLog.push_back(FullMessage);
|
gErrorLog.push_back(FullMessage);
|
||||||
std::cout << FullMessage << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Warning(const TString& rkMessage)
|
void Warning(const TString& rkMessage)
|
||||||
|
@ -73,7 +74,6 @@ void Warning(const TString& rkMessage)
|
||||||
TString FullMessage = "Warning: " + rkMessage;
|
TString FullMessage = "Warning: " + rkMessage;
|
||||||
Write(FullMessage);
|
Write(FullMessage);
|
||||||
gErrorLog.push_back(FullMessage);
|
gErrorLog.push_back(FullMessage);
|
||||||
std::cout << FullMessage << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileWrite(const TString& rkFilename, const TString& rkMessage)
|
void FileWrite(const TString& rkFilename, const TString& rkMessage)
|
||||||
|
|
|
@ -15,6 +15,8 @@ public:
|
||||||
bool IsLayerEnabled() const;
|
bool IsLayerEnabled() const;
|
||||||
bool IsSkyEnabled() const;
|
bool IsSkyEnabled() const;
|
||||||
CModel* SkyModel() const;
|
CModel* SkyModel() const;
|
||||||
|
|
||||||
|
inline CScriptObject* Instance() const { return mpObj; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CAREAATTRIBUTES_H
|
#endif // CAREAATTRIBUTES_H
|
||||||
|
|
|
@ -2,23 +2,25 @@
|
||||||
#include "Core/Resource/Script/CScriptLayer.h"
|
#include "Core/Resource/Script/CScriptLayer.h"
|
||||||
#include "Core/Render/CRenderer.h"
|
#include "Core/Render/CRenderer.h"
|
||||||
|
|
||||||
CGameArea::CGameArea() : CResource()
|
CGameArea::CGameArea()
|
||||||
|
: CResource()
|
||||||
|
, mWorldIndex(-1)
|
||||||
|
, mVertexCount(0)
|
||||||
|
, mTriangleCount(0)
|
||||||
|
, mTerrainMerged(false)
|
||||||
|
, mOriginalWorldMeshCount(0)
|
||||||
|
, mUsesCompression(false)
|
||||||
|
, mMaterialSet(nullptr)
|
||||||
|
, mpGeneratorLayer(nullptr)
|
||||||
|
, mpCollision(nullptr)
|
||||||
{
|
{
|
||||||
mVertexCount = 0;
|
|
||||||
mTriangleCount = 0;
|
|
||||||
mTerrainMerged = false;
|
|
||||||
mOriginalWorldMeshCount = 0;
|
|
||||||
mUsesCompression = false;
|
|
||||||
mMaterialSet = nullptr;
|
|
||||||
mpGeneratorLayer = nullptr;
|
|
||||||
mCollision = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGameArea::~CGameArea()
|
CGameArea::~CGameArea()
|
||||||
{
|
{
|
||||||
ClearTerrain();
|
ClearTerrain();
|
||||||
|
|
||||||
delete mCollision;
|
delete mpCollision;
|
||||||
delete mpGeneratorLayer;
|
delete mpGeneratorLayer;
|
||||||
|
|
||||||
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||||
|
@ -108,85 +110,109 @@ void CGameArea::ClearScriptLayers()
|
||||||
mpGeneratorLayer = nullptr;
|
mpGeneratorLayer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGame CGameArea::Version()
|
u32 CGameArea::TotalInstanceCount() const
|
||||||
{
|
{
|
||||||
return mVersion;
|
u32 Num = 0;
|
||||||
|
|
||||||
|
for (u32 iLyr = 0; iLyr < mScriptLayers.size(); iLyr++)
|
||||||
|
Num += mScriptLayers[iLyr]->NumInstances();
|
||||||
|
|
||||||
|
return Num;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransform4f CGameArea::GetTransform()
|
CScriptObject* CGameArea::InstanceByID(u32 InstanceID)
|
||||||
{
|
|
||||||
return mTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CGameArea::GetTerrainModelCount()
|
|
||||||
{
|
|
||||||
return mTerrainModels.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CGameArea::GetStaticModelCount()
|
|
||||||
{
|
|
||||||
return mStaticTerrainModels.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
CModel* CGameArea::GetTerrainModel(u32 mdl)
|
|
||||||
{
|
|
||||||
return mTerrainModels[mdl];
|
|
||||||
}
|
|
||||||
|
|
||||||
CStaticModel* CGameArea::GetStaticModel(u32 mdl)
|
|
||||||
{
|
|
||||||
return mStaticTerrainModels[mdl];
|
|
||||||
}
|
|
||||||
|
|
||||||
CCollisionMeshGroup* CGameArea::GetCollision()
|
|
||||||
{
|
|
||||||
return mCollision;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CGameArea::GetScriptLayerCount()
|
|
||||||
{
|
|
||||||
return mScriptLayers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
CScriptLayer* CGameArea::GetScriptLayer(u32 index)
|
|
||||||
{
|
|
||||||
return mScriptLayers[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
CScriptLayer* CGameArea::GetGeneratorLayer()
|
|
||||||
{
|
|
||||||
return mpGeneratorLayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CScriptObject* CGameArea::GetInstanceByID(u32 InstanceID)
|
|
||||||
{
|
{
|
||||||
auto it = mObjectMap.find(InstanceID);
|
auto it = mObjectMap.find(InstanceID);
|
||||||
if (it != mObjectMap.end()) return it->second;
|
if (it != mObjectMap.end()) return it->second;
|
||||||
else return nullptr;
|
else return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CGameArea::GetLightLayerCount()
|
|
||||||
|
CScriptObject* CGameArea::SpawnInstance(CScriptTemplate *pTemplate,
|
||||||
|
CScriptLayer *pLayer,
|
||||||
|
const CVector3f& rkPosition /*= CVector3f::skZero*/,
|
||||||
|
const CQuaternion& rkRotation /*= CQuaternion::skIdentity*/,
|
||||||
|
const CVector3f& rkScale /*= CVector3f::skOne*/,
|
||||||
|
u32 SuggestedID /*= -1*/,
|
||||||
|
u32 SuggestedLayerIndex /*= -1*/ )
|
||||||
{
|
{
|
||||||
return mLightLayers.size();
|
// Verify we can fit another instance in this area.
|
||||||
|
u32 NumInstances = TotalInstanceCount();
|
||||||
|
|
||||||
|
if (NumInstances >= 0xFFFF)
|
||||||
|
{
|
||||||
|
Log::Error("Unable to spawn a new script instance; too many instances in area (" + TString::FromInt32(NumInstances, 0, 10) + ")");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the suggested instance ID is valid
|
||||||
|
u32 InstanceID = SuggestedID;
|
||||||
|
|
||||||
|
if (InstanceID != -1)
|
||||||
|
{
|
||||||
|
if (mObjectMap.find(InstanceID) == mObjectMap.end())
|
||||||
|
InstanceID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not valid (or if there's no suggested ID) then determine a new instance ID
|
||||||
|
if (InstanceID == -1)
|
||||||
|
{
|
||||||
|
// Determine layer index
|
||||||
|
u32 LayerIndex = -1;
|
||||||
|
|
||||||
|
for (u32 iLyr = 0; iLyr < mScriptLayers.size(); iLyr++)
|
||||||
|
{
|
||||||
|
if (mScriptLayers[iLyr] == pLayer)
|
||||||
|
{
|
||||||
|
LayerIndex = iLyr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LayerIndex == -1)
|
||||||
|
{
|
||||||
|
Log::Error("Unable to spawn a new script instance; invalid script layer passed in");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for a valid instance ID
|
||||||
|
InstanceID = (LayerIndex << 26) | (mWorldIndex << 16) | 1;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto it = mObjectMap.find(InstanceID);
|
||||||
|
|
||||||
|
if (it == mObjectMap.end())
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
InstanceID++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn instance
|
||||||
|
CScriptObject *pInstance = new CScriptObject(InstanceID, this, pLayer, pTemplate);
|
||||||
|
pInstance->EvaluateProperties();
|
||||||
|
pInstance->SetPosition(rkPosition);
|
||||||
|
pInstance->SetRotation(rkRotation.ToEuler());
|
||||||
|
pInstance->SetScale(rkScale);
|
||||||
|
pInstance->SetName(pTemplate->Name());
|
||||||
|
if (pTemplate->Game() < eEchoesDemo) pInstance->SetActive(true);
|
||||||
|
pLayer->AddInstance(pInstance, SuggestedLayerIndex);
|
||||||
|
mObjectMap[InstanceID] = pInstance;
|
||||||
|
return pInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CGameArea::GetLightCount(u32 layer)
|
void CGameArea::DeleteInstance(CScriptObject *pInstance)
|
||||||
{
|
{
|
||||||
if (mLightLayers.empty()) return 0;
|
pInstance->Layer()->RemoveInstance(pInstance);
|
||||||
return mLightLayers[layer].size();
|
pInstance->Template()->RemoveObject(pInstance);
|
||||||
}
|
|
||||||
|
|
||||||
CLight* CGameArea::GetLight(u32 layer, u32 light)
|
auto it = mObjectMap.find(pInstance->InstanceID());
|
||||||
{
|
if (it != mObjectMap.end()) mObjectMap.erase(it);
|
||||||
return mLightLayers[layer][light];
|
|
||||||
}
|
|
||||||
|
|
||||||
CPoiToWorld* CGameArea::GetPoiToWorldMap()
|
if (mpPoiToWorldMap && mpPoiToWorldMap->HasPoiMappings(pInstance->InstanceID()))
|
||||||
{
|
mpPoiToWorldMap->RemovePoi(pInstance->InstanceID());
|
||||||
return mpPoiToWorldMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAABox CGameArea::AABox()
|
pInstance->BreakAllLinks();
|
||||||
{
|
delete pInstance;
|
||||||
return mAABox;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,14 @@
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include "Core/Resource/Model/CStaticModel.h"
|
#include "Core/Resource/Model/CStaticModel.h"
|
||||||
#include <Common/types.h>
|
#include <Common/types.h>
|
||||||
|
#include <Math/CQuaternion.h>
|
||||||
#include <Math/CTransform4f.h>
|
#include <Math/CTransform4f.h>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class CScriptLayer;
|
class CScriptLayer;
|
||||||
class CScriptObject;
|
class CScriptObject;
|
||||||
|
class CScriptTemplate;
|
||||||
|
|
||||||
class CGameArea : public CResource
|
class CGameArea : public CResource
|
||||||
{
|
{
|
||||||
|
@ -23,6 +25,7 @@ class CGameArea : public CResource
|
||||||
friend class CAreaCooker;
|
friend class CAreaCooker;
|
||||||
|
|
||||||
EGame mVersion;
|
EGame mVersion;
|
||||||
|
u32 mWorldIndex;
|
||||||
u32 mVertexCount;
|
u32 mVertexCount;
|
||||||
u32 mTriangleCount;
|
u32 mTriangleCount;
|
||||||
bool mTerrainMerged;
|
bool mTerrainMerged;
|
||||||
|
@ -50,7 +53,7 @@ class CGameArea : public CResource
|
||||||
CScriptLayer *mpGeneratorLayer;
|
CScriptLayer *mpGeneratorLayer;
|
||||||
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
||||||
// Collision
|
// Collision
|
||||||
CCollisionMeshGroup *mCollision;
|
CCollisionMeshGroup *mpCollision;
|
||||||
// Lights
|
// Lights
|
||||||
std::vector<std::vector<CLight*>> mLightLayers;
|
std::vector<std::vector<CLight*>> mLightLayers;
|
||||||
// Object to Static Geometry Map
|
// Object to Static Geometry Map
|
||||||
|
@ -64,24 +67,34 @@ public:
|
||||||
void MergeTerrain();
|
void MergeTerrain();
|
||||||
void ClearTerrain();
|
void ClearTerrain();
|
||||||
void ClearScriptLayers();
|
void ClearScriptLayers();
|
||||||
|
u32 TotalInstanceCount() const;
|
||||||
|
CScriptObject* InstanceByID(u32 InstanceID);
|
||||||
|
CScriptObject* SpawnInstance(CScriptTemplate *pTemplate, CScriptLayer *pLayer,
|
||||||
|
const CVector3f& rkPosition = CVector3f::skZero,
|
||||||
|
const CQuaternion& rkRotation = CQuaternion::skIdentity,
|
||||||
|
const CVector3f& rkScale = CVector3f::skOne,
|
||||||
|
u32 SuggestedID = -1, u32 SuggestedLayerIndex = -1);
|
||||||
|
void DeleteInstance(CScriptObject *pInstance);
|
||||||
|
|
||||||
// Getters
|
// Inline Accessors
|
||||||
EGame Version();
|
inline EGame Version() const { return mVersion; }
|
||||||
CTransform4f GetTransform();
|
inline u32 WorldIndex() const { return mWorldIndex; }
|
||||||
u32 GetTerrainModelCount();
|
inline CTransform4f GetTransform() const { return mTransform; }
|
||||||
u32 GetStaticModelCount();
|
inline u32 GetTerrainModelCount() const { return mTerrainModels.size(); }
|
||||||
CModel* GetTerrainModel(u32 mdl);
|
inline u32 GetStaticModelCount() const { return mStaticTerrainModels.size(); }
|
||||||
CStaticModel* GetStaticModel(u32 mdl);
|
inline CModel* GetTerrainModel(u32 iMdl) const { return mTerrainModels[iMdl]; }
|
||||||
CCollisionMeshGroup* GetCollision();
|
inline CStaticModel* GetStaticModel(u32 iMdl) const { return mStaticTerrainModels[iMdl]; }
|
||||||
u32 GetScriptLayerCount();
|
inline CCollisionMeshGroup* GetCollision() const { return mpCollision; }
|
||||||
CScriptLayer* GetScriptLayer(u32 index);
|
inline u32 GetScriptLayerCount() const { return mScriptLayers.size(); }
|
||||||
CScriptLayer* GetGeneratorLayer();
|
inline CScriptLayer* GetScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
|
||||||
CScriptObject* GetInstanceByID(u32 InstanceID);
|
inline CScriptLayer* GetGeneratorLayer() const { return mpGeneratorLayer; }
|
||||||
u32 GetLightLayerCount();
|
inline u32 GetLightLayerCount() const { return mLightLayers.size(); }
|
||||||
u32 GetLightCount(u32 layer);
|
inline u32 GetLightCount(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
|
||||||
CLight* GetLight(u32 layer, u32 light);
|
inline CLight* GetLight(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
|
||||||
CPoiToWorld* GetPoiToWorldMap();
|
inline CPoiToWorld* GetPoiToWorldMap() const { return mpPoiToWorldMap; }
|
||||||
CAABox AABox();
|
inline CAABox AABox() const { return mAABox; }
|
||||||
|
|
||||||
|
inline void SetWorldIndex(u32 NewWorldIndex) { mWorldIndex = NewWorldIndex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CGAMEAREA_H
|
#endif // CGAMEAREA_H
|
||||||
|
|
|
@ -39,6 +39,22 @@ public:
|
||||||
{
|
{
|
||||||
return mMaps[Index];
|
return mMaps[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const SPoiMap* MapByID(u32 InstanceID) const
|
||||||
|
{
|
||||||
|
auto it = mPoiLookupMap.find(InstanceID);
|
||||||
|
|
||||||
|
if (it != mPoiLookupMap.end())
|
||||||
|
return it->second;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasPoiMappings(u32 InstanceID) const
|
||||||
|
{
|
||||||
|
auto it = mPoiLookupMap.find(InstanceID);
|
||||||
|
return (it != mPoiLookupMap.end());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPOITOWORLD_H
|
#endif // CPOITOWORLD_H
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
|
|
||||||
inline CUniqueID ID() const
|
inline CUniqueID ID() const
|
||||||
{
|
{
|
||||||
TString FileName = mPath.GetFileName();
|
TString FileName = mPath.GetFileName(false);
|
||||||
|
|
||||||
if (!mIsPath)
|
if (!mIsPath)
|
||||||
return CUniqueID::FromString(FileName);
|
return CUniqueID::FromString(FileName);
|
||||||
|
|
|
@ -16,12 +16,12 @@ CWorld::~CWorld()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorld::SetAreaLayerInfo(CGameArea *pArea, u32 AreaIndex)
|
void CWorld::SetAreaLayerInfo(CGameArea *pArea)
|
||||||
{
|
{
|
||||||
// The AreaIndex parameter is a placeholder until an improved world loader is implemented.
|
// The AreaIndex parameter is a placeholder until an improved world loader is implemented.
|
||||||
// For now it's the easiest/fastest way to do this because this function is called from
|
// For now it's the easiest/fastest way to do this because this function is called from
|
||||||
// the start window and the start window already knows the area index.
|
// the start window and the start window already knows the area index.
|
||||||
SArea& AreaInfo = mAreas[AreaIndex];
|
SArea& AreaInfo = mAreas[pArea->WorldIndex()];
|
||||||
|
|
||||||
for (u32 iLyr = 0; iLyr < pArea->GetScriptLayerCount(); iLyr++)
|
for (u32 iLyr = 0; iLyr < pArea->GetScriptLayerCount(); iLyr++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
CWorld();
|
CWorld();
|
||||||
~CWorld();
|
~CWorld();
|
||||||
|
|
||||||
void SetAreaLayerInfo(CGameArea *pArea, u32 AreaIndex);
|
void SetAreaLayerInfo(CGameArea *pArea);
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
EGame Version();
|
EGame Version();
|
||||||
|
|
|
@ -595,7 +595,7 @@ void CAreaLoader::ReadCollision()
|
||||||
{
|
{
|
||||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading collision (MP1/MP2/MP3)");
|
Log::FileWrite(mpMREA->GetSourceString(), "Reading collision (MP1/MP2/MP3)");
|
||||||
mpSectionMgr->ToSection(mCollisionBlockNum);
|
mpSectionMgr->ToSection(mCollisionBlockNum);
|
||||||
mpArea->mCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
mpArea->mpCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAreaLoader::ReadEGMC()
|
void CAreaLoader::ReadEGMC()
|
||||||
|
@ -643,7 +643,7 @@ void CAreaLoader::SetUpObjects()
|
||||||
|
|
||||||
if (iConMap != mConnectionMap.end())
|
if (iConMap != mConnectionMap.end())
|
||||||
{
|
{
|
||||||
CScriptObject *pObj = mpArea->GetInstanceByID(InstanceID);
|
CScriptObject *pObj = mpArea->InstanceByID(InstanceID);
|
||||||
pObj->mInLinks = iConMap->second;
|
pObj->mInLinks = iConMap->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,8 +214,8 @@ CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& SCLY)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpObj = new CScriptObject(mpArea, mpLayer, pTemp);
|
u32 InstanceID = SCLY.ReadLong();
|
||||||
mpObj->mInstanceID = SCLY.ReadLong();
|
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemp);
|
||||||
|
|
||||||
// Load connections
|
// Load connections
|
||||||
u32 NumLinks = SCLY.ReadLong();
|
u32 NumLinks = SCLY.ReadLong();
|
||||||
|
@ -249,7 +249,7 @@ CScriptLayer* CScriptLoader::LoadLayerMP1(IInputStream &SCLY)
|
||||||
SCLY.Seek(0x1, SEEK_CUR); // One unknown byte at the start of each layer
|
SCLY.Seek(0x1, SEEK_CUR); // One unknown byte at the start of each layer
|
||||||
u32 NumObjects = SCLY.ReadLong();
|
u32 NumObjects = SCLY.ReadLong();
|
||||||
|
|
||||||
mpLayer = new CScriptLayer();
|
mpLayer = new CScriptLayer(mpArea);
|
||||||
mpLayer->Reserve(NumObjects);
|
mpLayer->Reserve(NumObjects);
|
||||||
|
|
||||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||||
|
@ -327,8 +327,8 @@ CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& SCLY)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpObj = new CScriptObject(mpArea, mpLayer, pTemplate);
|
u32 InstanceID = SCLY.ReadLong();
|
||||||
mpObj->mInstanceID = SCLY.ReadLong();
|
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemplate);
|
||||||
|
|
||||||
// Load connections
|
// Load connections
|
||||||
u32 NumConnections = SCLY.ReadShort();
|
u32 NumConnections = SCLY.ReadShort();
|
||||||
|
@ -359,7 +359,7 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& SCLY)
|
||||||
SCLY.Seek(0x1, SEEK_CUR); // Skipping version. todo: verify this?
|
SCLY.Seek(0x1, SEEK_CUR); // Skipping version. todo: verify this?
|
||||||
u32 NumObjects = SCLY.ReadLong();
|
u32 NumObjects = SCLY.ReadLong();
|
||||||
|
|
||||||
mpLayer = new CScriptLayer();
|
mpLayer = new CScriptLayer(mpArea);
|
||||||
mpLayer->Reserve(NumObjects);
|
mpLayer->Reserve(NumObjects);
|
||||||
|
|
||||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||||
|
@ -372,9 +372,10 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& SCLY)
|
||||||
return mpLayer;
|
return mpLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
CScriptLayer* CScriptLoader::LoadLayer(IInputStream &SCLY, CGameArea *pArea, EGame Version)
|
// ************ STATIC ************
|
||||||
|
CScriptLayer* CScriptLoader::LoadLayer(IInputStream& rSCLY, CGameArea *pArea, EGame Version)
|
||||||
{
|
{
|
||||||
if (!SCLY.IsValid()) return nullptr;
|
if (!rSCLY.IsValid()) return nullptr;
|
||||||
|
|
||||||
CScriptLoader Loader;
|
CScriptLoader Loader;
|
||||||
Loader.mVersion = Version;
|
Loader.mVersion = Version;
|
||||||
|
@ -391,7 +392,7 @@ CScriptLayer* CScriptLoader::LoadLayer(IInputStream &SCLY, CGameArea *pArea, EGa
|
||||||
CTemplateLoader::LoadGameTemplates(Version);
|
CTemplateLoader::LoadGameTemplates(Version);
|
||||||
|
|
||||||
if (Version <= ePrime)
|
if (Version <= ePrime)
|
||||||
return Loader.LoadLayerMP1(SCLY);
|
return Loader.LoadLayerMP1(rSCLY);
|
||||||
else
|
else
|
||||||
return Loader.LoadLayerMP2(SCLY);
|
return Loader.LoadLayerMP2(rSCLY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ public:
|
||||||
void SetSender(u32 NewSenderID, u32 Index = -1)
|
void SetSender(u32 NewSenderID, u32 Index = -1)
|
||||||
{
|
{
|
||||||
u32 OldSenderID = mSenderID;
|
u32 OldSenderID = mSenderID;
|
||||||
CScriptObject *pOldSender = mpArea->GetInstanceByID(OldSenderID);
|
CScriptObject *pOldSender = mpArea->InstanceByID(OldSenderID);
|
||||||
CScriptObject *pNewSender = mpArea->GetInstanceByID(NewSenderID);
|
CScriptObject *pNewSender = mpArea->InstanceByID(NewSenderID);
|
||||||
|
|
||||||
mSenderID = NewSenderID;
|
mSenderID = NewSenderID;
|
||||||
pOldSender->RemoveLink(eOutgoing, this);
|
pOldSender->RemoveLink(eOutgoing, this);
|
||||||
|
@ -63,8 +63,8 @@ public:
|
||||||
void SetReceiver(u32 NewReceiverID, u32 Index = -1)
|
void SetReceiver(u32 NewReceiverID, u32 Index = -1)
|
||||||
{
|
{
|
||||||
u32 OldReceiverID = mSenderID;
|
u32 OldReceiverID = mSenderID;
|
||||||
CScriptObject *pOldReceiver = mpArea->GetInstanceByID(OldReceiverID);
|
CScriptObject *pOldReceiver = mpArea->InstanceByID(OldReceiverID);
|
||||||
CScriptObject *pNewReceiver = mpArea->GetInstanceByID(NewReceiverID);
|
CScriptObject *pNewReceiver = mpArea->InstanceByID(NewReceiverID);
|
||||||
|
|
||||||
mReceiverID = NewReceiverID;
|
mReceiverID = NewReceiverID;
|
||||||
pOldReceiver->RemoveLink(eIncoming, this);
|
pOldReceiver->RemoveLink(eIncoming, this);
|
||||||
|
@ -73,7 +73,7 @@ public:
|
||||||
|
|
||||||
u32 SenderIndex() const
|
u32 SenderIndex() const
|
||||||
{
|
{
|
||||||
CScriptObject *pSender = mpArea->GetInstanceByID(mSenderID);
|
CScriptObject *pSender = mpArea->InstanceByID(mSenderID);
|
||||||
|
|
||||||
for (u32 iLink = 0; iLink < pSender->NumLinks(eOutgoing); iLink++)
|
for (u32 iLink = 0; iLink < pSender->NumLinks(eOutgoing); iLink++)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ public:
|
||||||
|
|
||||||
u32 ReceiverIndex() const
|
u32 ReceiverIndex() const
|
||||||
{
|
{
|
||||||
CScriptObject *pReceiver = mpArea->GetInstanceByID(mReceiverID);
|
CScriptObject *pReceiver = mpArea->InstanceByID(mReceiverID);
|
||||||
|
|
||||||
for (u32 iLink = 0; iLink < pReceiver->NumLinks(eIncoming); iLink++)
|
for (u32 iLink = 0; iLink < pReceiver->NumLinks(eIncoming); iLink++)
|
||||||
{
|
{
|
||||||
|
@ -117,8 +117,8 @@ public:
|
||||||
u32 Message() const { return mMessageID; }
|
u32 Message() const { return mMessageID; }
|
||||||
u32 SenderID() const { return mSenderID; }
|
u32 SenderID() const { return mSenderID; }
|
||||||
u32 ReceiverID() const { return mReceiverID; }
|
u32 ReceiverID() const { return mReceiverID; }
|
||||||
CScriptObject* Sender() const { return mpArea->GetInstanceByID(mSenderID); }
|
CScriptObject* Sender() const { return mpArea->InstanceByID(mSenderID); }
|
||||||
CScriptObject* Receiver() const { return mpArea->GetInstanceByID(mReceiverID); }
|
CScriptObject* Receiver() const { return mpArea->InstanceByID(mReceiverID); }
|
||||||
|
|
||||||
void SetState(u32 StateID) { mStateID = StateID; }
|
void SetState(u32 StateID) { mStateID = StateID; }
|
||||||
void SetMessage(u32 MessageID) { mMessageID = MessageID; }
|
void SetMessage(u32 MessageID) { mMessageID = MessageID; }
|
||||||
|
|
|
@ -8,13 +8,15 @@
|
||||||
|
|
||||||
class CScriptLayer
|
class CScriptLayer
|
||||||
{
|
{
|
||||||
|
CGameArea *mpArea;
|
||||||
TString mLayerName;
|
TString mLayerName;
|
||||||
bool mActive;
|
bool mActive;
|
||||||
bool mVisible;
|
bool mVisible;
|
||||||
std::vector<CScriptObject*> mInstances;
|
std::vector<CScriptObject*> mInstances;
|
||||||
public:
|
public:
|
||||||
CScriptLayer()
|
CScriptLayer(CGameArea *pArea)
|
||||||
: mLayerName("New Layer")
|
: mpArea(pArea)
|
||||||
|
, mLayerName("New Layer")
|
||||||
, mActive(true)
|
, mActive(true)
|
||||||
, mVisible(true)
|
, mVisible(true)
|
||||||
{
|
{
|
||||||
|
@ -27,9 +29,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data Manipulation
|
// Data Manipulation
|
||||||
void AddInstance(CScriptObject *pObject)
|
void AddInstance(CScriptObject *pObject, u32 Index = -1)
|
||||||
{
|
{
|
||||||
mInstances.push_back(pObject);
|
if (Index != -1 && Index < mInstances.size())
|
||||||
|
{
|
||||||
|
auto it = mInstances.begin();
|
||||||
|
std::advance(it, Index);
|
||||||
|
mInstances.insert(it, pObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
mInstances.push_back(pObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveInstance(CScriptObject *pInstance)
|
void RemoveInstance(CScriptObject *pInstance)
|
||||||
|
@ -67,6 +77,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
|
inline CGameArea* Area() const { return mpArea; }
|
||||||
inline TString Name() const { return mLayerName; }
|
inline TString Name() const { return mLayerName; }
|
||||||
inline bool IsActive() const { return mActive; }
|
inline bool IsActive() const { return mActive; }
|
||||||
inline bool IsVisible() const { return mVisible; }
|
inline bool IsVisible() const { return mVisible; }
|
||||||
|
@ -88,6 +99,17 @@ public:
|
||||||
inline void SetActive(bool Active) { mActive = Active; }
|
inline void SetActive(bool Active) { mActive = Active; }
|
||||||
inline void SetVisible(bool Visible) { mVisible = Visible; }
|
inline void SetVisible(bool Visible) { mVisible = Visible; }
|
||||||
|
|
||||||
|
inline u32 AreaIndex() const
|
||||||
|
{
|
||||||
|
for (u32 iLyr = 0; iLyr < mpArea->GetScriptLayerCount(); iLyr++)
|
||||||
|
{
|
||||||
|
if (mpArea->GetScriptLayer(iLyr) == this)
|
||||||
|
return iLyr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
CScriptObject* operator[](u32 Index) { return InstanceByIndex(Index); }
|
CScriptObject* operator[](u32 Index) { return InstanceByIndex(Index); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
#include "CMasterTemplate.h"
|
#include "CMasterTemplate.h"
|
||||||
#include "Core/Resource/CAnimSet.h"
|
#include "Core/Resource/CAnimSet.h"
|
||||||
|
|
||||||
CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate)
|
CScriptObject::CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate)
|
||||||
: mpTemplate(pTemplate)
|
: mpTemplate(pTemplate)
|
||||||
, mpArea(pArea)
|
, mpArea(pArea)
|
||||||
, mpLayer(pLayer)
|
, mpLayer(pLayer)
|
||||||
, mVersion(0)
|
, mVersion(0)
|
||||||
|
, mInstanceID(InstanceID)
|
||||||
, mpDisplayModel(nullptr)
|
, mpDisplayModel(nullptr)
|
||||||
, mpCollision(nullptr)
|
, mpCollision(nullptr)
|
||||||
, mHasInGameModel(false)
|
, mHasInGameModel(false)
|
||||||
|
@ -75,16 +76,27 @@ bool CScriptObject::IsEditorProperty(IProperty *pProp)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptObject::SetLayer(CScriptLayer *pLayer)
|
void CScriptObject::SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex)
|
||||||
{
|
{
|
||||||
if (pLayer != mpLayer)
|
if (pLayer != mpLayer)
|
||||||
{
|
{
|
||||||
mpLayer->RemoveInstance(this);
|
mpLayer->RemoveInstance(this);
|
||||||
mpLayer = pLayer;
|
mpLayer = pLayer;
|
||||||
mpLayer->AddInstance(this);
|
mpLayer->AddInstance(this, NewLayerIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CScriptObject::LayerIndex() const
|
||||||
|
{
|
||||||
|
for (u32 iInst = 0; iInst < mpLayer->NumInstances(); iInst++)
|
||||||
|
{
|
||||||
|
if (mpLayer->InstanceByIndex(iInst) == this)
|
||||||
|
return iInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool CScriptObject::HasNearVisibleActivation() const
|
bool CScriptObject::HasNearVisibleActivation() const
|
||||||
{
|
{
|
||||||
/* This function is used to check whether an inactive DKCR object should render in game mode. DKCR deactivates a lot of
|
/* This function is used to check whether an inactive DKCR object should render in game mode. DKCR deactivates a lot of
|
||||||
|
@ -240,6 +252,26 @@ void CScriptObject::RemoveLink(ELinkType Type, CLink *pLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CScriptObject::BreakAllLinks()
|
||||||
|
{
|
||||||
|
for (auto it = mInLinks.begin(); it != mInLinks.end(); it++)
|
||||||
|
{
|
||||||
|
CLink *pLink = *it;
|
||||||
|
pLink->Sender()->RemoveLink(eOutgoing, pLink);
|
||||||
|
delete pLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = mOutLinks.begin(); it != mOutLinks.end(); it++)
|
||||||
|
{
|
||||||
|
CLink *pLink = *it;
|
||||||
|
pLink->Receiver()->RemoveLink(eIncoming, pLink);
|
||||||
|
delete pLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInLinks.clear();
|
||||||
|
mOutLinks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
TString CScriptObject::InstanceName() const
|
TString CScriptObject::InstanceName() const
|
||||||
{
|
{
|
||||||
if (mpInstanceName)
|
if (mpInstanceName)
|
||||||
|
|
|
@ -50,7 +50,7 @@ class CScriptObject
|
||||||
mutable bool mIsCheckingNearVisibleActivation;
|
mutable bool mIsCheckingNearVisibleActivation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
|
CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
|
||||||
~CScriptObject();
|
~CScriptObject();
|
||||||
|
|
||||||
void EvaluateProperties();
|
void EvaluateProperties();
|
||||||
|
@ -59,7 +59,8 @@ public:
|
||||||
void EvaluateCollisionModel();
|
void EvaluateCollisionModel();
|
||||||
void EvaluateVolume();
|
void EvaluateVolume();
|
||||||
bool IsEditorProperty(IProperty *pProp);
|
bool IsEditorProperty(IProperty *pProp);
|
||||||
void SetLayer(CScriptLayer *pLayer);
|
void SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex = -1);
|
||||||
|
u32 LayerIndex() const;
|
||||||
bool HasNearVisibleActivation() const;
|
bool HasNearVisibleActivation() const;
|
||||||
|
|
||||||
CScriptTemplate* Template() const;
|
CScriptTemplate* Template() const;
|
||||||
|
@ -78,6 +79,7 @@ public:
|
||||||
CLink* Link(ELinkType Type, u32 Index) const;
|
CLink* Link(ELinkType Type, u32 Index) const;
|
||||||
void AddLink(ELinkType Type, CLink *pLink, u32 Index = -1);
|
void AddLink(ELinkType Type, CLink *pLink, u32 Index = -1);
|
||||||
void RemoveLink(ELinkType Type, CLink *pLink);
|
void RemoveLink(ELinkType Type, CLink *pLink);
|
||||||
|
void BreakAllLinks();
|
||||||
|
|
||||||
CVector3f Position() const;
|
CVector3f Position() const;
|
||||||
CVector3f Rotation() const;
|
CVector3f Rotation() const;
|
||||||
|
|
|
@ -65,6 +65,18 @@ CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
|
||||||
|
|
||||||
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
|
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
|
||||||
mNodes[eScriptNode].push_back(pNode);
|
mNodes[eScriptNode].push_back(pNode);
|
||||||
|
mScriptNodeMap[pObj->InstanceID()] = pNode;
|
||||||
|
pNode->BuildLightList(mpArea);
|
||||||
|
|
||||||
|
// AreaAttributes check
|
||||||
|
switch (pObj->ObjectTypeID())
|
||||||
|
{
|
||||||
|
case 0x4E: // MP1 AreaAttributes ID
|
||||||
|
case 0x52454141: // MP2/MP3/DKCR AreaAttributes ID ("REAA")
|
||||||
|
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mNumNodes++;
|
mNumNodes++;
|
||||||
return pNode;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
@ -79,6 +91,48 @@ CLightNode* CScene::CreateLightNode(CLight *pLight)
|
||||||
return pNode;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CScene::DeleteNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
ENodeType Type = pNode->NodeType();
|
||||||
|
|
||||||
|
for (auto it = mNodes[Type].begin(); it != mNodes[Type].end(); it++)
|
||||||
|
{
|
||||||
|
if (*it == pNode)
|
||||||
|
{
|
||||||
|
mNodes[Type].erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type == eScriptNode)
|
||||||
|
{
|
||||||
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
||||||
|
|
||||||
|
auto ScriptMapIt = mScriptNodeMap.find(pScript->Object()->InstanceID());
|
||||||
|
if (ScriptMapIt != mScriptNodeMap.end())
|
||||||
|
mScriptNodeMap.erase(ScriptMapIt);
|
||||||
|
|
||||||
|
switch (pScript->Object()->ObjectTypeID())
|
||||||
|
{
|
||||||
|
case 0x4E:
|
||||||
|
case 0x52454141:
|
||||||
|
for (auto it = mAreaAttributesObjects.begin(); it != mAreaAttributesObjects.end(); it++)
|
||||||
|
{
|
||||||
|
if ((*it).Instance() == pScript->Object())
|
||||||
|
{
|
||||||
|
mAreaAttributesObjects.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pNode->Unparent();
|
||||||
|
delete pNode;
|
||||||
|
mNumNodes--;
|
||||||
|
}
|
||||||
|
|
||||||
void CScene::SetActiveArea(CGameArea *pArea)
|
void CScene::SetActiveArea(CGameArea *pArea)
|
||||||
{
|
{
|
||||||
// Clear existing area
|
// Clear existing area
|
||||||
|
@ -121,20 +175,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
||||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||||
{
|
{
|
||||||
CScriptObject *pObj = pLayer->InstanceByIndex(iObj);
|
CScriptObject *pObj = pLayer->InstanceByIndex(iObj);
|
||||||
CScriptNode *pNode = CreateScriptNode(pObj);
|
CreateScriptNode(pObj);
|
||||||
pNode->BuildLightList(mpArea);
|
|
||||||
|
|
||||||
// Add to map
|
|
||||||
mScriptNodeMap[pObj->InstanceID()] = pNode;
|
|
||||||
|
|
||||||
// AreaAttributes check
|
|
||||||
switch (pObj->ObjectTypeID())
|
|
||||||
{
|
|
||||||
case 0x4E: // MP1 AreaAttributes ID
|
|
||||||
case 0x52454141: // MP2/MP3/DKCR AreaAttributes ID ("REAA")
|
|
||||||
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,10 +185,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
||||||
for (u32 iObj = 0; iObj < pGenLayer->NumInstances(); iObj++)
|
for (u32 iObj = 0; iObj < pGenLayer->NumInstances(); iObj++)
|
||||||
{
|
{
|
||||||
CScriptObject *pObj = pGenLayer->InstanceByIndex(iObj);
|
CScriptObject *pObj = pGenLayer->InstanceByIndex(iObj);
|
||||||
CScriptNode *pNode = CreateScriptNode(pObj);
|
CreateScriptNode(pObj);
|
||||||
|
|
||||||
// Add to map
|
|
||||||
mScriptNodeMap[pObj->InstanceID()] = pNode;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,16 +255,10 @@ void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
|
||||||
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
|
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
|
||||||
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
|
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
|
||||||
|
|
||||||
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
|
for (CSceneIterator It(this, NodeFlags, false); It; ++It)
|
||||||
{
|
{
|
||||||
if (NodeFlags & it->first)
|
if (ViewInfo.GameMode || It->IsVisible())
|
||||||
{
|
It->AddToRenderer(pRenderer, ViewInfo);
|
||||||
std::vector<CSceneNode*>& rNodeVec = it->second;
|
|
||||||
|
|
||||||
for (u32 iNode = 0; iNode < rNodeVec.size(); iNode++)
|
|
||||||
if (ViewInfo.GameMode || rNodeVec[iNode]->IsVisible())
|
|
||||||
rNodeVec[iNode]->AddToRenderer(pRenderer, ViewInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,16 +268,10 @@ SRayIntersection CScene::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo
|
||||||
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
|
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
|
||||||
CRayCollisionTester Tester(Ray);
|
CRayCollisionTester Tester(Ray);
|
||||||
|
|
||||||
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
|
for (CSceneIterator It(this, NodeFlags, false); It; ++It)
|
||||||
{
|
{
|
||||||
if (NodeFlags & it->first)
|
if (It->IsVisible())
|
||||||
{
|
It->RayAABoxIntersectTest(Tester, ViewInfo);
|
||||||
std::vector<CSceneNode*>& rNodeVec = it->second;
|
|
||||||
|
|
||||||
for (u32 iNode = 0; iNode < rNodeVec.size(); iNode++)
|
|
||||||
if (rNodeVec[iNode]->IsVisible())
|
|
||||||
rNodeVec[iNode]->RayAABoxIntersectTest(Tester, ViewInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Tester.TestNodes(ViewInfo);
|
return Tester.TestNodes(ViewInfo);
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
|
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
|
||||||
CScriptNode* CreateScriptNode(CScriptObject *pObj);
|
CScriptNode* CreateScriptNode(CScriptObject *pObj);
|
||||||
CLightNode* CreateLightNode(CLight *pLight);
|
CLightNode* CreateLightNode(CLight *pLight);
|
||||||
|
void DeleteNode(CSceneNode *pNode);
|
||||||
void SetActiveArea(CGameArea *pArea);
|
void SetActiveArea(CGameArea *pArea);
|
||||||
void SetActiveWorld(CWorld *pWorld);
|
void SetActiveWorld(CWorld *pWorld);
|
||||||
void PostLoad();
|
void PostLoad();
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
|
|
||||||
inline operator bool() const
|
inline operator bool() const
|
||||||
{
|
{
|
||||||
return DoneIterating();
|
return !DoneIterating();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline CSceneNode* operator*() const
|
inline CSceneNode* operator*() const
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
#include "CNodeSelection.h"
|
|
||||||
|
|
||||||
CSceneSelection::CSceneSelection(CScene *pScene)
|
|
||||||
{
|
|
||||||
mpScene = pScene;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSceneSelection::SelectNode(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
// There shouldn't be more than one selection per scene, so this should be safe.
|
|
||||||
if (!pNode->IsSelected())
|
|
||||||
{
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
mSelectedNodes.push_back(pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSceneSelection::DeselectNode(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
if (pNode->IsSelected())
|
|
||||||
{
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
{
|
|
||||||
if (*it == pNode)
|
|
||||||
{
|
|
||||||
mSelectedNodes.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CSceneSelection::SelectionSize()
|
|
||||||
{
|
|
||||||
return mSelectedNodes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSceneNode* CSceneSelection::NodeByIndex(u32 Index)
|
|
||||||
{
|
|
||||||
if (Index >= SelectionSize()) return nullptr;
|
|
||||||
return mSelectedNodes[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSceneSelection::ClearSelection()
|
|
||||||
{
|
|
||||||
for (auto it = mSelectedNodes.begin(); it != mSelectedNodes.end(); it++)
|
|
||||||
(*it)->SetSelected(false);
|
|
||||||
|
|
||||||
mSelectedNodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ OPERATORS ************
|
|
||||||
CSceneNode* CSceneSelection::operator[](u32 Index)
|
|
||||||
{
|
|
||||||
return NodeByIndex(Index);
|
|
||||||
}
|
|
|
@ -1,24 +1,126 @@
|
||||||
#ifndef CNODESELECTION_H
|
#ifndef CNODESELECTION_H
|
||||||
#define CNODESELECTION_H
|
#define CNODESELECTION_H
|
||||||
|
|
||||||
|
#include <Core/Scene/CSceneIterator.h>
|
||||||
#include <Core/Scene/CSceneNode.h>
|
#include <Core/Scene/CSceneNode.h>
|
||||||
#include <list>
|
#include <Core/Scene/CScriptNode.h>
|
||||||
|
#include <QList>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
class CSceneSelection
|
class CNodeSelection : public QObject
|
||||||
{
|
{
|
||||||
CScene *mpScene;
|
Q_OBJECT
|
||||||
std::vector<CSceneNode*> mSelectedNodes;
|
|
||||||
|
FNodeFlags mAllowedNodes;
|
||||||
|
QList<CSceneNode*> mSelectedNodes;
|
||||||
|
|
||||||
|
mutable CAABox mCachedBounds;
|
||||||
|
mutable bool mBoundsDirty;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSceneSelection(CScene *pScene);
|
CNodeSelection()
|
||||||
void SelectNode(CSceneNode *pNode);
|
: mAllowedNodes(eAllNodeTypes)
|
||||||
void DeselectNode(CSceneNode *pNode);
|
, mBoundsDirty(true) {}
|
||||||
u32 SelectionSize();
|
|
||||||
CSceneNode* NodeByIndex(u32 Index);
|
|
||||||
void ClearSelection();
|
|
||||||
|
|
||||||
// Operators
|
~CNodeSelection()
|
||||||
CSceneNode* operator[](u32 Index);
|
{
|
||||||
|
foreach (CSceneNode *pNode, mSelectedNodes)
|
||||||
|
pNode->SetSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (IsAllowedType(pNode->NodeType()) && !pNode->IsSelected())
|
||||||
|
{
|
||||||
|
pNode->SetSelected(true);
|
||||||
|
mSelectedNodes << pNode;
|
||||||
|
mCachedBounds.ExpandBounds(pNode->AABox());
|
||||||
|
emit Modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeselectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (pNode->IsSelected())
|
||||||
|
{
|
||||||
|
pNode->SetSelected(false);
|
||||||
|
mSelectedNodes.removeOne(pNode);
|
||||||
|
mBoundsDirty = true;
|
||||||
|
emit Modified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
foreach (CSceneNode *pNode, mSelectedNodes)
|
||||||
|
pNode->SetSelected(false);
|
||||||
|
|
||||||
|
mSelectedNodes.clear();
|
||||||
|
mBoundsDirty = true;
|
||||||
|
emit Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearAndSelectNode(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
// Block signals for Clear so that Modified only emits once.
|
||||||
|
blockSignals(true);
|
||||||
|
Clear();
|
||||||
|
blockSignals(false);
|
||||||
|
SelectNode(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSelectedNodes(const QList<CSceneNode*>& rkList)
|
||||||
|
{
|
||||||
|
blockSignals(true);
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, rkList)
|
||||||
|
SelectNode(pNode);
|
||||||
|
blockSignals(false);
|
||||||
|
|
||||||
|
mBoundsDirty = true;
|
||||||
|
emit Modified();
|
||||||
|
}
|
||||||
|
|
||||||
|
CAABox Bounds() const
|
||||||
|
{
|
||||||
|
if (mBoundsDirty)
|
||||||
|
{
|
||||||
|
mCachedBounds = CAABox::skInfinite;
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, mSelectedNodes)
|
||||||
|
{
|
||||||
|
mCachedBounds.ExpandBounds(pNode->AABox());
|
||||||
|
|
||||||
|
if (pNode->NodeType() == eScriptNode)
|
||||||
|
{
|
||||||
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
||||||
|
|
||||||
|
if (pScript->HasPreviewVolume())
|
||||||
|
mCachedBounds.ExpandBounds(pScript->PreviewVolumeAABox());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mBoundsDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mCachedBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32 Size() const { return mSelectedNodes.size(); }
|
||||||
|
inline bool IsEmpty() const { return Size() == 0; }
|
||||||
|
inline CSceneNode* At(u32 Index) const { return mSelectedNodes[Index]; }
|
||||||
|
inline CSceneNode* Front() const { return mSelectedNodes.front(); }
|
||||||
|
inline CSceneNode* Back() const { return mSelectedNodes.back(); }
|
||||||
|
inline CSceneNode* operator[](u32 Index) const { return mSelectedNodes[Index]; }
|
||||||
|
inline void UpdateBounds() { mBoundsDirty = true; }
|
||||||
|
inline void SetAllowedNodeTypes(FNodeFlags Types) { mAllowedNodes = Types; }
|
||||||
|
inline bool IsAllowedType(ENodeType Type) const { return (mAllowedNodes & Type) != 0; }
|
||||||
|
inline bool IsAllowedType(CSceneNode *pNode) const { return (mAllowedNodes & pNode->NodeType()) != 0; }
|
||||||
|
inline QList<CSceneNode*> SelectedNodeList() const { return mSelectedNodes; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void Modified();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CNODESELECTION_H
|
#endif // CNODESELECTION_H
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "CSceneViewport.h"
|
#include "CSceneViewport.h"
|
||||||
|
#include "CSelectionIterator.h"
|
||||||
#include "UICommon.h"
|
#include "UICommon.h"
|
||||||
#include "Editor/Undo/UndoCommands.h"
|
#include "Editor/Undo/UndoCommands.h"
|
||||||
#include <Core/Render/CDrawUtil.h>
|
#include <Core/Render/CDrawUtil.h>
|
||||||
|
@ -386,10 +387,8 @@ void CSceneViewport::OnToggleSelect()
|
||||||
|
|
||||||
void CSceneViewport::OnHideSelection()
|
void CSceneViewport::OnHideSelection()
|
||||||
{
|
{
|
||||||
const QList<CSceneNode*>& rkSelection = mpEditor->GetSelection();
|
for (CSelectionIterator It(mpEditor->Selection()); It; ++It)
|
||||||
|
It->SetVisible(false);
|
||||||
foreach (CSceneNode *pNode, rkSelection)
|
|
||||||
pNode->SetVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneViewport::OnHideUnselected()
|
void CSceneViewport::OnHideUnselected()
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef CSELECTIONITERATOR
|
||||||
|
#define CSELECTIONITERATOR
|
||||||
|
|
||||||
|
#include "CNodeSelection.h"
|
||||||
|
|
||||||
|
class CSelectionIterator
|
||||||
|
{
|
||||||
|
CNodeSelection *mpSelection;
|
||||||
|
u32 mCurrentIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSelectionIterator(CNodeSelection *pSelection)
|
||||||
|
: mpSelection(pSelection), mCurrentIndex(0) {}
|
||||||
|
|
||||||
|
inline void Next() { mCurrentIndex++; }
|
||||||
|
inline bool DoneIterating() const { return (mCurrentIndex == mpSelection->Size()); }
|
||||||
|
inline operator bool() const { return !DoneIterating(); }
|
||||||
|
inline CSceneNode* operator*() const { return mpSelection->At(mCurrentIndex); }
|
||||||
|
inline CSceneNode* operator->() const { return mpSelection->At(mCurrentIndex); }
|
||||||
|
inline CSelectionIterator& operator++() { Next(); return *this; }
|
||||||
|
inline CSelectionIterator operator++(int) { CSelectionIterator Copy = *this; Next(); return Copy; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CSELECTIONITERATOR
|
||||||
|
|
|
@ -183,8 +183,9 @@ void CStartWindow::on_LaunchWorldEditorButton_clicked()
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mpWorld->SetAreaLayerInfo(pArea, mSelectedAreaIndex);
|
pArea->SetWorldIndex(mSelectedAreaIndex);
|
||||||
mpWorldEditor->SetArea(mpWorld, pArea, mSelectedAreaIndex);
|
mpWorld->SetAreaLayerInfo(pArea);
|
||||||
|
mpWorldEditor->SetArea(mpWorld, pArea);
|
||||||
gResCache.Clean();
|
gResCache.Clean();
|
||||||
|
|
||||||
mpWorldEditor->setWindowModality(Qt::WindowModal);
|
mpWorldEditor->setWindowModality(Qt::WindowModal);
|
||||||
|
|
|
@ -149,17 +149,19 @@ HEADERS += \
|
||||||
Undo/CAddLinkCommand.h \
|
Undo/CAddLinkCommand.h \
|
||||||
Undo/CDeleteLinksCommand.h \
|
Undo/CDeleteLinksCommand.h \
|
||||||
Undo/CEditLinkCommand.h \
|
Undo/CEditLinkCommand.h \
|
||||||
WorldEditor/CConfirmUnlinkDialog.h
|
WorldEditor/CConfirmUnlinkDialog.h \
|
||||||
|
Undo/CDeleteSelectionCommand.h \
|
||||||
|
Undo/CCreateInstanceCommand.h \
|
||||||
|
WorldEditor/CTemplateMimeData.h \
|
||||||
|
WorldEditor/CTemplateListView.h \
|
||||||
|
CSelectionIterator.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
ModelEditor/CModelEditorViewport.cpp \
|
ModelEditor/CModelEditorViewport.cpp \
|
||||||
ModelEditor/CModelEditorWindow.cpp \
|
ModelEditor/CModelEditorWindow.cpp \
|
||||||
Undo/CClearSelectionCommand.cpp \
|
|
||||||
Undo/CDeselectNodeCommand.cpp \
|
|
||||||
Undo/CRotateNodeCommand.cpp \
|
Undo/CRotateNodeCommand.cpp \
|
||||||
Undo/CScaleNodeCommand.cpp \
|
Undo/CScaleNodeCommand.cpp \
|
||||||
Undo/CSelectNodeCommand.cpp \
|
|
||||||
Undo/CTranslateNodeCommand.cpp \
|
Undo/CTranslateNodeCommand.cpp \
|
||||||
Widgets/IPreviewPanel.cpp \
|
Widgets/IPreviewPanel.cpp \
|
||||||
Widgets/WAnimParamsEditor.cpp \
|
Widgets/WAnimParamsEditor.cpp \
|
||||||
|
@ -185,7 +187,6 @@ SOURCES += \
|
||||||
CBasicViewport.cpp \
|
CBasicViewport.cpp \
|
||||||
CDarkStyle.cpp \
|
CDarkStyle.cpp \
|
||||||
CGizmo.cpp \
|
CGizmo.cpp \
|
||||||
CNodeSelection.cpp \
|
|
||||||
CSceneViewport.cpp \
|
CSceneViewport.cpp \
|
||||||
CStartWindow.cpp \
|
CStartWindow.cpp \
|
||||||
INodeEditor.cpp \
|
INodeEditor.cpp \
|
||||||
|
@ -193,8 +194,6 @@ SOURCES += \
|
||||||
TestDialog.cpp \
|
TestDialog.cpp \
|
||||||
UICommon.cpp \
|
UICommon.cpp \
|
||||||
CErrorLogDialog.cpp \
|
CErrorLogDialog.cpp \
|
||||||
Undo/CSelectAllCommand.cpp \
|
|
||||||
Undo/CInvertSelectionCommand.cpp \
|
|
||||||
WorldEditor/CPoiMapEditDialog.cpp \
|
WorldEditor/CPoiMapEditDialog.cpp \
|
||||||
WorldEditor/CPoiMapModel.cpp \
|
WorldEditor/CPoiMapModel.cpp \
|
||||||
PropertyEdit/CPropertyModel.cpp \
|
PropertyEdit/CPropertyModel.cpp \
|
||||||
|
@ -211,7 +210,9 @@ SOURCES += \
|
||||||
WorldEditor/CSelectInstanceDialog.cpp \
|
WorldEditor/CSelectInstanceDialog.cpp \
|
||||||
Undo/CAddLinkCommand.cpp \
|
Undo/CAddLinkCommand.cpp \
|
||||||
Undo/CDeleteLinksCommand.cpp \
|
Undo/CDeleteLinksCommand.cpp \
|
||||||
Undo/CEditLinkCommand.cpp
|
Undo/CEditLinkCommand.cpp \
|
||||||
|
Undo/CDeleteSelectionCommand.cpp \
|
||||||
|
Undo/CCreateInstanceCommand.cpp
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "INodeEditor.h"
|
#include "INodeEditor.h"
|
||||||
|
#include "CSelectionIterator.h"
|
||||||
#include "Editor/Undo/UndoCommands.h"
|
#include "Editor/Undo/UndoCommands.h"
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
|
||||||
INodeEditor::INodeEditor(QWidget *pParent)
|
INodeEditor::INodeEditor(QWidget *pParent)
|
||||||
: QMainWindow(pParent)
|
: QMainWindow(pParent)
|
||||||
, mPickMode(false)
|
, mPickMode(false)
|
||||||
, mSelectionNodeFlags(eAllNodeTypes)
|
, mpSelection(new CNodeSelection)
|
||||||
, mSelectionLocked(false)
|
, mSelectionLocked(false)
|
||||||
, mShowGizmo(false)
|
, mShowGizmo(false)
|
||||||
, mGizmoHovering(false)
|
, mGizmoHovering(false)
|
||||||
|
@ -53,10 +54,12 @@ INodeEditor::INodeEditor(QWidget *pParent)
|
||||||
connect(mGizmoActions[2], SIGNAL(triggered()), this, SLOT(OnRotateTriggered()));
|
connect(mGizmoActions[2], SIGNAL(triggered()), this, SLOT(OnRotateTriggered()));
|
||||||
connect(mGizmoActions[3], SIGNAL(triggered()), this, SLOT(OnScaleTriggered()));
|
connect(mGizmoActions[3], SIGNAL(triggered()), this, SLOT(OnScaleTriggered()));
|
||||||
connect(mpTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTransformSpaceChanged(int)));
|
connect(mpTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTransformSpaceChanged(int)));
|
||||||
|
connect(mpSelection, SIGNAL(Modified()), this, SLOT(OnSelectionModified()));
|
||||||
}
|
}
|
||||||
|
|
||||||
INodeEditor::~INodeEditor()
|
INodeEditor::~INodeEditor()
|
||||||
{
|
{
|
||||||
|
delete mpSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUndoStack* INodeEditor::UndoStack()
|
QUndoStack* INodeEditor::UndoStack()
|
||||||
|
@ -76,7 +79,7 @@ CGizmo* INodeEditor::Gizmo()
|
||||||
|
|
||||||
bool INodeEditor::IsGizmoVisible()
|
bool INodeEditor::IsGizmoVisible()
|
||||||
{
|
{
|
||||||
return (mShowGizmo && !mSelection.empty());
|
return (mShowGizmo && !mpSelection->IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::BeginGizmoTransform()
|
void INodeEditor::BeginGizmoTransform()
|
||||||
|
@ -113,33 +116,12 @@ ETransformSpace INodeEditor::CurrentTransformSpace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::RecalculateSelectionBounds()
|
|
||||||
{
|
|
||||||
mSelectionBounds = CAABox::skInfinite;
|
|
||||||
|
|
||||||
foreach (CSceneNode *pNode, mSelection)
|
|
||||||
ExpandSelectionBounds(pNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void INodeEditor::ExpandSelectionBounds(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
mSelectionBounds.ExpandBounds(pNode->AABox());
|
|
||||||
|
|
||||||
if (pNode->NodeType() == eScriptNode)
|
|
||||||
{
|
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
|
||||||
|
|
||||||
if (pScript->HasPreviewVolume())
|
|
||||||
mSelectionBounds.ExpandBounds(pScript->PreviewVolumeAABox());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void INodeEditor::SelectNode(CSceneNode *pNode)
|
void INodeEditor::SelectNode(CSceneNode *pNode)
|
||||||
{
|
{
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
{
|
{
|
||||||
if (!pNode->IsSelected())
|
if (!pNode->IsSelected())
|
||||||
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
mUndoStack.push(new CSelectNodeCommand(mpSelection, pNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +130,7 @@ void INodeEditor::DeselectNode(CSceneNode *pNode)
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
{
|
{
|
||||||
if (pNode->IsSelected())
|
if (pNode->IsSelected())
|
||||||
mUndoStack.push(new CDeselectNodeCommand(this, pNode, mSelection));
|
mUndoStack.push(new CDeselectNodeCommand(mpSelection, pNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +138,8 @@ void INodeEditor::ClearSelection()
|
||||||
{
|
{
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
{
|
{
|
||||||
if (!mSelection.empty())
|
if (!mpSelection->IsEmpty())
|
||||||
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
mUndoStack.push(new CClearSelectionCommand(mpSelection));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,17 +147,17 @@ void INodeEditor::ClearAndSelectNode(CSceneNode *pNode)
|
||||||
{
|
{
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
{
|
{
|
||||||
if (mSelection.empty())
|
if (mpSelection->IsEmpty())
|
||||||
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
mUndoStack.push(new CSelectNodeCommand(mpSelection, pNode));
|
||||||
|
|
||||||
else if ((mSelection.size() == 1) && (mSelection.front() == pNode))
|
else if ((mpSelection->Size() == 1) && (mpSelection->Front() == pNode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mUndoStack.beginMacro("Select");
|
mUndoStack.beginMacro("Select");
|
||||||
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
mUndoStack.push(new CClearSelectionCommand(mpSelection));
|
||||||
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
mUndoStack.push(new CSelectNodeCommand(mpSelection, pNode));
|
||||||
mUndoStack.endMacro();
|
mUndoStack.endMacro();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,13 +166,13 @@ void INodeEditor::ClearAndSelectNode(CSceneNode *pNode)
|
||||||
void INodeEditor::SelectAll(FNodeFlags NodeFlags)
|
void INodeEditor::SelectAll(FNodeFlags NodeFlags)
|
||||||
{
|
{
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
mUndoStack.push(new CSelectAllCommand(this, mSelection, &mScene, NodeFlags));
|
mUndoStack.push(new CSelectAllCommand(mpSelection, &mScene, NodeFlags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::InvertSelection(FNodeFlags NodeFlags)
|
void INodeEditor::InvertSelection(FNodeFlags NodeFlags)
|
||||||
{
|
{
|
||||||
if (!mSelectionLocked)
|
if (!mSelectionLocked)
|
||||||
mUndoStack.push(new CInvertSelectionCommand(this, mSelection, &mScene, NodeFlags));
|
mUndoStack.push(new CInvertSelectionCommand(mpSelection, &mScene, NodeFlags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::SetSelectionLocked(bool Locked)
|
void INodeEditor::SetSelectionLocked(bool Locked)
|
||||||
|
@ -200,12 +182,12 @@ void INodeEditor::SetSelectionLocked(bool Locked)
|
||||||
|
|
||||||
bool INodeEditor::HasSelection() const
|
bool INodeEditor::HasSelection() const
|
||||||
{
|
{
|
||||||
return (!mSelection.isEmpty());
|
return (!mpSelection->IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<CSceneNode*>& INodeEditor::GetSelection() const
|
CNodeSelection* INodeEditor::Selection() const
|
||||||
{
|
{
|
||||||
return mSelection;
|
return mpSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor /*= Qt::CrossCursor*/)
|
void INodeEditor::EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor /*= Qt::CrossCursor*/)
|
||||||
|
@ -231,22 +213,42 @@ void INodeEditor::ExitPickMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::NotifySelectionModified()
|
void INodeEditor::NotifySelectionTransformed()
|
||||||
|
{
|
||||||
|
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||||
|
It->OnTransformed();
|
||||||
|
|
||||||
|
mpSelection->UpdateBounds();
|
||||||
|
emit SelectionTransformed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::NotifyNodeAboutToBeSpawned()
|
||||||
|
{
|
||||||
|
emit NodeAboutToBeSpawned();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::NotifyNodeSpawned(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
emit NodeSpawned(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::NotifyNodeAboutToBeDeleted(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
emit NodeAboutToBeDeleted(pNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void INodeEditor::NotifyNodeDeleted()
|
||||||
|
{
|
||||||
|
emit NodeDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void INodeEditor::OnSelectionModified()
|
||||||
{
|
{
|
||||||
RecalculateSelectionBounds();
|
|
||||||
UpdateSelectionUI();
|
UpdateSelectionUI();
|
||||||
emit SelectionModified();
|
emit SelectionModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
void INodeEditor::NotifySelectionTransformed()
|
|
||||||
{
|
|
||||||
foreach (CSceneNode *pNode, mSelection)
|
|
||||||
pNode->OnTransformed();
|
|
||||||
|
|
||||||
emit SelectionTransformed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ PUBLIC SLOTS ************
|
|
||||||
void INodeEditor::OnGizmoMoved()
|
void INodeEditor::OnGizmoMoved()
|
||||||
{
|
{
|
||||||
switch (mGizmo.Mode())
|
switch (mGizmo.Mode())
|
||||||
|
@ -254,26 +256,25 @@ void INodeEditor::OnGizmoMoved()
|
||||||
case CGizmo::eTranslate:
|
case CGizmo::eTranslate:
|
||||||
{
|
{
|
||||||
CVector3f delta = mGizmo.DeltaTranslation();
|
CVector3f delta = mGizmo.DeltaTranslation();
|
||||||
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
mUndoStack.push(new CTranslateNodeCommand(this, mpSelection->SelectedNodeList(), delta, mTranslateSpace));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
{
|
{
|
||||||
CQuaternion delta = mGizmo.DeltaRotation();
|
CQuaternion delta = mGizmo.DeltaRotation();
|
||||||
mUndoStack.push(new CRotateNodeCommand(this, mSelection, CVector3f::skZero, delta, mRotateSpace));
|
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta, mRotateSpace));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
{
|
{
|
||||||
CVector3f delta = mGizmo.DeltaScale();
|
CVector3f delta = mGizmo.DeltaScale();
|
||||||
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecalculateSelectionBounds();
|
|
||||||
UpdateGizmoUI();
|
UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +286,7 @@ void INodeEditor::OnViewportClick(const SRayIntersection& rkRayIntersect, QMouse
|
||||||
// Not in pick mode: process node selection/deselection
|
// Not in pick mode: process node selection/deselection
|
||||||
if (!mPickMode)
|
if (!mPickMode)
|
||||||
{
|
{
|
||||||
bool ValidNode = (pNode && (pNode->NodeType() & mSelectionNodeFlags));
|
bool ValidNode = (pNode && mpSelection->IsAllowedType(pNode));
|
||||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||||
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||||
|
|
||||||
|
@ -364,11 +365,11 @@ void INodeEditor::UpdateTransformActionsEnabled()
|
||||||
bool AllowTranslate = true, AllowRotate = true, AllowScale = true;
|
bool AllowTranslate = true, AllowRotate = true, AllowScale = true;
|
||||||
bool SelectedModeWasEnabled = mpGizmoGroup->checkedAction()->isEnabled();
|
bool SelectedModeWasEnabled = mpGizmoGroup->checkedAction()->isEnabled();
|
||||||
|
|
||||||
for (auto it = mSelection.begin(); it != mSelection.end(); it++)
|
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||||
{
|
{
|
||||||
if (!(*it)->AllowsTranslate()) AllowTranslate = false;
|
if (!It->AllowsTranslate()) AllowTranslate = false;
|
||||||
if (!(*it)->AllowsRotate()) AllowRotate = false;
|
if (!It->AllowsRotate()) AllowRotate = false;
|
||||||
if (!(*it)->AllowsScale()) AllowScale = false;
|
if (!It->AllowsScale()) AllowScale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mGizmoActions[1]->setEnabled(AllowTranslate);
|
mGizmoActions[1]->setEnabled(AllowTranslate);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define INODEEDITOR_H
|
#define INODEEDITOR_H
|
||||||
|
|
||||||
#include "CGizmo.h"
|
#include "CGizmo.h"
|
||||||
|
#include "CNodeSelection.h"
|
||||||
#include <Math/ETransformSpace.h>
|
#include <Math/ETransformSpace.h>
|
||||||
#include <Core/Scene/CScene.h>
|
#include <Core/Scene/CScene.h>
|
||||||
|
|
||||||
|
@ -23,9 +24,7 @@ protected:
|
||||||
|
|
||||||
// Node management
|
// Node management
|
||||||
CScene mScene;
|
CScene mScene;
|
||||||
QList<CSceneNode*> mSelection;
|
CNodeSelection *mpSelection;
|
||||||
FNodeFlags mSelectionNodeFlags;
|
|
||||||
CAABox mSelectionBounds;
|
|
||||||
bool mSelectionLocked;
|
bool mSelectionLocked;
|
||||||
|
|
||||||
// Gizmo
|
// Gizmo
|
||||||
|
@ -62,8 +61,6 @@ public:
|
||||||
void EndGizmoTransform();
|
void EndGizmoTransform();
|
||||||
ETransformSpace CurrentTransformSpace();
|
ETransformSpace CurrentTransformSpace();
|
||||||
|
|
||||||
void RecalculateSelectionBounds();
|
|
||||||
void ExpandSelectionBounds(CSceneNode *pNode);
|
|
||||||
void SelectNode(CSceneNode *pNode);
|
void SelectNode(CSceneNode *pNode);
|
||||||
void DeselectNode(CSceneNode *pNode);
|
void DeselectNode(CSceneNode *pNode);
|
||||||
void ClearSelection();
|
void ClearSelection();
|
||||||
|
@ -72,15 +69,22 @@ public:
|
||||||
void InvertSelection(FNodeFlags NodeFlags);
|
void InvertSelection(FNodeFlags NodeFlags);
|
||||||
void SetSelectionLocked(bool Locked);
|
void SetSelectionLocked(bool Locked);
|
||||||
bool HasSelection() const;
|
bool HasSelection() const;
|
||||||
const QList<CSceneNode*>& GetSelection() const;
|
CNodeSelection* Selection() const;
|
||||||
|
|
||||||
void EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor = Qt::CrossCursor);
|
void EnterPickMode(FNodeFlags AllowedNodes, bool ExitOnInvalidPick, bool EmitOnInvalidPick, bool EmitHoverOnButtonPress, QCursor Cursor = Qt::CrossCursor);
|
||||||
void ExitPickMode();
|
void ExitPickMode();
|
||||||
|
|
||||||
void NotifySelectionModified();
|
|
||||||
void NotifySelectionTransformed();
|
void NotifySelectionTransformed();
|
||||||
|
virtual void NotifyNodeAboutToBeSpawned();
|
||||||
|
virtual void NotifyNodeSpawned(CSceneNode *pNode);
|
||||||
|
virtual void NotifyNodeAboutToBeDeleted(CSceneNode *pNode);
|
||||||
|
virtual void NotifyNodeDeleted();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void NodeAboutToBeSpawned();
|
||||||
|
void NodeSpawned(CSceneNode *pNode);
|
||||||
|
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
||||||
|
void NodeDeleted();
|
||||||
void SelectionModified();
|
void SelectionModified();
|
||||||
void SelectionTransformed();
|
void SelectionTransformed();
|
||||||
|
|
||||||
|
@ -90,6 +94,7 @@ signals:
|
||||||
void PickModeHoverChanged(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
void PickModeHoverChanged(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void OnSelectionModified();
|
||||||
void OnGizmoMoved();
|
void OnGizmoMoved();
|
||||||
virtual void UpdateGizmoUI() = 0;
|
virtual void UpdateGizmoUI() = 0;
|
||||||
virtual void UpdateSelectionUI() = 0;
|
virtual void UpdateSelectionUI() = 0;
|
||||||
|
|
|
@ -499,7 +499,7 @@ Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
||||||
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPropertyModel::NotifyPropertyModified(IProperty *pProp)
|
void CPropertyModel::NotifyPropertyModified(class CScriptObject*, IProperty *pProp)
|
||||||
{
|
{
|
||||||
NotifyPropertyModified(IndexForProperty(pProp));
|
NotifyPropertyModified(IndexForProperty(pProp));
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
inline void SetBoldModifiedProperties(bool Enable) { mBoldModifiedProperties = Enable; }
|
inline void SetBoldModifiedProperties(bool Enable) { mBoldModifiedProperties = Enable; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void NotifyPropertyModified(IProperty *pProp);
|
void NotifyPropertyModified(class CScriptObject *pInst, IProperty *pProp);
|
||||||
void NotifyPropertyModified(const QModelIndex& rkIndex);
|
void NotifyPropertyModified(const QModelIndex& rkIndex);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -75,7 +75,7 @@ void CPropertyView::SetEditor(CWorldEditor *pEditor)
|
||||||
{
|
{
|
||||||
mpEditor = pEditor;
|
mpEditor = pEditor;
|
||||||
mpDelegate->SetEditor(pEditor);
|
mpDelegate->SetEditor(pEditor);
|
||||||
connect(mpEditor, SIGNAL(PropertyModified(IProperty*,bool)), mpModel, SLOT(NotifyPropertyModified(IProperty*)));
|
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), mpModel, SLOT(NotifyPropertyModified(CScriptObject*,IProperty*)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPropertyView::SetInstance(CScriptObject *pObj)
|
void CPropertyView::SetInstance(CScriptObject *pObj)
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include "CClearSelectionCommand.h"
|
|
||||||
#include "Editor/INodeEditor.h"
|
|
||||||
|
|
||||||
CClearSelectionCommand::CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection)
|
|
||||||
: IUndoCommand("Clear Selection"),
|
|
||||||
mpEditor(pEditor),
|
|
||||||
mSelectionState(selection),
|
|
||||||
mpSelection(&selection)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CClearSelectionCommand::~CClearSelectionCommand()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CClearSelectionCommand::undo()
|
|
||||||
{
|
|
||||||
mpSelection->reserve(mSelectionState.size());
|
|
||||||
|
|
||||||
foreach (CSceneNode *pNode, mSelectionState)
|
|
||||||
{
|
|
||||||
if (!pNode->IsSelected())
|
|
||||||
{
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
mpSelection->push_back(pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CClearSelectionCommand::redo()
|
|
||||||
{
|
|
||||||
foreach (CSceneNode *pNode, *mpSelection)
|
|
||||||
if (pNode->IsSelected())
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
mpSelection->clear();
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
|
@ -7,14 +7,18 @@
|
||||||
|
|
||||||
class CClearSelectionCommand : public IUndoCommand
|
class CClearSelectionCommand : public IUndoCommand
|
||||||
{
|
{
|
||||||
INodeEditor *mpEditor;
|
QList<CSceneNode*> mOldSelection;
|
||||||
QList<CSceneNode*> mSelectionState;
|
CNodeSelection *mpSelection;
|
||||||
QList<CSceneNode*> *mpSelection;
|
|
||||||
public:
|
public:
|
||||||
CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection);
|
CClearSelectionCommand(CNodeSelection *pSelection)
|
||||||
~CClearSelectionCommand();
|
: IUndoCommand("Clear Selection"),
|
||||||
void undo();
|
mOldSelection(pSelection->SelectedNodeList()),
|
||||||
void redo();
|
mpSelection(pSelection)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void undo() { mpSelection->SetSelectedNodes(mOldSelection); }
|
||||||
|
void redo() { mpSelection->Clear(); }
|
||||||
bool AffectsCleanState() const { return false; }
|
bool AffectsCleanState() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include "CCreateInstanceCommand.h"
|
||||||
|
|
||||||
|
CCreateInstanceCommand::CCreateInstanceCommand(CWorldEditor *pEditor, CScriptTemplate *pTemplate, CScriptLayer *pLayer, const CVector3f& rkPosition)
|
||||||
|
: IUndoCommand("Create Instance")
|
||||||
|
, mpEditor(pEditor)
|
||||||
|
, mpScene(pEditor->Scene())
|
||||||
|
, mpArea(pEditor->ActiveArea())
|
||||||
|
, mpTemplate(pTemplate)
|
||||||
|
, mLayerIndex(pLayer->AreaIndex())
|
||||||
|
, mSpawnPosition(rkPosition)
|
||||||
|
, mOldSelection(pEditor->Selection()->SelectedNodeList())
|
||||||
|
, mpNewInstance(nullptr)
|
||||||
|
, mpNewNode(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCreateInstanceCommand::undo()
|
||||||
|
{
|
||||||
|
mpEditor->NotifyNodeAboutToBeDeleted(mpNewNode);
|
||||||
|
mpEditor->Selection()->SetSelectedNodes(mOldSelection);
|
||||||
|
mpScene->DeleteNode(mpNewNode);
|
||||||
|
mpArea->DeleteInstance(mpNewInstance);
|
||||||
|
mpNewNode = nullptr;
|
||||||
|
mpNewInstance = nullptr;
|
||||||
|
mpEditor->NotifyNodeDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCreateInstanceCommand::redo()
|
||||||
|
{
|
||||||
|
mpEditor->NotifyNodeAboutToBeSpawned();
|
||||||
|
|
||||||
|
CScriptLayer *pLayer = (mLayerIndex == -1 ? mpArea->GetGeneratorLayer() : mpArea->GetScriptLayer(mLayerIndex));
|
||||||
|
mpNewInstance = mpArea->SpawnInstance(mpTemplate, pLayer, mSpawnPosition);
|
||||||
|
mpNewNode = mpScene->CreateScriptNode(mpNewInstance);
|
||||||
|
mpNewNode->SetPosition(mSpawnPosition);
|
||||||
|
|
||||||
|
mpEditor->NotifyNodeSpawned(mpNewNode);
|
||||||
|
mpEditor->Selection()->ClearAndSelectNode(mpNewNode);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef CCREATEINSTANCECOMMAND_H
|
||||||
|
#define CCREATEINSTANCECOMMAND_H
|
||||||
|
|
||||||
|
#include "IUndoCommand.h"
|
||||||
|
#include "CClearSelectionCommand.h"
|
||||||
|
#include "CSelectNodeCommand.h"
|
||||||
|
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||||
|
#include <Core/Resource/CGameArea.h>
|
||||||
|
#include <Core/Resource/Script/CScriptLayer.h>
|
||||||
|
#include <Core/Resource/Script/CScriptObject.h>
|
||||||
|
|
||||||
|
class CCreateInstanceCommand : public IUndoCommand
|
||||||
|
{
|
||||||
|
CWorldEditor *mpEditor;
|
||||||
|
CScene *mpScene;
|
||||||
|
CGameArea *mpArea;
|
||||||
|
CScriptTemplate *mpTemplate;
|
||||||
|
u32 mLayerIndex;
|
||||||
|
CVector3f mSpawnPosition;
|
||||||
|
|
||||||
|
QList<CSceneNode*> mOldSelection;
|
||||||
|
CScriptObject *mpNewInstance;
|
||||||
|
CScriptNode *mpNewNode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CCreateInstanceCommand(CWorldEditor *pEditor, CScriptTemplate *pTemplate, CScriptLayer *pLayer, const CVector3f& rkPosition);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
bool AffectsCleanState() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCREATEINSTANCECOMMAND_H
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include "CDeleteSelectionCommand.h"
|
||||||
|
#include "Editor/CSelectionIterator.h"
|
||||||
|
|
||||||
|
CDeleteSelectionCommand::CDeleteSelectionCommand(CWorldEditor *pEditor)
|
||||||
|
: IUndoCommand("Delete")
|
||||||
|
, mpEditor(pEditor)
|
||||||
|
{
|
||||||
|
mOldSelection = pEditor->Selection()->SelectedNodeList();
|
||||||
|
|
||||||
|
for (CSelectionIterator It(pEditor->Selection()); It; ++It)
|
||||||
|
{
|
||||||
|
if (It->NodeType() == eScriptNode)
|
||||||
|
mNodesToDelete << *It;
|
||||||
|
else
|
||||||
|
mNewSelection << *It;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDeleteSelectionCommand::undo()
|
||||||
|
{
|
||||||
|
//foreach (CSceneNode *pNode, mNodesToDelete)
|
||||||
|
// pNode->SetDeleted(false);
|
||||||
|
//mpEditor->Selection()->SetSelectedNodes(mOldSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDeleteSelectionCommand::redo()
|
||||||
|
{
|
||||||
|
mpEditor->Selection()->SetSelectedNodes(mNewSelection);
|
||||||
|
|
||||||
|
foreach (CSceneNode *pNode, mNodesToDelete)
|
||||||
|
{
|
||||||
|
CScriptObject *pInst = static_cast<CScriptNode*>(pNode)->Object();
|
||||||
|
mpEditor->NotifyNodeAboutToBeDeleted(pNode);
|
||||||
|
mpEditor->Scene()->DeleteNode(pNode);
|
||||||
|
mpEditor->ActiveArea()->DeleteInstance(pInst);
|
||||||
|
mpEditor->NotifyNodeDeleted();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef CDELETESELECTIONCOMMAND_H
|
||||||
|
#define CDELETESELECTIONCOMMAND_H
|
||||||
|
|
||||||
|
#include "IUndoCommand.h"
|
||||||
|
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||||
|
#include <Core/Scene/CSceneNode.h>
|
||||||
|
|
||||||
|
class CDeleteSelectionCommand : public IUndoCommand
|
||||||
|
{
|
||||||
|
CWorldEditor *mpEditor;
|
||||||
|
QList<CSceneNode*> mNodesToDelete;
|
||||||
|
QList<CSceneNode*> mOldSelection;
|
||||||
|
QList<CSceneNode*> mNewSelection;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CDeleteSelectionCommand(CWorldEditor *pEditor);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
bool AffectsCleanState() const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CDELETESELECTIONCOMMAND_H
|
|
@ -1,42 +0,0 @@
|
||||||
#include "CDeselectNodeCommand.h"
|
|
||||||
#include "Editor/INodeEditor.h"
|
|
||||||
|
|
||||||
CDeselectNodeCommand::CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
|
||||||
: IUndoCommand("Deselect"),
|
|
||||||
mpEditor(pEditor),
|
|
||||||
mpNode(pNode),
|
|
||||||
mpSelection(&selection)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDeselectNodeCommand::undo()
|
|
||||||
{
|
|
||||||
if (!mpNode->IsSelected())
|
|
||||||
{
|
|
||||||
mpNode->SetSelected(true);
|
|
||||||
mpSelection->push_back(mpNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpEditor->ExpandSelectionBounds(mpNode);
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDeselectNodeCommand::redo()
|
|
||||||
{
|
|
||||||
if (mpNode->IsSelected())
|
|
||||||
{
|
|
||||||
mpNode->SetSelected(false);
|
|
||||||
|
|
||||||
for (auto it = mpSelection->begin(); it != mpSelection->end(); it++)
|
|
||||||
{
|
|
||||||
if (*it == mpNode)
|
|
||||||
{
|
|
||||||
mpSelection->erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
|
@ -7,13 +7,17 @@
|
||||||
|
|
||||||
class CDeselectNodeCommand : public IUndoCommand
|
class CDeselectNodeCommand : public IUndoCommand
|
||||||
{
|
{
|
||||||
INodeEditor *mpEditor;
|
|
||||||
CSceneNode *mpNode;
|
CSceneNode *mpNode;
|
||||||
QList<CSceneNode*> *mpSelection;
|
CNodeSelection *mpSelection;
|
||||||
public:
|
public:
|
||||||
CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
CDeselectNodeCommand(CNodeSelection *pSelection, CSceneNode *pNode)
|
||||||
void undo();
|
: IUndoCommand("Deselect")
|
||||||
void redo();
|
, mpNode(pNode)
|
||||||
|
, mpSelection(pSelection)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void undo() { mpSelection->SelectNode(mpNode); }
|
||||||
|
void redo() { mpSelection->DeselectNode(mpNode); }
|
||||||
bool AffectsCleanState() const { return false; }
|
bool AffectsCleanState() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#include "CInvertSelectionCommand.h"
|
|
||||||
#include <Core/Scene/CSceneIterator.h>
|
|
||||||
|
|
||||||
CInvertSelectionCommand::CInvertSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags)
|
|
||||||
: IUndoCommand("Invert Selection")
|
|
||||||
, mpEditor(pEditor)
|
|
||||||
, mOldSelection(rSelection)
|
|
||||||
, mpSelection(&rSelection)
|
|
||||||
{
|
|
||||||
CSceneIterator it(pScene, NodeFlags);
|
|
||||||
|
|
||||||
while (!it.DoneIterating())
|
|
||||||
{
|
|
||||||
if (!it->IsSelected())
|
|
||||||
mNewSelection.append(*it);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CInvertSelectionCommand::~CInvertSelectionCommand()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInvertSelectionCommand::undo()
|
|
||||||
{
|
|
||||||
*mpSelection = mOldSelection;
|
|
||||||
|
|
||||||
// Deselect all nodes in new selection
|
|
||||||
foreach (CSceneNode *pNode, mNewSelection)
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
// Select all nodes in the old selection
|
|
||||||
foreach (CSceneNode *pNode, mOldSelection)
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
|
|
||||||
// Update editor
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInvertSelectionCommand::redo()
|
|
||||||
{
|
|
||||||
*mpSelection = mNewSelection;
|
|
||||||
|
|
||||||
// Deselect all nodes in the old selection
|
|
||||||
foreach (CSceneNode *pNode, mOldSelection)
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
// Select all nodes in the new selection
|
|
||||||
foreach (CSceneNode *pNode, mNewSelection)
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
|
|
||||||
// Update editor
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
|
@ -7,17 +7,27 @@
|
||||||
|
|
||||||
class CInvertSelectionCommand : public IUndoCommand
|
class CInvertSelectionCommand : public IUndoCommand
|
||||||
{
|
{
|
||||||
INodeEditor *mpEditor;
|
CNodeSelection *mpSelection;
|
||||||
QList<CSceneNode*> mOldSelection;
|
QList<CSceneNode*> mOldSelection;
|
||||||
QList<CSceneNode*> mNewSelection;
|
QList<CSceneNode*> mNewSelection;
|
||||||
QList<CSceneNode*> *mpSelection;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CInvertSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags);
|
CInvertSelectionCommand(CNodeSelection *pSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||||
~CInvertSelectionCommand();
|
: IUndoCommand("Invert Selection")
|
||||||
void undo();
|
, mpSelection(pSelection)
|
||||||
void redo();
|
{
|
||||||
virtual bool AffectsCleanState() const { return false; }
|
for (CSceneIterator It(pScene, NodeFlags); It; ++It)
|
||||||
|
{
|
||||||
|
if (It->IsSelected())
|
||||||
|
mOldSelection << *It;
|
||||||
|
else
|
||||||
|
mNewSelection << *It;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() { mpSelection->SetSelectedNodes(mOldSelection); }
|
||||||
|
void redo() { mpSelection->SetSelectedNodes(mNewSelection); }
|
||||||
|
bool AffectsCleanState() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CINVERTSELECTIONCOMMAND_H
|
#endif // CINVERTSELECTIONCOMMAND_H
|
||||||
|
|
|
@ -79,7 +79,6 @@ void CRotateNodeCommand::undo()
|
||||||
rotate.pNode->SetRotation(rotate.initialRot);
|
rotate.pNode->SetRotation(rotate.initialRot);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +93,6 @@ void CRotateNodeCommand::redo()
|
||||||
rotate.pNode->SetRotation(rotate.newRot);
|
rotate.pNode->SetRotation(rotate.newRot);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,6 @@ void CScaleNodeCommand::undo()
|
||||||
scale.pNode->SetScale(scale.initialScale);
|
scale.pNode->SetScale(scale.initialScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +93,6 @@ void CScaleNodeCommand::redo()
|
||||||
scale.pNode->SetScale(scale.newScale);
|
scale.pNode->SetScale(scale.newScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#include "CSelectAllCommand.h"
|
|
||||||
#include <Core/Scene/CSceneIterator.h>
|
|
||||||
|
|
||||||
CSelectAllCommand::CSelectAllCommand(INodeEditor *pEditor, QList<CSceneNode *> &rSelection, CScene *pScene, FNodeFlags NodeFlags)
|
|
||||||
: IUndoCommand("Select All")
|
|
||||||
, mpEditor(pEditor)
|
|
||||||
, mOldSelection(rSelection)
|
|
||||||
, mpSelection(&rSelection)
|
|
||||||
{
|
|
||||||
CSceneIterator it(pScene, NodeFlags);
|
|
||||||
|
|
||||||
while (!it.DoneIterating())
|
|
||||||
{
|
|
||||||
mNewSelection.append(*it);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CSelectAllCommand::~CSelectAllCommand()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CSelectAllCommand::undo()
|
|
||||||
{
|
|
||||||
*mpSelection = mOldSelection;
|
|
||||||
|
|
||||||
// Deselect all nodes in new selection
|
|
||||||
foreach (CSceneNode *pNode, mNewSelection)
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
// Select all nodes in the old selection
|
|
||||||
foreach (CSceneNode *pNode, mOldSelection)
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
|
|
||||||
// Update editor
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSelectAllCommand::redo()
|
|
||||||
{
|
|
||||||
*mpSelection = mNewSelection;
|
|
||||||
|
|
||||||
// Deselect all nodes in the old selection
|
|
||||||
foreach (CSceneNode *pNode, mOldSelection)
|
|
||||||
pNode->SetSelected(false);
|
|
||||||
|
|
||||||
// Select all nodes in the new selection
|
|
||||||
foreach (CSceneNode *pNode, mNewSelection)
|
|
||||||
pNode->SetSelected(true);
|
|
||||||
|
|
||||||
// Update editor
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
|
@ -7,16 +7,22 @@
|
||||||
|
|
||||||
class CSelectAllCommand : public IUndoCommand
|
class CSelectAllCommand : public IUndoCommand
|
||||||
{
|
{
|
||||||
INodeEditor *mpEditor;
|
|
||||||
QList<CSceneNode*> mOldSelection;
|
QList<CSceneNode*> mOldSelection;
|
||||||
QList<CSceneNode*> mNewSelection;
|
QList<CSceneNode*> mNewSelection;
|
||||||
QList<CSceneNode*> *mpSelection;
|
CNodeSelection *mpSelection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSelectAllCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags);
|
CSelectAllCommand(CNodeSelection *pSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||||
~CSelectAllCommand();
|
: IUndoCommand("Select All")
|
||||||
void undo();
|
, mOldSelection(pSelection->SelectedNodeList())
|
||||||
void redo();
|
, mpSelection(pSelection)
|
||||||
|
{
|
||||||
|
for (CSceneIterator It(pScene, NodeFlags); It; ++It)
|
||||||
|
mNewSelection << *It;
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() { mpSelection->SetSelectedNodes(mOldSelection); }
|
||||||
|
void redo() { mpSelection->SetSelectedNodes(mNewSelection); }
|
||||||
bool AffectsCleanState() const { return false; }
|
bool AffectsCleanState() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#include "CSelectNodeCommand.h"
|
|
||||||
#include "Editor/INodeEditor.h"
|
|
||||||
|
|
||||||
CSelectNodeCommand::CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
|
||||||
: IUndoCommand("Select"),
|
|
||||||
mpEditor(pEditor),
|
|
||||||
mpNode(pNode),
|
|
||||||
mpSelection(&selection)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSelectNodeCommand::undo()
|
|
||||||
{
|
|
||||||
if (mpNode->IsSelected())
|
|
||||||
{
|
|
||||||
mpNode->SetSelected(false);
|
|
||||||
|
|
||||||
for (auto it = mpSelection->begin(); it != mpSelection->end(); it++)
|
|
||||||
{
|
|
||||||
if (*it == mpNode)
|
|
||||||
{
|
|
||||||
mpSelection->erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSelectNodeCommand::redo()
|
|
||||||
{
|
|
||||||
if (!mpNode->IsSelected())
|
|
||||||
{
|
|
||||||
mpNode->SetSelected(true);
|
|
||||||
mpSelection->push_back(mpNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
mpEditor->ExpandSelectionBounds(mpNode);
|
|
||||||
mpEditor->NotifySelectionModified();
|
|
||||||
}
|
|
|
@ -7,13 +7,18 @@
|
||||||
|
|
||||||
class CSelectNodeCommand : public IUndoCommand
|
class CSelectNodeCommand : public IUndoCommand
|
||||||
{
|
{
|
||||||
INodeEditor *mpEditor;
|
|
||||||
CSceneNode *mpNode;
|
CSceneNode *mpNode;
|
||||||
QList<CSceneNode*> *mpSelection;
|
CNodeSelection *mpSelection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
CSelectNodeCommand(CNodeSelection *pSelection, CSceneNode *pNode)
|
||||||
void undo();
|
: IUndoCommand("Select")
|
||||||
void redo();
|
, mpNode(pNode)
|
||||||
|
, mpSelection(pSelection)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void undo() { mpSelection->DeselectNode(mpNode); }
|
||||||
|
void redo() { mpSelection->SelectNode(mpNode); }
|
||||||
bool AffectsCleanState() const { return false; }
|
bool AffectsCleanState() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,6 @@ void CTranslateNodeCommand::undo()
|
||||||
foreach (SNodeTranslate translate, mNodeList)
|
foreach (SNodeTranslate translate, mNodeList)
|
||||||
translate.pNode->SetPosition(translate.initialPos);
|
translate.pNode->SetPosition(translate.initialPos);
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
@ -83,7 +82,6 @@ void CTranslateNodeCommand::redo()
|
||||||
foreach (SNodeTranslate translate, mNodeList)
|
foreach (SNodeTranslate translate, mNodeList)
|
||||||
translate.pNode->SetPosition(translate.newPos);
|
translate.pNode->SetPosition(translate.newPos);
|
||||||
|
|
||||||
mpEditor->RecalculateSelectionBounds();
|
|
||||||
mpEditor->NotifySelectionTransformed();
|
mpEditor->NotifySelectionTransformed();
|
||||||
mpEditor->UpdateGizmoUI();
|
mpEditor->UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef UNDOCOMMANDS
|
#ifndef UNDOCOMMANDS
|
||||||
#define UNDOCOMMANDS
|
#define UNDOCOMMANDS
|
||||||
|
|
||||||
|
#include "CCreateInstanceCommand.h"
|
||||||
|
|
||||||
#include "CTranslateNodeCommand.h"
|
#include "CTranslateNodeCommand.h"
|
||||||
#include "CRotateNodeCommand.h"
|
#include "CRotateNodeCommand.h"
|
||||||
#include "CScaleNodeCommand.h"
|
#include "CScaleNodeCommand.h"
|
||||||
|
@ -10,6 +12,7 @@
|
||||||
#include "CClearSelectionCommand.h"
|
#include "CClearSelectionCommand.h"
|
||||||
#include "CSelectAllCommand.h"
|
#include "CSelectAllCommand.h"
|
||||||
#include "CInvertSelectionCommand.h"
|
#include "CInvertSelectionCommand.h"
|
||||||
|
#include "CDeleteSelectionCommand.h"
|
||||||
|
|
||||||
#include "CEditScriptPropertyCommand.h"
|
#include "CEditScriptPropertyCommand.h"
|
||||||
#include "CResizeScriptArrayCommand.h"
|
#include "CResizeScriptArrayCommand.h"
|
||||||
|
|
|
@ -26,11 +26,6 @@
|
||||||
#define TYPES_NODE_TYPE_SHIFT 1
|
#define TYPES_NODE_TYPE_SHIFT 1
|
||||||
#define TYPES_ITEM_TYPE_SHIFT 0
|
#define TYPES_ITEM_TYPE_SHIFT 0
|
||||||
|
|
||||||
bool SortTemplatesAlphabetical(CScriptTemplate *pA, CScriptTemplate *pB)
|
|
||||||
{
|
|
||||||
return (pA->Name() < pB->Name());
|
|
||||||
}
|
|
||||||
|
|
||||||
CInstancesModel::CInstancesModel(QObject *pParent) : QAbstractItemModel(pParent)
|
CInstancesModel::CInstancesModel(QObject *pParent) : QAbstractItemModel(pParent)
|
||||||
{
|
{
|
||||||
mpEditor = nullptr;
|
mpEditor = nullptr;
|
||||||
|
@ -40,6 +35,7 @@ CInstancesModel::CInstancesModel(QObject *pParent) : QAbstractItemModel(pParent)
|
||||||
mModelType = eLayers;
|
mModelType = eLayers;
|
||||||
mShowColumnEnabled = true;
|
mShowColumnEnabled = true;
|
||||||
mBaseItems << "Script";
|
mBaseItems << "Script";
|
||||||
|
mAddingOrRemovingRows = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CInstancesModel::~CInstancesModel()
|
CInstancesModel::~CInstancesModel()
|
||||||
|
@ -319,6 +315,11 @@ void CInstancesModel::SetEditor(CWorldEditor *pEditor)
|
||||||
|
|
||||||
mpEditor = pEditor;
|
mpEditor = pEditor;
|
||||||
mpScene = (pEditor ? pEditor->Scene() : nullptr);
|
mpScene = (pEditor ? pEditor->Scene() : nullptr);
|
||||||
|
connect(mpEditor, SIGNAL(NodeAboutToBeSpawned()), this, SLOT(NodeAboutToBeCreated()));
|
||||||
|
connect(mpEditor, SIGNAL(NodeSpawned(CSceneNode*)), this, SLOT(NodeCreated(CSceneNode*)));
|
||||||
|
connect(mpEditor, SIGNAL(NodeAboutToBeDeleted(CSceneNode*)), this, SLOT(NodeAboutToBeDeleted(CSceneNode*)));
|
||||||
|
connect(mpEditor, SIGNAL(NodeDeleted()), this, SLOT(NodeDeleted()));
|
||||||
|
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(PropertyModified(CScriptObject*,IProperty*)));
|
||||||
connect(mpEditor, SIGNAL(InstancesLayerAboutToChange()), this, SLOT(InstancesLayerPreChange()));
|
connect(mpEditor, SIGNAL(InstancesLayerAboutToChange()), this, SLOT(InstancesLayerPreChange()));
|
||||||
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(InstancesLayerPostChange(QList<CScriptNode*>)));
|
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(InstancesLayerPostChange(QList<CScriptNode*>)));
|
||||||
}
|
}
|
||||||
|
@ -347,52 +348,6 @@ void CInstancesModel::SetShowColumnEnabled(bool Enabled)
|
||||||
emit layoutChanged();
|
emit layoutChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInstancesModel::NodeCreated(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
if (mModelType == eTypes)
|
|
||||||
{
|
|
||||||
if (pNode->NodeType() == eScriptNode)
|
|
||||||
{
|
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
|
||||||
CScriptObject *pObj = pScript->Object();
|
|
||||||
pObj->Template()->SortObjects();
|
|
||||||
|
|
||||||
if (pObj->Template()->NumObjects() == 1)
|
|
||||||
{
|
|
||||||
mTemplateList << pObj->Template();
|
|
||||||
qSort(mTemplateList.begin(), mTemplateList.end(), SortTemplatesAlphabetical);
|
|
||||||
emit layoutChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInstancesModel::NodeDeleted(CSceneNode *pNode)
|
|
||||||
{
|
|
||||||
if (mModelType = eTypes)
|
|
||||||
{
|
|
||||||
if (pNode->NodeType() == eScriptNode)
|
|
||||||
{
|
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
|
||||||
CScriptObject *pObj = pScript->Object();
|
|
||||||
|
|
||||||
if (pObj->Template()->NumObjects() == 0)
|
|
||||||
{
|
|
||||||
for (auto it = mTemplateList.begin(); it != mTemplateList.end(); it++)
|
|
||||||
{
|
|
||||||
if (*it == pObj->Template())
|
|
||||||
{
|
|
||||||
mTemplateList.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit layoutChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CScriptLayer* CInstancesModel::IndexLayer(const QModelIndex& index) const
|
CScriptLayer* CInstancesModel::IndexLayer(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
if ((mModelType != eLayers) || (IndexNodeType(index) != eScriptType) || (IndexType(index) != eObjectTypeIndex))
|
if ((mModelType != eLayers) || (IndexNodeType(index) != eScriptType) || (IndexType(index) != eObjectTypeIndex))
|
||||||
|
@ -420,6 +375,107 @@ CScriptObject* CInstancesModel::IndexObject(const QModelIndex& index) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PUBLIC SLOTS ************
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void CInstancesModel::NodeAboutToBeCreated()
|
||||||
|
{
|
||||||
|
if (!mAddingOrRemovingRows)
|
||||||
|
{
|
||||||
|
emit layoutAboutToBeChanged();
|
||||||
|
mAddingOrRemovingRows = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInstancesModel::NodeCreated(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (mModelType == eTypes)
|
||||||
|
{
|
||||||
|
if (pNode->NodeType() == eScriptNode)
|
||||||
|
{
|
||||||
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
||||||
|
CScriptObject *pObj = pScript->Object();
|
||||||
|
pObj->Template()->SortObjects();
|
||||||
|
|
||||||
|
if (pObj->Template()->NumObjects() == 1)
|
||||||
|
{
|
||||||
|
QModelIndex ScriptRootIdx = index(0, 0, QModelIndex());
|
||||||
|
int NewIndex = 0;
|
||||||
|
|
||||||
|
for (; NewIndex < mTemplateList.size(); NewIndex++)
|
||||||
|
{
|
||||||
|
if (mTemplateList[NewIndex]->Name() > pObj->Template()->Name())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows(ScriptRootIdx, NewIndex, NewIndex);
|
||||||
|
mTemplateList.insert(NewIndex, pObj->Template());
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit layoutChanged();
|
||||||
|
mAddingOrRemovingRows = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInstancesModel::NodeAboutToBeDeleted(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
if (!mAddingOrRemovingRows)
|
||||||
|
{
|
||||||
|
emit layoutAboutToBeChanged();
|
||||||
|
mAddingOrRemovingRows = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mModelType == eTypes)
|
||||||
|
{
|
||||||
|
if (pNode->NodeType() == eScriptNode)
|
||||||
|
{
|
||||||
|
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
||||||
|
CScriptObject *pObj = pScript->Object();
|
||||||
|
|
||||||
|
if (pObj->Template()->NumObjects() <= 1)
|
||||||
|
{
|
||||||
|
QModelIndex ScriptRootIdx = index(0, 0, QModelIndex());
|
||||||
|
int TempIdx = mTemplateList.indexOf(pObj->Template());
|
||||||
|
beginRemoveRows(ScriptRootIdx, TempIdx, TempIdx);
|
||||||
|
mTemplateList.removeOne(pObj->Template());
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInstancesModel::NodeDeleted()
|
||||||
|
{
|
||||||
|
emit layoutChanged();
|
||||||
|
mAddingOrRemovingRows = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInstancesModel::PropertyModified(CScriptObject *pInst, IProperty *pProp)
|
||||||
|
{
|
||||||
|
if (pInst->InstanceNameProperty() == pProp)
|
||||||
|
{
|
||||||
|
QModelIndex ScriptRoot = index(0, 0, QModelIndex());
|
||||||
|
|
||||||
|
if (mModelType == eLayers)
|
||||||
|
{
|
||||||
|
u32 Index = pInst->Layer()->AreaIndex();
|
||||||
|
QModelIndex LayerIndex = index(Index, 0, ScriptRoot);
|
||||||
|
QModelIndex InstIndex = index(pInst->LayerIndex(), 0, LayerIndex);
|
||||||
|
emit dataChanged(InstIndex, InstIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 Index = mTemplateList.indexOf(pInst->Template());
|
||||||
|
QModelIndex TempIndex = index(Index, 0, ScriptRoot);
|
||||||
|
|
||||||
|
QList<CScriptObject*> InstList = QList<CScriptObject*>::fromStdList(pInst->Template()->ObjectList());
|
||||||
|
u32 InstIdx = InstList.indexOf(pInst);
|
||||||
|
QModelIndex InstIndex = index(InstIdx, 0, TempIndex);
|
||||||
|
emit dataChanged(InstIndex, InstIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CInstancesModel::InstancesLayerPreChange()
|
void CInstancesModel::InstancesLayerPreChange()
|
||||||
{
|
{
|
||||||
// This is only really needed on layers, which have rows moved.
|
// This is only really needed on layers, which have rows moved.
|
||||||
|
@ -501,7 +557,9 @@ void CInstancesModel::GenerateList()
|
||||||
mTemplateList << pTemp;
|
mTemplateList << pTemp;
|
||||||
}
|
}
|
||||||
|
|
||||||
qSort(mTemplateList.begin(), mTemplateList.end(), SortTemplatesAlphabetical);
|
qSort(mTemplateList.begin(), mTemplateList.end(), [](CScriptTemplate *pLeft, CScriptTemplate *pRight) -> bool {
|
||||||
|
return (pLeft->Name() < pRight->Name());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
|
@ -37,6 +37,7 @@ private:
|
||||||
QList<CScriptTemplate*> mTemplateList;
|
QList<CScriptTemplate*> mTemplateList;
|
||||||
QStringList mBaseItems;
|
QStringList mBaseItems;
|
||||||
bool mShowColumnEnabled;
|
bool mShowColumnEnabled;
|
||||||
|
bool mAddingOrRemovingRows;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CInstancesModel(QObject *pParent = 0);
|
explicit CInstancesModel(QObject *pParent = 0);
|
||||||
|
@ -53,13 +54,17 @@ public:
|
||||||
void SetArea(CGameArea *pArea);
|
void SetArea(CGameArea *pArea);
|
||||||
void SetModelType(EInstanceModelType type);
|
void SetModelType(EInstanceModelType type);
|
||||||
void SetShowColumnEnabled(bool Enabled);
|
void SetShowColumnEnabled(bool Enabled);
|
||||||
void NodeCreated(CSceneNode *pNode);
|
|
||||||
void NodeDeleted(CSceneNode *pNode);
|
|
||||||
CScriptLayer* IndexLayer(const QModelIndex& index) const;
|
CScriptLayer* IndexLayer(const QModelIndex& index) const;
|
||||||
CScriptTemplate* IndexTemplate(const QModelIndex& index) const;
|
CScriptTemplate* IndexTemplate(const QModelIndex& index) const;
|
||||||
CScriptObject* IndexObject(const QModelIndex& index) const;
|
CScriptObject* IndexObject(const QModelIndex& index) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void NodeAboutToBeCreated();
|
||||||
|
void NodeCreated(CSceneNode *pNode);
|
||||||
|
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
||||||
|
void NodeDeleted();
|
||||||
|
|
||||||
|
void PropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||||
void InstancesLayerPreChange();
|
void InstancesLayerPreChange();
|
||||||
void InstancesLayerPostChange(const QList<CScriptNode*>& rkInstanceList);
|
void InstancesLayerPostChange(const QList<CScriptNode*>& rkInstanceList);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ QVariant CLinkModel::data(const QModelIndex &index, int role) const
|
||||||
case 0: // Column 0 - Target Object
|
case 0: // Column 0 - Target Object
|
||||||
{
|
{
|
||||||
u32 TargetID = (mType == eIncoming ? pLink->SenderID() : pLink->ReceiverID());
|
u32 TargetID = (mType == eIncoming ? pLink->SenderID() : pLink->ReceiverID());
|
||||||
CScriptObject *pTarget = mpObject->Area()->GetInstanceByID(TargetID);
|
CScriptObject *pTarget = mpObject->Area()->InstanceByID(TargetID);
|
||||||
|
|
||||||
if (pTarget) {
|
if (pTarget) {
|
||||||
QString ObjType = QString("[%1] ").arg(UICommon::ToQString(pTarget->Template()->Name()));
|
QString ObjType = QString("[%1] ").arg(UICommon::ToQString(pTarget->Template()->Name()));
|
||||||
|
|
|
@ -69,7 +69,7 @@ QVariant CPoiMapModel::data(const QModelIndex& rkIndex, int Role) const
|
||||||
if (rkIndex.row() < rowCount(QModelIndex()))
|
if (rkIndex.row() < rowCount(QModelIndex()))
|
||||||
{
|
{
|
||||||
const CPoiToWorld::SPoiMap *pkMap = mpPoiToWorld->MapByIndex(rkIndex.row());
|
const CPoiToWorld::SPoiMap *pkMap = mpPoiToWorld->MapByIndex(rkIndex.row());
|
||||||
CScriptObject *pPOI = mpArea->GetInstanceByID(pkMap->PoiID);
|
CScriptObject *pPOI = mpArea->InstanceByID(pkMap->PoiID);
|
||||||
|
|
||||||
if (Role == Qt::DisplayRole)
|
if (Role == Qt::DisplayRole)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
#ifndef CTEMPLATELISTVIEW
|
||||||
|
#define CTEMPLATELISTVIEW
|
||||||
|
|
||||||
|
#include "CTemplateMimeData.h"
|
||||||
|
#include "Editor/UICommon.h"
|
||||||
|
#include <Core/Resource/Script/CMasterTemplate.h>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QListView>
|
||||||
|
|
||||||
|
class CTemplateListModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
CMasterTemplate *mpMaster;
|
||||||
|
QList<CScriptTemplate*> mTemplates;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTemplateListModel(QObject *pParent = 0)
|
||||||
|
: QAbstractListModel(pParent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex&) const
|
||||||
|
{
|
||||||
|
return mTemplates.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& rkIndex, int Role) const
|
||||||
|
{
|
||||||
|
if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole)
|
||||||
|
return TO_QSTRING(mTemplates[rkIndex.row()]->Name());
|
||||||
|
else
|
||||||
|
return QVariant::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions supportedDropActions() const
|
||||||
|
{
|
||||||
|
return Qt::IgnoreAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions supportedDragActions() const
|
||||||
|
{
|
||||||
|
return Qt::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* mimeData(const QModelIndexList& rkIndices) const
|
||||||
|
{
|
||||||
|
if (rkIndices.size() != 1) return nullptr;
|
||||||
|
QModelIndex Index = rkIndices.front();
|
||||||
|
CScriptTemplate *pTemp = TemplateForIndex(Index);
|
||||||
|
return new CTemplateMimeData(pTemp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags flags(const QModelIndex&) const
|
||||||
|
{
|
||||||
|
return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMaster(CMasterTemplate *pMaster)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
mpMaster = pMaster;
|
||||||
|
mTemplates.clear();
|
||||||
|
|
||||||
|
for (u32 iTemp = 0; iTemp < mpMaster->NumScriptTemplates(); iTemp++)
|
||||||
|
mTemplates << mpMaster->TemplateByIndex(iTemp);
|
||||||
|
|
||||||
|
qSort(mTemplates.begin(), mTemplates.end(), [](CScriptTemplate *pLeft, CScriptTemplate *pRight) -> bool {
|
||||||
|
return pLeft->Name() < pRight->Name();
|
||||||
|
});
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CScriptTemplate* TemplateForIndex(const QModelIndex& rkIndex) const
|
||||||
|
{
|
||||||
|
return mTemplates[rkIndex.row()];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTemplateListView : public QListView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
CTemplateListModel *mpModel;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTemplateListView(QWidget *pParent = 0)
|
||||||
|
: QListView(pParent)
|
||||||
|
{
|
||||||
|
setModel(new CTemplateListModel(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setModel(QAbstractItemModel *pModel)
|
||||||
|
{
|
||||||
|
if (CTemplateListModel *pTempModel = qobject_cast<CTemplateListModel*>(pModel))
|
||||||
|
mpModel = pTempModel;
|
||||||
|
else
|
||||||
|
mpModel = nullptr;
|
||||||
|
|
||||||
|
QListView::setModel(mpModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetMaster(CMasterTemplate *pMaster)
|
||||||
|
{
|
||||||
|
if (mpModel) mpModel->SetMaster(pMaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startDrag(Qt::DropActions)
|
||||||
|
{
|
||||||
|
QModelIndexList Selection = selectionModel()->selectedRows();
|
||||||
|
|
||||||
|
if (Selection.size() == 1 && mpModel)
|
||||||
|
{
|
||||||
|
QDrag *pDrag = new QDrag(this);
|
||||||
|
pDrag->setMimeData(mpModel->mimeData(Selection));
|
||||||
|
pDrag->setPixmap(QPixmap());
|
||||||
|
pDrag->exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CTEMPLATELISTVIEW
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef CTEMPLATEMIMEDATA_H
|
||||||
|
#define CTEMPLATEMIMEDATA_H
|
||||||
|
|
||||||
|
#include <Core/Resource/Script/CScriptTemplate.h>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
|
class CTemplateMimeData : public QMimeData
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
CScriptTemplate *mpTemplate;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTemplateMimeData(CScriptTemplate *pTemplate)
|
||||||
|
: mpTemplate(pTemplate)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline CScriptTemplate* Template() const { return mpTemplate; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CTEMPLATEMIMEDATA_H
|
|
@ -1,17 +1,18 @@
|
||||||
#include "CWorldEditor.h"
|
#include "CWorldEditor.h"
|
||||||
#include "ui_CWorldEditor.h"
|
#include "ui_CWorldEditor.h"
|
||||||
|
|
||||||
#include "CConfirmUnlinkDialog.h"
|
#include "CConfirmUnlinkDialog.h"
|
||||||
#include "CLayerEditor.h"
|
#include "CLayerEditor.h"
|
||||||
|
#include "CTemplateMimeData.h"
|
||||||
#include "WModifyTab.h"
|
#include "WModifyTab.h"
|
||||||
#include "WInstancesTab.h"
|
#include "WInstancesTab.h"
|
||||||
|
|
||||||
#include "Editor/CBasicViewport.h"
|
#include "Editor/CBasicViewport.h"
|
||||||
|
#include "Editor/CSelectionIterator.h"
|
||||||
|
#include "Editor/UICommon.h"
|
||||||
#include "Editor/PropertyEdit/CPropertyView.h"
|
#include "Editor/PropertyEdit/CPropertyView.h"
|
||||||
#include "Editor/Widgets/WDraggableSpinBox.h"
|
#include "Editor/Widgets/WDraggableSpinBox.h"
|
||||||
#include "Editor/Widgets/WVectorEditor.h"
|
#include "Editor/Widgets/WVectorEditor.h"
|
||||||
#include "Editor/Undo/UndoCommands.h"
|
#include "Editor/Undo/UndoCommands.h"
|
||||||
#include "Editor/UICommon.h"
|
|
||||||
|
|
||||||
#include <Core/Render/CDrawUtil.h>
|
#include <Core/Render/CDrawUtil.h>
|
||||||
#include <Core/Resource/Cooker/CAreaCooker.h>
|
#include <Core/Resource/Cooker/CAreaCooker.h>
|
||||||
|
@ -38,7 +39,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
Log::Write("Creating World Editor");
|
Log::Write("Creating World Editor");
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
mSelectionNodeFlags = eScriptNode | eLightNode;
|
mpSelection->SetAllowedNodeTypes(eScriptNode | eLightNode);
|
||||||
|
|
||||||
// Start refresh timer
|
// Start refresh timer
|
||||||
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
||||||
|
@ -51,6 +52,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
|
|
||||||
// Initialize UI stuff
|
// Initialize UI stuff
|
||||||
ui->MainViewport->SetScene(this, &mScene);
|
ui->MainViewport->SetScene(this, &mScene);
|
||||||
|
ui->CreateTabContents->SetEditor(this);
|
||||||
ui->ModifyTabContents->SetEditor(this);
|
ui->ModifyTabContents->SetEditor(this);
|
||||||
ui->InstancesTabContents->SetEditor(this, &mScene);
|
ui->InstancesTabContents->SetEditor(this, &mScene);
|
||||||
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
||||||
|
@ -66,6 +68,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
// Initialize actions
|
// Initialize actions
|
||||||
addAction(ui->ActionIncrementGizmo);
|
addAction(ui->ActionIncrementGizmo);
|
||||||
addAction(ui->ActionDecrementGizmo);
|
addAction(ui->ActionDecrementGizmo);
|
||||||
|
addAction(ui->ActionDelete);
|
||||||
|
|
||||||
QAction *pToolBarUndo = mUndoStack.createUndoAction(this);
|
QAction *pToolBarUndo = mUndoStack.createUndoAction(this);
|
||||||
pToolBarUndo->setIcon(QIcon(":/icons/Undo.png"));
|
pToolBarUndo->setIcon(QIcon(":/icons/Undo.png"));
|
||||||
|
@ -93,6 +96,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
||||||
connect(ui->ActionLink, SIGNAL(toggled(bool)), this, SLOT(OnLinkButtonToggled(bool)));
|
connect(ui->ActionLink, SIGNAL(toggled(bool)), this, SLOT(OnLinkButtonToggled(bool)));
|
||||||
connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked()));
|
connect(ui->ActionUnlink, SIGNAL(triggered()), this, SLOT(OnUnlinkClicked()));
|
||||||
|
connect(ui->ActionDelete, SIGNAL(triggered()), this, SLOT(DeleteSelection()));
|
||||||
connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged()));
|
connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged()));
|
||||||
|
|
||||||
connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save()));
|
connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save()));
|
||||||
|
@ -100,6 +104,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
||||||
ui->CreateTabEditorProperties->SyncToEditor(this);
|
ui->CreateTabEditorProperties->SyncToEditor(this);
|
||||||
ui->ModifyTabEditorProperties->SyncToEditor(this);
|
ui->ModifyTabEditorProperties->SyncToEditor(this);
|
||||||
ui->InstancesTabEditorProperties->SyncToEditor(this);
|
ui->InstancesTabEditorProperties->SyncToEditor(this);
|
||||||
|
ui->MainViewport->setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CWorldEditor::~CWorldEditor()
|
CWorldEditor::~CWorldEditor()
|
||||||
|
@ -127,12 +132,7 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWorldEditor::eventFilter(QObject * /*pObj*/, QEvent * /*pEvent*/)
|
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
|
||||||
{
|
{
|
||||||
ExitPickMode();
|
ExitPickMode();
|
||||||
ui->MainViewport->ResetHover();
|
ui->MainViewport->ResetHover();
|
||||||
|
@ -181,6 +181,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
||||||
|
|
||||||
// Set up sidebar tabs
|
// Set up sidebar tabs
|
||||||
CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(mpArea->Version());
|
CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(mpArea->Version());
|
||||||
|
ui->CreateTabContents->SetMaster(pMaster);
|
||||||
ui->InstancesTabContents->SetMaster(pMaster);
|
ui->InstancesTabContents->SetMaster(pMaster);
|
||||||
|
|
||||||
// Set up dialogs
|
// Set up dialogs
|
||||||
|
@ -192,8 +193,8 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
||||||
|
|
||||||
if (CurrentGame() < eReturns)
|
if (CurrentGame() < eReturns)
|
||||||
{
|
{
|
||||||
CStringTable *pAreaNameTable = mpWorld->GetAreaName(AreaIndex);
|
CStringTable *pAreaNameTable = mpWorld->GetAreaName(mpArea->WorldIndex());
|
||||||
TWideString AreaName = pAreaNameTable ? pAreaNameTable->GetString("ENGL", 0) : (TWideString("!") + mpWorld->GetAreaInternalName(AreaIndex).ToUTF16());
|
TWideString AreaName = pAreaNameTable ? pAreaNameTable->GetString("ENGL", 0) : (TWideString("!") + mpWorld->GetAreaInternalName(mpArea->WorldIndex()).ToUTF16());
|
||||||
|
|
||||||
if (AreaName.IsEmpty())
|
if (AreaName.IsEmpty())
|
||||||
AreaName = "[Untitled Area]";
|
AreaName = "[Untitled Area]";
|
||||||
|
@ -206,7 +207,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
||||||
{
|
{
|
||||||
QString LevelName;
|
QString LevelName;
|
||||||
if (pWorldNameTable) LevelName = TO_QSTRING(WorldName);
|
if (pWorldNameTable) LevelName = TO_QSTRING(WorldName);
|
||||||
else LevelName = "!" + TO_QSTRING(mpWorld->GetAreaInternalName(AreaIndex));
|
else LevelName = "!" + TO_QSTRING(mpWorld->GetAreaInternalName(mpArea->WorldIndex()));
|
||||||
|
|
||||||
setWindowTitle(QString("Prime World Editor - %1[*]").arg(LevelName));
|
setWindowTitle(QString("Prime World Editor - %1[*]").arg(LevelName));
|
||||||
Log::Write("Loaded level: World " + mpWorld->Source() + " / Area " + mpArea->Source() + " (" + TO_TSTRING(LevelName) + ")");
|
Log::Write("Loaded level: World " + mpWorld->Source() + " / Area " + mpArea->Source() + " (" + TO_TSTRING(LevelName) + ")");
|
||||||
|
@ -238,7 +239,20 @@ bool CWorldEditor::CheckUnsavedChanges()
|
||||||
return OkToClear;
|
return OkToClear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSceneViewport* CWorldEditor::Viewport() const
|
||||||
|
{
|
||||||
|
return ui->MainViewport;
|
||||||
|
}
|
||||||
|
|
||||||
// ************ PUBLIC SLOTS ************
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void CWorldEditor::NotifyNodeAboutToBeDeleted(CSceneNode *pNode)
|
||||||
|
{
|
||||||
|
INodeEditor::NotifyNodeAboutToBeDeleted(pNode);
|
||||||
|
|
||||||
|
if (ui->MainViewport->HoverNode() == pNode)
|
||||||
|
ui->MainViewport->ResetHover();
|
||||||
|
}
|
||||||
|
|
||||||
bool CWorldEditor::Save()
|
bool CWorldEditor::Save()
|
||||||
{
|
{
|
||||||
TString Out = mpArea->FullSource();
|
TString Out = mpArea->FullSource();
|
||||||
|
@ -273,9 +287,9 @@ void CWorldEditor::OnPropertyModified(IProperty *pProp)
|
||||||
{
|
{
|
||||||
bool EditorProperty = false;
|
bool EditorProperty = false;
|
||||||
|
|
||||||
if (!mSelection.isEmpty() && mSelection.front()->NodeType() == eScriptNode)
|
if (!mpSelection->IsEmpty() && mpSelection->Front()->NodeType() == eScriptNode)
|
||||||
{
|
{
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(mSelection.front());
|
CScriptNode *pScript = static_cast<CScriptNode*>(mpSelection->Front());
|
||||||
pScript->PropertyModified(pProp);
|
pScript->PropertyModified(pProp);
|
||||||
|
|
||||||
// Check editor property
|
// Check editor property
|
||||||
|
@ -295,13 +309,13 @@ void CWorldEditor::OnPropertyModified(IProperty *pProp)
|
||||||
CFileTemplate *pFile = static_cast<CFileTemplate*>(pProp->Template());
|
CFileTemplate *pFile = static_cast<CFileTemplate*>(pProp->Template());
|
||||||
|
|
||||||
if (pFile->AcceptsExtension("CMDL") || pFile->AcceptsExtension("ANCS") || pFile->AcceptsExtension("CHAR"))
|
if (pFile->AcceptsExtension("CMDL") || pFile->AcceptsExtension("ANCS") || pFile->AcceptsExtension("CHAR"))
|
||||||
NotifySelectionModified();
|
SelectionModified();
|
||||||
}
|
}
|
||||||
else if (pProp->Type() == eCharacterProperty)
|
else if (pProp->Type() == eCharacterProperty)
|
||||||
NotifySelectionModified();
|
SelectionModified();
|
||||||
|
|
||||||
// Emit signal so other widgets can react to the property change
|
// Emit signal so other widgets can react to the property change
|
||||||
emit PropertyModified(pProp, EditorProperty);
|
emit PropertyModified(pScript->Object(), pProp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,11 +324,11 @@ void CWorldEditor::SetSelectionActive(bool Active)
|
||||||
// Gather list of selected objects that actually have Active properties
|
// Gather list of selected objects that actually have Active properties
|
||||||
QVector<CScriptObject*> Objects;
|
QVector<CScriptObject*> Objects;
|
||||||
|
|
||||||
foreach (CSceneNode *pNode, mSelection)
|
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||||
{
|
{
|
||||||
if (pNode->NodeType() == eScriptNode)
|
if (It->NodeType() == eScriptNode)
|
||||||
{
|
{
|
||||||
CScriptNode *pScript = static_cast<CScriptNode*>(pNode);
|
CScriptNode *pScript = static_cast<CScriptNode*>(*It);
|
||||||
CScriptObject *pInst = pScript->Object();
|
CScriptObject *pInst = pScript->Object();
|
||||||
IProperty *pActive = pInst->ActiveProperty();
|
IProperty *pActive = pInst->ActiveProperty();
|
||||||
|
|
||||||
|
@ -343,9 +357,9 @@ void CWorldEditor::SetSelectionInstanceNames(const QString& rkNewName, bool IsDo
|
||||||
{
|
{
|
||||||
// todo: this only supports one node at a time because a macro prevents us from merging undo commands
|
// todo: this only supports one node at a time because a macro prevents us from merging undo commands
|
||||||
// this is fine right now because this function is only ever called with a selection of one node, but probably want to fix in the future
|
// this is fine right now because this function is only ever called with a selection of one node, but probably want to fix in the future
|
||||||
if (mSelection.size() == 1 && mSelection.front()->NodeType() == eScriptNode)
|
if (mpSelection->Size() == 1 && mpSelection->Front()->NodeType() == eScriptNode)
|
||||||
{
|
{
|
||||||
CScriptNode *pNode = static_cast<CScriptNode*>(mSelection.front());
|
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelection->Front());
|
||||||
CScriptObject *pInst = pNode->Object();
|
CScriptObject *pInst = pNode->Object();
|
||||||
IProperty *pName = pInst->InstanceNameProperty();
|
IProperty *pName = pInst->InstanceNameProperty();
|
||||||
|
|
||||||
|
@ -363,16 +377,23 @@ void CWorldEditor::SetSelectionLayer(CScriptLayer *pLayer)
|
||||||
{
|
{
|
||||||
QList<CScriptNode*> ScriptNodes;
|
QList<CScriptNode*> ScriptNodes;
|
||||||
|
|
||||||
foreach (CSceneNode *pNode, mSelection)
|
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||||
{
|
{
|
||||||
if (pNode->NodeType() == eScriptNode)
|
if (It->NodeType() == eScriptNode)
|
||||||
ScriptNodes << static_cast<CScriptNode*>(pNode);
|
ScriptNodes << static_cast<CScriptNode*>(*It);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ScriptNodes.isEmpty())
|
if (!ScriptNodes.isEmpty())
|
||||||
mUndoStack.push(new CChangeLayerCommand(this, ScriptNodes, pLayer));
|
mUndoStack.push(new CChangeLayerCommand(this, ScriptNodes, pLayer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWorldEditor::DeleteSelection()
|
||||||
|
{
|
||||||
|
// note: make it only happen if there is a script node selected
|
||||||
|
CDeleteSelectionCommand *pCmd = new CDeleteSelectionCommand(this);
|
||||||
|
mUndoStack.push(pCmd);
|
||||||
|
}
|
||||||
|
|
||||||
void CWorldEditor::UpdateStatusBar()
|
void CWorldEditor::UpdateStatusBar()
|
||||||
{
|
{
|
||||||
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
||||||
|
@ -384,7 +405,7 @@ void CWorldEditor::UpdateStatusBar()
|
||||||
{
|
{
|
||||||
CSceneNode *pHoverNode = ui->MainViewport->HoverNode();
|
CSceneNode *pHoverNode = ui->MainViewport->HoverNode();
|
||||||
|
|
||||||
if (pHoverNode && (pHoverNode->NodeType() & mSelectionNodeFlags))
|
if (pHoverNode && mpSelection->IsAllowedType(pHoverNode))
|
||||||
StatusText = TO_QSTRING(pHoverNode->Name());
|
StatusText = TO_QSTRING(pHoverNode->Name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,26 +430,26 @@ void CWorldEditor::UpdateGizmoUI()
|
||||||
case CGizmo::eTranslate:
|
case CGizmo::eTranslate:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalTranslation();
|
spinBoxValue = mGizmo.TotalTranslation();
|
||||||
else if (!mSelection.empty())
|
else if (!mpSelection->IsEmpty())
|
||||||
spinBoxValue = mSelection.front()->AbsolutePosition();
|
spinBoxValue = mpSelection->Front()->AbsolutePosition();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalRotation();
|
spinBoxValue = mGizmo.TotalRotation();
|
||||||
else if (!mSelection.empty())
|
else if (!mpSelection->IsEmpty())
|
||||||
spinBoxValue = mSelection.front()->AbsoluteRotation().ToEuler();
|
spinBoxValue = mpSelection->Front()->AbsoluteRotation().ToEuler();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||||
spinBoxValue = mGizmo.TotalScale();
|
spinBoxValue = mGizmo.TotalScale();
|
||||||
else if (!mSelection.empty())
|
else if (!mpSelection->IsEmpty())
|
||||||
spinBoxValue = mSelection.front()->AbsoluteScale();
|
spinBoxValue = mpSelection->Front()->AbsoluteScale();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!mSelection.empty()) spinBoxValue = mSelection.front()->AbsolutePosition();
|
else if (!mpSelection->IsEmpty()) spinBoxValue = mpSelection->Front()->AbsolutePosition();
|
||||||
|
|
||||||
ui->TransformSpinBox->blockSignals(true);
|
ui->TransformSpinBox->blockSignals(true);
|
||||||
ui->TransformSpinBox->SetValue(spinBoxValue);
|
ui->TransformSpinBox->SetValue(spinBoxValue);
|
||||||
|
@ -439,26 +460,23 @@ void CWorldEditor::UpdateGizmoUI()
|
||||||
if (!mGizmoTransforming)
|
if (!mGizmoTransforming)
|
||||||
{
|
{
|
||||||
// Set gizmo transform
|
// Set gizmo transform
|
||||||
if (!mSelection.empty())
|
if (!mpSelection->IsEmpty())
|
||||||
{
|
{
|
||||||
mGizmo.SetPosition(mSelection.front()->AbsolutePosition());
|
mGizmo.SetPosition(mpSelection->Front()->AbsolutePosition());
|
||||||
mGizmo.SetLocalRotation(mSelection.front()->AbsoluteRotation());
|
mGizmo.SetLocalRotation(mpSelection->Front()->AbsoluteRotation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWorldEditor::UpdateSelectionUI()
|
void CWorldEditor::UpdateSelectionUI()
|
||||||
{
|
{
|
||||||
// Update sidebar
|
|
||||||
ui->ModifyTabContents->GenerateUI(mSelection);
|
|
||||||
|
|
||||||
// Update selection info text
|
// Update selection info text
|
||||||
QString SelectionText;
|
QString SelectionText;
|
||||||
|
|
||||||
if (mSelection.size() == 1)
|
if (mpSelection->Size() == 1)
|
||||||
SelectionText = TO_QSTRING(mSelection.front()->Name());
|
SelectionText = TO_QSTRING(mpSelection->Front()->Name());
|
||||||
else if (mSelection.size() > 1)
|
else if (mpSelection->Size() > 1)
|
||||||
SelectionText = QString("%1 objects selected").arg(mSelection.size());
|
SelectionText = QString("%1 objects selected").arg(mpSelection->Size());
|
||||||
|
|
||||||
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
|
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
|
||||||
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
||||||
|
@ -478,7 +496,7 @@ void CWorldEditor::UpdateCursor()
|
||||||
|
|
||||||
if (ui->MainViewport->IsHoveringGizmo())
|
if (ui->MainViewport->IsHoveringGizmo())
|
||||||
ui->MainViewport->SetCursorState(Qt::SizeAllCursor);
|
ui->MainViewport->SetCursorState(Qt::SizeAllCursor);
|
||||||
else if ((pHoverNode) && (pHoverNode->NodeType() & mSelectionNodeFlags))
|
else if ((pHoverNode) && mpSelection->IsAllowedType(pHoverNode))
|
||||||
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
|
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
|
||||||
else
|
else
|
||||||
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
|
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
|
||||||
|
@ -604,10 +622,10 @@ void CWorldEditor::OnUnlinkClicked()
|
||||||
{
|
{
|
||||||
QList<CScriptNode*> SelectedScriptNodes;
|
QList<CScriptNode*> SelectedScriptNodes;
|
||||||
|
|
||||||
foreach (CSceneNode *pNode, mSelection)
|
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||||
{
|
{
|
||||||
if (pNode->NodeType() == eScriptNode)
|
if (It->NodeType() == eScriptNode)
|
||||||
SelectedScriptNodes << static_cast<CScriptNode*>(pNode);
|
SelectedScriptNodes << static_cast<CScriptNode*>(*It);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SelectedScriptNodes.isEmpty())
|
if (!SelectedScriptNodes.isEmpty())
|
||||||
|
@ -727,8 +745,8 @@ void CWorldEditor::UpdateCameraOrbit()
|
||||||
{
|
{
|
||||||
CCamera *pCamera = &ui->MainViewport->Camera();
|
CCamera *pCamera = &ui->MainViewport->Camera();
|
||||||
|
|
||||||
if (!mSelection.isEmpty())
|
if (!mpSelection->IsEmpty())
|
||||||
pCamera->SetOrbit(mSelectionBounds);
|
pCamera->SetOrbit(mpSelection->Bounds());
|
||||||
else if (mpArea)
|
else if (mpArea)
|
||||||
pCamera->SetOrbit(mpArea->AABox(), 1.5f);
|
pCamera->SetOrbit(mpArea->AABox(), 1.5f);
|
||||||
}
|
}
|
||||||
|
@ -745,34 +763,33 @@ void CWorldEditor::OnCameraSpeedChange(double speed)
|
||||||
|
|
||||||
void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
||||||
{
|
{
|
||||||
if (mSelection.empty()) return;
|
if (mpSelection->IsEmpty()) return;
|
||||||
|
|
||||||
switch (mGizmo.Mode())
|
switch (mGizmo.Mode())
|
||||||
{
|
{
|
||||||
// Use absolute position/rotation, but relative scale. (This way spinbox doesn't show preview multiplier)
|
// Use absolute position/rotation, but relative scale. (This way spinbox doesn't show preview multiplier)
|
||||||
case CGizmo::eTranslate:
|
case CGizmo::eTranslate:
|
||||||
{
|
{
|
||||||
CVector3f delta = value - mSelection.front()->AbsolutePosition();
|
CVector3f delta = value - mpSelection->Front()->AbsolutePosition();
|
||||||
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
mUndoStack.push(new CTranslateNodeCommand(this, mpSelection->SelectedNodeList(), delta, mTranslateSpace));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eRotate:
|
case CGizmo::eRotate:
|
||||||
{
|
{
|
||||||
CQuaternion delta = CQuaternion::FromEuler(value) * mSelection.front()->AbsoluteRotation().Inverse();
|
CQuaternion delta = CQuaternion::FromEuler(value) * mpSelection->Front()->AbsoluteRotation().Inverse();
|
||||||
mUndoStack.push(new CRotateNodeCommand(this, mSelection, CVector3f::skZero, delta, mRotateSpace));
|
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta, mRotateSpace));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CGizmo::eScale:
|
case CGizmo::eScale:
|
||||||
{
|
{
|
||||||
CVector3f delta = value / mSelection.front()->AbsoluteScale();
|
CVector3f delta = value / mpSelection->Front()->AbsoluteScale();
|
||||||
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecalculateSelectionBounds();
|
|
||||||
UpdateGizmoUI();
|
UpdateGizmoUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +799,7 @@ void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
|
||||||
ui->TransformSpinBox->blockSignals(true);
|
ui->TransformSpinBox->blockSignals(true);
|
||||||
ui->MainViewport->setFocus();
|
ui->MainViewport->setFocus();
|
||||||
ui->TransformSpinBox->blockSignals(false);
|
ui->TransformSpinBox->blockSignals(false);
|
||||||
if (mSelection.empty()) return;
|
if (mpSelection->IsEmpty()) return;
|
||||||
|
|
||||||
if (mGizmo.Mode() == CGizmo::eTranslate) mUndoStack.push(CTranslateNodeCommand::End());
|
if (mGizmo.Mode() == CGizmo::eTranslate) mUndoStack.push(CTranslateNodeCommand::End());
|
||||||
else if (mGizmo.Mode() == CGizmo::eRotate) mUndoStack.push(CRotateNodeCommand::End());
|
else if (mGizmo.Mode() == CGizmo::eRotate) mUndoStack.push(CRotateNodeCommand::End());
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "CPoiMapEditDialog.h"
|
#include "CPoiMapEditDialog.h"
|
||||||
#include "Editor/INodeEditor.h"
|
#include "Editor/INodeEditor.h"
|
||||||
#include "Editor/CGizmo.h"
|
#include "Editor/CGizmo.h"
|
||||||
|
#include "Editor/CSceneViewport.h"
|
||||||
|
|
||||||
#include <Common/CTimer.h>
|
#include <Common/CTimer.h>
|
||||||
#include <Common/EKeyInputs.h>
|
#include <Common/EKeyInputs.h>
|
||||||
|
@ -47,21 +48,24 @@ public:
|
||||||
explicit CWorldEditor(QWidget *parent = 0);
|
explicit CWorldEditor(QWidget *parent = 0);
|
||||||
~CWorldEditor();
|
~CWorldEditor();
|
||||||
void closeEvent(QCloseEvent *pEvent);
|
void closeEvent(QCloseEvent *pEvent);
|
||||||
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||||
void SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex);
|
|
||||||
bool CheckUnsavedChanges();
|
bool CheckUnsavedChanges();
|
||||||
|
|
||||||
inline CGameArea* ActiveArea() const { return mpArea; }
|
inline CGameArea* ActiveArea() const { return mpArea; }
|
||||||
inline EGame CurrentGame() const { return mpArea ? mpArea->Version() : eUnknownVersion; }
|
inline EGame CurrentGame() const { return mpArea ? mpArea->Version() : eUnknownVersion; }
|
||||||
inline CLinkDialog* LinkDialog() const { return mpLinkDialog; }
|
inline CLinkDialog* LinkDialog() const { return mpLinkDialog; }
|
||||||
|
CSceneViewport* Viewport() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
virtual void NotifyNodeAboutToBeDeleted(CSceneNode *pNode);
|
||||||
|
|
||||||
bool Save();
|
bool Save();
|
||||||
void OnLinksModified(const QList<CScriptObject*>& rkInstances);
|
void OnLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||||
void OnPropertyModified(IProperty *pProp);
|
void OnPropertyModified(IProperty *pProp);
|
||||||
void SetSelectionActive(bool Active);
|
void SetSelectionActive(bool Active);
|
||||||
void SetSelectionInstanceNames(const QString& rkNewName, bool IsDone);
|
void SetSelectionInstanceNames(const QString& rkNewName, bool IsDone);
|
||||||
void SetSelectionLayer(CScriptLayer *pLayer);
|
void SetSelectionLayer(CScriptLayer *pLayer);
|
||||||
|
void DeleteSelection();
|
||||||
|
|
||||||
void UpdateStatusBar();
|
void UpdateStatusBar();
|
||||||
void UpdateGizmoUI();
|
void UpdateGizmoUI();
|
||||||
|
@ -116,7 +120,7 @@ signals:
|
||||||
void InstancesLayerAboutToChange();
|
void InstancesLayerAboutToChange();
|
||||||
void InstancesLayerChanged(const QList<CScriptNode*>& rkInstanceList);
|
void InstancesLayerChanged(const QList<CScriptNode*>& rkInstanceList);
|
||||||
void InstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
void InstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||||
void PropertyModified(IProperty *pProp, bool IsEditorProperty);
|
void PropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CWORLDEDITOR_H
|
#endif // CWORLDEDITOR_H
|
||||||
|
|
|
@ -229,7 +229,7 @@
|
||||||
<enum>QTabWidget::Rounded</enum>
|
<enum>QTabWidget::Rounded</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
<size>
|
<size>
|
||||||
|
@ -268,17 +268,14 @@
|
||||||
<widget class="WEditorProperties" name="CreateTabEditorProperties" native="true"/>
|
<widget class="WEditorProperties" name="CreateTabEditorProperties" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<widget class="WCreateTab" name="CreateTabContents" native="true">
|
||||||
<property name="orientation">
|
<property name="sizePolicy">
|
||||||
<enum>Qt::Vertical</enum>
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
</widget>
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -755,6 +752,14 @@
|
||||||
<string>Edit POI to World Map</string>
|
<string>Edit POI to World Map</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="ActionDelete">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Del</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -792,6 +797,12 @@
|
||||||
<header>Editor/WorldEditor/WEditorProperties.h</header>
|
<header>Editor/WorldEditor/WEditorProperties.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>WCreateTab</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>Editor/WorldEditor/WCreateTab.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../Icons.qrc"/>
|
<include location="../Icons.qrc"/>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "WCreateTab.h"
|
#include "WCreateTab.h"
|
||||||
#include "ui_WCreateTab.h"
|
#include "ui_WCreateTab.h"
|
||||||
|
#include "CTemplateMimeData.h"
|
||||||
|
#include "CWorldEditor.h"
|
||||||
|
#include "Editor/Undo/UndoCommands.h"
|
||||||
|
|
||||||
WCreateTab::WCreateTab(QWidget *parent) :
|
WCreateTab::WCreateTab(QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
|
@ -12,3 +15,47 @@ WCreateTab::~WCreateTab()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WCreateTab::eventFilter(QObject *pObj, QEvent *pEvent)
|
||||||
|
{
|
||||||
|
if (pObj == mpEditor->Viewport())
|
||||||
|
{
|
||||||
|
if (pEvent->type() == QEvent::DragEnter)
|
||||||
|
{
|
||||||
|
QDragEnterEvent *pDragEvent = static_cast<QDragEnterEvent*>(pEvent);
|
||||||
|
|
||||||
|
if (qobject_cast<const CTemplateMimeData*>(pDragEvent->mimeData()))
|
||||||
|
{
|
||||||
|
pDragEvent->acceptProposedAction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (pEvent->type() == QEvent::Drop)
|
||||||
|
{
|
||||||
|
QDropEvent *pDropEvent = static_cast<QDropEvent*>(pEvent);
|
||||||
|
const CTemplateMimeData *pMimeData = qobject_cast<const CTemplateMimeData*>(pDropEvent->mimeData());
|
||||||
|
|
||||||
|
if (pMimeData)
|
||||||
|
{
|
||||||
|
CVector3f SpawnPoint = mpEditor->Viewport()->HoverPoint();
|
||||||
|
CCreateInstanceCommand *pCmd = new CCreateInstanceCommand(mpEditor, pMimeData->Template(), mpEditor->ActiveArea()->GetScriptLayer(0), SpawnPoint);
|
||||||
|
mpEditor->UndoStack()->push(pCmd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WCreateTab::SetEditor(CWorldEditor *pEditor)
|
||||||
|
{
|
||||||
|
mpEditor = pEditor;
|
||||||
|
pEditor->Viewport()->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WCreateTab::SetMaster(CMasterTemplate *pMaster)
|
||||||
|
{
|
||||||
|
ui->TemplateView->SetMaster(pMaster);
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef WCREATETAB_H
|
#ifndef WCREATETAB_H
|
||||||
#define WCREATETAB_H
|
#define WCREATETAB_H
|
||||||
|
|
||||||
|
#include "CWorldEditor.h"
|
||||||
|
#include <Core/Resource/Script/CMasterTemplate.h>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -10,11 +12,14 @@ class WCreateTab;
|
||||||
class WCreateTab : public QWidget
|
class WCreateTab : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
CWorldEditor *mpEditor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WCreateTab(QWidget *parent = 0);
|
explicit WCreateTab(QWidget *parent = 0);
|
||||||
~WCreateTab();
|
~WCreateTab();
|
||||||
|
bool eventFilter(QObject *, QEvent *);
|
||||||
|
void SetEditor(CWorldEditor *pEditor);
|
||||||
|
void SetMaster(CMasterTemplate *pMaster);
|
||||||
private:
|
private:
|
||||||
Ui::WCreateTab *ui;
|
Ui::WCreateTab *ui;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,14 +6,90 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>216</width>
|
<width>290</width>
|
||||||
<height>421</height>
|
<height>470</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Create Instance</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Spawn Layer:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="CTemplateListView" name="TemplateView">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="dragEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::MoveAction</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectItems</enum>
|
||||||
|
</property>
|
||||||
|
<property name="verticalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalScrollMode">
|
||||||
|
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CTemplateListView</class>
|
||||||
|
<extends>QListView</extends>
|
||||||
|
<header>Editor/WorldEditor/CTemplateListView.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -65,7 +65,7 @@ void WEditorProperties::SyncToEditor(CWorldEditor *pEditor)
|
||||||
connect(mpEditor, SIGNAL(SelectionModified()), this, SLOT(OnSelectionModified()));
|
connect(mpEditor, SIGNAL(SelectionModified()), this, SLOT(OnSelectionModified()));
|
||||||
connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersModified()));
|
connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersModified()));
|
||||||
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(OnInstancesLayerChanged(QList<CScriptNode*>)));
|
connect(mpEditor, SIGNAL(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(OnInstancesLayerChanged(QList<CScriptNode*>)));
|
||||||
connect(mpEditor, SIGNAL(PropertyModified(IProperty*,bool)), this, SLOT(OnPropertyModified(IProperty*,bool)));
|
connect(mpEditor, SIGNAL(PropertyModified(CScriptObject*,IProperty*)), this, SLOT(OnPropertyModified(CScriptObject*,IProperty*)));
|
||||||
|
|
||||||
OnLayersModified();
|
OnLayersModified();
|
||||||
}
|
}
|
||||||
|
@ -100,16 +100,16 @@ void WEditorProperties::SetLayerComboBox()
|
||||||
// ************ PUBLIC SLOTS ************
|
// ************ PUBLIC SLOTS ************
|
||||||
void WEditorProperties::OnSelectionModified()
|
void WEditorProperties::OnSelectionModified()
|
||||||
{
|
{
|
||||||
const QList<CSceneNode*>& rkSelection = mpEditor->GetSelection();
|
CNodeSelection *pSelection = mpEditor->Selection();
|
||||||
mpDisplayNode = (rkSelection.size() == 1 ? rkSelection.front() : nullptr);
|
mpDisplayNode = (pSelection->Size() == 1 ? pSelection->Front() : nullptr);
|
||||||
|
|
||||||
if (rkSelection.empty() || rkSelection.size() != 1 || mpDisplayNode->NodeType() != eScriptNode)
|
if (pSelection->IsEmpty() || pSelection->Size() != 1 || mpDisplayNode->NodeType() != eScriptNode)
|
||||||
{
|
{
|
||||||
mpActiveCheckBox->setChecked(false);
|
mpActiveCheckBox->setChecked(false);
|
||||||
mpActiveCheckBox->setEnabled(false);
|
mpActiveCheckBox->setEnabled(false);
|
||||||
mpInstanceNameLineEdit->setEnabled(false);
|
mpInstanceNameLineEdit->setEnabled(false);
|
||||||
|
|
||||||
if (rkSelection.empty())
|
if (pSelection->IsEmpty())
|
||||||
{
|
{
|
||||||
mpInstanceInfoLabel->setText("<i>[No selection]</i>");
|
mpInstanceInfoLabel->setText("<i>[No selection]</i>");
|
||||||
mpInstanceNameLineEdit->clear();
|
mpInstanceNameLineEdit->clear();
|
||||||
|
@ -121,7 +121,7 @@ void WEditorProperties::OnSelectionModified()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mpInstanceInfoLabel->setText(QString("<i>[%1 objects selected]</i>").arg(rkSelection.size()));
|
mpInstanceInfoLabel->setText(QString("<i>[%1 objects selected]</i>").arg(pSelection->Size()));
|
||||||
mpInstanceNameLineEdit->clear();
|
mpInstanceNameLineEdit->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,11 +139,11 @@ void WEditorProperties::OnSelectionModified()
|
||||||
SetLayerComboBox();
|
SetLayerComboBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WEditorProperties::OnPropertyModified(IProperty* /*pProp*/, bool IsEditorProperty)
|
void WEditorProperties::OnPropertyModified(CScriptObject *pInstance, IProperty *pProp)
|
||||||
{
|
{
|
||||||
if (!mpInstanceNameLineEdit->hasFocus())
|
if (!mpInstanceNameLineEdit->hasFocus())
|
||||||
{
|
{
|
||||||
if (mpDisplayNode->NodeType() == eScriptNode && IsEditorProperty)
|
if (mpDisplayNode->NodeType() == eScriptNode && pInstance->IsEditorProperty(pProp))
|
||||||
UpdatePropertyValues();
|
UpdatePropertyValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnSelectionModified();
|
void OnSelectionModified();
|
||||||
void OnPropertyModified(IProperty *pProp, bool IsEditorProperty);
|
void OnPropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||||
void OnInstancesLayerChanged(const QList<CScriptNode*>& rkNodeList);
|
void OnInstancesLayerChanged(const QList<CScriptNode*>& rkNodeList);
|
||||||
void OnLayersModified();
|
void OnLayersModified();
|
||||||
void UpdatePropertyValues();
|
void UpdatePropertyValues();
|
||||||
|
|
|
@ -64,18 +64,28 @@ void WModifyTab::SetEditor(CWorldEditor *pEditor)
|
||||||
ui->PropertyView->SetEditor(mpWorldEditor);
|
ui->PropertyView->SetEditor(mpWorldEditor);
|
||||||
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
|
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
|
||||||
connect(mpWorldEditor, SIGNAL(InstanceLinksModified(const QList<CScriptObject*>&)), this, SLOT(OnInstanceLinksModified(const QList<CScriptObject*>&)));
|
connect(mpWorldEditor, SIGNAL(InstanceLinksModified(const QList<CScriptObject*>&)), this, SLOT(OnInstanceLinksModified(const QList<CScriptObject*>&)));
|
||||||
|
connect(mpWorldEditor->Selection(), SIGNAL(Modified()), this, SLOT(GenerateUI()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
void WModifyTab::ClearUI()
|
||||||
|
{
|
||||||
|
ui->ObjectsTabWidget->hide();
|
||||||
|
ui->PropertyView->SetInstance(nullptr);
|
||||||
|
ui->LightGroupBox->hide();
|
||||||
|
mpSelectedNode = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************ PUBLIC SLOTS ************
|
||||||
|
void WModifyTab::GenerateUI()
|
||||||
{
|
{
|
||||||
if (mIsPicking)
|
if (mIsPicking)
|
||||||
mpWorldEditor->ExitPickMode();
|
mpWorldEditor->ExitPickMode();
|
||||||
|
|
||||||
if (Selection.size() == 1)
|
if (mpWorldEditor->Selection()->Size() == 1)
|
||||||
{
|
{
|
||||||
if (mpSelectedNode != Selection.front())
|
if (mpSelectedNode != mpWorldEditor->Selection()->Front())
|
||||||
{
|
{
|
||||||
mpSelectedNode = Selection.front();
|
mpSelectedNode = mpWorldEditor->Selection()->Front();
|
||||||
|
|
||||||
// todo: set up editing UI for Light Nodes
|
// todo: set up editing UI for Light Nodes
|
||||||
if (mpSelectedNode->NodeType() == eScriptNode)
|
if (mpSelectedNode->NodeType() == eScriptNode)
|
||||||
|
@ -100,15 +110,6 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
||||||
ClearUI();
|
ClearUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WModifyTab::ClearUI()
|
|
||||||
{
|
|
||||||
ui->ObjectsTabWidget->hide();
|
|
||||||
ui->PropertyView->SetInstance(nullptr);
|
|
||||||
ui->LightGroupBox->hide();
|
|
||||||
mpSelectedNode = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ PUBLIC SLOTS ************
|
|
||||||
void WModifyTab::OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances)
|
void WModifyTab::OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances)
|
||||||
{
|
{
|
||||||
if (mpSelectedNode && mpSelectedNode->NodeType() == eScriptNode)
|
if (mpSelectedNode && mpSelectedNode->NodeType() == eScriptNode)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "CLinkDialog.h"
|
#include "CLinkDialog.h"
|
||||||
#include "CLinkModel.h"
|
#include "CLinkModel.h"
|
||||||
|
#include "Editor/CNodeSelection.h"
|
||||||
#include <Core/Scene/CSceneNode.h>
|
#include <Core/Scene/CSceneNode.h>
|
||||||
#include <Core/Scene/CScriptNode.h>
|
#include <Core/Scene/CScriptNode.h>
|
||||||
|
|
||||||
|
@ -36,10 +37,10 @@ public:
|
||||||
explicit WModifyTab(QWidget *pParent = 0);
|
explicit WModifyTab(QWidget *pParent = 0);
|
||||||
~WModifyTab();
|
~WModifyTab();
|
||||||
void SetEditor(CWorldEditor *pEditor);
|
void SetEditor(CWorldEditor *pEditor);
|
||||||
void GenerateUI(QList<CSceneNode*>& Selection);
|
|
||||||
void ClearUI();
|
void ClearUI();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void GenerateUI();
|
||||||
void OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
void OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||||
void OnWorldSelectionTransformed();
|
void OnWorldSelectionTransformed();
|
||||||
|
|
||||||
|
|
|
@ -20,22 +20,22 @@ CQuaternion::CQuaternion(float _w, float _x, float _y, float _z)
|
||||||
z = _z;
|
z = _z;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CQuaternion::XAxis()
|
CVector3f CQuaternion::XAxis() const
|
||||||
{
|
{
|
||||||
return (*this * CVector3f::skUnitX);
|
return (*this * CVector3f::skUnitX);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CQuaternion::YAxis()
|
CVector3f CQuaternion::YAxis() const
|
||||||
{
|
{
|
||||||
return (*this * CVector3f::skUnitY);
|
return (*this * CVector3f::skUnitY);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CQuaternion::ZAxis()
|
CVector3f CQuaternion::ZAxis() const
|
||||||
{
|
{
|
||||||
return (*this * CVector3f::skUnitZ);
|
return (*this * CVector3f::skUnitZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
CQuaternion CQuaternion::Inverse()
|
CQuaternion CQuaternion::Inverse() const
|
||||||
{
|
{
|
||||||
float fNorm = (w * w) + (x * x) + (y * y) + (z * z);
|
float fNorm = (w * w) + (x * x) + (y * y) + (z * z);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ CQuaternion CQuaternion::Inverse()
|
||||||
return CQuaternion::skZero;
|
return CQuaternion::skZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
CVector3f CQuaternion::ToEuler()
|
CVector3f CQuaternion::ToEuler() const
|
||||||
{
|
{
|
||||||
// There is more than one way to do this conversion, based on rotation order.
|
// There is more than one way to do this conversion, based on rotation order.
|
||||||
// But since we only care about the rotation order used in Retro games, which is consistent,
|
// But since we only care about the rotation order used in Retro games, which is consistent,
|
||||||
|
|
|
@ -11,11 +11,11 @@ public:
|
||||||
CQuaternion();
|
CQuaternion();
|
||||||
CQuaternion(float _w, float _x, float _y, float _z);
|
CQuaternion(float _w, float _x, float _y, float _z);
|
||||||
|
|
||||||
CVector3f XAxis();
|
CVector3f XAxis() const;
|
||||||
CVector3f YAxis();
|
CVector3f YAxis() const;
|
||||||
CVector3f ZAxis();
|
CVector3f ZAxis() const;
|
||||||
CQuaternion Inverse();
|
CQuaternion Inverse() const;
|
||||||
CVector3f ToEuler();
|
CVector3f ToEuler() const;
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
CVector3f operator*(const CVector3f& vec) const;
|
CVector3f operator*(const CVector3f& vec) const;
|
||||||
|
|
Loading…
Reference in New Issue