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);
|
||||
fflush(gpLogFile);
|
||||
}
|
||||
|
||||
std::cout << rkMessage << "\n";
|
||||
}
|
||||
|
||||
void Error(const TString& rkMessage)
|
||||
|
@ -65,7 +67,6 @@ void Error(const TString& rkMessage)
|
|||
TString FullMessage = "ERROR: " + rkMessage;
|
||||
Write(FullMessage);
|
||||
gErrorLog.push_back(FullMessage);
|
||||
std::cout << FullMessage << "\n";
|
||||
}
|
||||
|
||||
void Warning(const TString& rkMessage)
|
||||
|
@ -73,7 +74,6 @@ void Warning(const TString& rkMessage)
|
|||
TString FullMessage = "Warning: " + rkMessage;
|
||||
Write(FullMessage);
|
||||
gErrorLog.push_back(FullMessage);
|
||||
std::cout << FullMessage << "\n";
|
||||
}
|
||||
|
||||
void FileWrite(const TString& rkFilename, const TString& rkMessage)
|
||||
|
|
|
@ -15,6 +15,8 @@ public:
|
|||
bool IsLayerEnabled() const;
|
||||
bool IsSkyEnabled() const;
|
||||
CModel* SkyModel() const;
|
||||
|
||||
inline CScriptObject* Instance() const { return mpObj; }
|
||||
};
|
||||
|
||||
#endif // CAREAATTRIBUTES_H
|
||||
|
|
|
@ -2,23 +2,25 @@
|
|||
#include "Core/Resource/Script/CScriptLayer.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()
|
||||
{
|
||||
ClearTerrain();
|
||||
|
||||
delete mCollision;
|
||||
delete mpCollision;
|
||||
delete mpGeneratorLayer;
|
||||
|
||||
for (u32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||
|
@ -108,85 +110,109 @@ void CGameArea::ClearScriptLayers()
|
|||
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()
|
||||
{
|
||||
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)
|
||||
CScriptObject* CGameArea::InstanceByID(u32 InstanceID)
|
||||
{
|
||||
auto it = mObjectMap.find(InstanceID);
|
||||
if (it != mObjectMap.end()) return it->second;
|
||||
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;
|
||||
}
|
||||
|
||||
u32 CGameArea::GetLightCount(u32 layer)
|
||||
// Check whether the suggested instance ID is valid
|
||||
u32 InstanceID = SuggestedID;
|
||||
|
||||
if (InstanceID != -1)
|
||||
{
|
||||
if (mLightLayers.empty()) return 0;
|
||||
return mLightLayers[layer].size();
|
||||
if (mObjectMap.find(InstanceID) == mObjectMap.end())
|
||||
InstanceID = -1;
|
||||
}
|
||||
|
||||
CLight* CGameArea::GetLight(u32 layer, u32 light)
|
||||
// If not valid (or if there's no suggested ID) then determine a new instance ID
|
||||
if (InstanceID == -1)
|
||||
{
|
||||
return mLightLayers[layer][light];
|
||||
// Determine layer index
|
||||
u32 LayerIndex = -1;
|
||||
|
||||
for (u32 iLyr = 0; iLyr < mScriptLayers.size(); iLyr++)
|
||||
{
|
||||
if (mScriptLayers[iLyr] == pLayer)
|
||||
{
|
||||
LayerIndex = iLyr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CPoiToWorld* CGameArea::GetPoiToWorldMap()
|
||||
if (LayerIndex == -1)
|
||||
{
|
||||
return mpPoiToWorldMap;
|
||||
Log::Error("Unable to spawn a new script instance; invalid script layer passed in");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CAABox CGameArea::AABox()
|
||||
// Look for a valid instance ID
|
||||
InstanceID = (LayerIndex << 26) | (mWorldIndex << 16) | 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
return mAABox;
|
||||
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;
|
||||
}
|
||||
|
||||
void CGameArea::DeleteInstance(CScriptObject *pInstance)
|
||||
{
|
||||
pInstance->Layer()->RemoveInstance(pInstance);
|
||||
pInstance->Template()->RemoveObject(pInstance);
|
||||
|
||||
auto it = mObjectMap.find(pInstance->InstanceID());
|
||||
if (it != mObjectMap.end()) mObjectMap.erase(it);
|
||||
|
||||
if (mpPoiToWorldMap && mpPoiToWorldMap->HasPoiMappings(pInstance->InstanceID()))
|
||||
mpPoiToWorldMap->RemovePoi(pInstance->InstanceID());
|
||||
|
||||
pInstance->BreakAllLinks();
|
||||
delete pInstance;
|
||||
}
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/Model/CStaticModel.h"
|
||||
#include <Common/types.h>
|
||||
#include <Math/CQuaternion.h>
|
||||
#include <Math/CTransform4f.h>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
class CScriptLayer;
|
||||
class CScriptObject;
|
||||
class CScriptTemplate;
|
||||
|
||||
class CGameArea : public CResource
|
||||
{
|
||||
|
@ -23,6 +25,7 @@ class CGameArea : public CResource
|
|||
friend class CAreaCooker;
|
||||
|
||||
EGame mVersion;
|
||||
u32 mWorldIndex;
|
||||
u32 mVertexCount;
|
||||
u32 mTriangleCount;
|
||||
bool mTerrainMerged;
|
||||
|
@ -50,7 +53,7 @@ class CGameArea : public CResource
|
|||
CScriptLayer *mpGeneratorLayer;
|
||||
std::unordered_map<u32, CScriptObject*> mObjectMap;
|
||||
// Collision
|
||||
CCollisionMeshGroup *mCollision;
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
// Lights
|
||||
std::vector<std::vector<CLight*>> mLightLayers;
|
||||
// Object to Static Geometry Map
|
||||
|
@ -64,24 +67,34 @@ public:
|
|||
void MergeTerrain();
|
||||
void ClearTerrain();
|
||||
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
|
||||
EGame Version();
|
||||
CTransform4f GetTransform();
|
||||
u32 GetTerrainModelCount();
|
||||
u32 GetStaticModelCount();
|
||||
CModel* GetTerrainModel(u32 mdl);
|
||||
CStaticModel* GetStaticModel(u32 mdl);
|
||||
CCollisionMeshGroup* GetCollision();
|
||||
u32 GetScriptLayerCount();
|
||||
CScriptLayer* GetScriptLayer(u32 index);
|
||||
CScriptLayer* GetGeneratorLayer();
|
||||
CScriptObject* GetInstanceByID(u32 InstanceID);
|
||||
u32 GetLightLayerCount();
|
||||
u32 GetLightCount(u32 layer);
|
||||
CLight* GetLight(u32 layer, u32 light);
|
||||
CPoiToWorld* GetPoiToWorldMap();
|
||||
CAABox AABox();
|
||||
// Inline Accessors
|
||||
inline EGame Version() const { return mVersion; }
|
||||
inline u32 WorldIndex() const { return mWorldIndex; }
|
||||
inline CTransform4f GetTransform() const { return mTransform; }
|
||||
inline u32 GetTerrainModelCount() const { return mTerrainModels.size(); }
|
||||
inline u32 GetStaticModelCount() const { return mStaticTerrainModels.size(); }
|
||||
inline CModel* GetTerrainModel(u32 iMdl) const { return mTerrainModels[iMdl]; }
|
||||
inline CStaticModel* GetStaticModel(u32 iMdl) const { return mStaticTerrainModels[iMdl]; }
|
||||
inline CCollisionMeshGroup* GetCollision() const { return mpCollision; }
|
||||
inline u32 GetScriptLayerCount() const { return mScriptLayers.size(); }
|
||||
inline CScriptLayer* GetScriptLayer(u32 Index) const { return mScriptLayers[Index]; }
|
||||
inline CScriptLayer* GetGeneratorLayer() const { return mpGeneratorLayer; }
|
||||
inline u32 GetLightLayerCount() const { return mLightLayers.size(); }
|
||||
inline u32 GetLightCount(u32 LayerIndex) const { return (LayerIndex < mLightLayers.size() ? mLightLayers[LayerIndex].size() : 0); }
|
||||
inline CLight* GetLight(u32 LayerIndex, u32 LightIndex) const { return mLightLayers[LayerIndex][LightIndex]; }
|
||||
inline CPoiToWorld* GetPoiToWorldMap() const { return mpPoiToWorldMap; }
|
||||
inline CAABox AABox() const { return mAABox; }
|
||||
|
||||
inline void SetWorldIndex(u32 NewWorldIndex) { mWorldIndex = NewWorldIndex; }
|
||||
};
|
||||
|
||||
#endif // CGAMEAREA_H
|
||||
|
|
|
@ -39,6 +39,22 @@ public:
|
|||
{
|
||||
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
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
|
||||
inline CUniqueID ID() const
|
||||
{
|
||||
TString FileName = mPath.GetFileName();
|
||||
TString FileName = mPath.GetFileName(false);
|
||||
|
||||
if (!mIsPath)
|
||||
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.
|
||||
// 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.
|
||||
SArea& AreaInfo = mAreas[AreaIndex];
|
||||
SArea& AreaInfo = mAreas[pArea->WorldIndex()];
|
||||
|
||||
for (u32 iLyr = 0; iLyr < pArea->GetScriptLayerCount(); iLyr++)
|
||||
{
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
CWorld();
|
||||
~CWorld();
|
||||
|
||||
void SetAreaLayerInfo(CGameArea *pArea, u32 AreaIndex);
|
||||
void SetAreaLayerInfo(CGameArea *pArea);
|
||||
|
||||
// Setters
|
||||
EGame Version();
|
||||
|
|
|
@ -595,7 +595,7 @@ void CAreaLoader::ReadCollision()
|
|||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading collision (MP1/MP2/MP3)");
|
||||
mpSectionMgr->ToSection(mCollisionBlockNum);
|
||||
mpArea->mCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||
mpArea->mpCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadEGMC()
|
||||
|
@ -643,7 +643,7 @@ void CAreaLoader::SetUpObjects()
|
|||
|
||||
if (iConMap != mConnectionMap.end())
|
||||
{
|
||||
CScriptObject *pObj = mpArea->GetInstanceByID(InstanceID);
|
||||
CScriptObject *pObj = mpArea->InstanceByID(InstanceID);
|
||||
pObj->mInLinks = iConMap->second;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,8 +214,8 @@ CScriptObject* CScriptLoader::LoadObjectMP1(IInputStream& SCLY)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
mpObj = new CScriptObject(mpArea, mpLayer, pTemp);
|
||||
mpObj->mInstanceID = SCLY.ReadLong();
|
||||
u32 InstanceID = SCLY.ReadLong();
|
||||
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemp);
|
||||
|
||||
// Load connections
|
||||
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
|
||||
u32 NumObjects = SCLY.ReadLong();
|
||||
|
||||
mpLayer = new CScriptLayer();
|
||||
mpLayer = new CScriptLayer(mpArea);
|
||||
mpLayer->Reserve(NumObjects);
|
||||
|
||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||
|
@ -327,8 +327,8 @@ CScriptObject* CScriptLoader::LoadObjectMP2(IInputStream& SCLY)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
mpObj = new CScriptObject(mpArea, mpLayer, pTemplate);
|
||||
mpObj->mInstanceID = SCLY.ReadLong();
|
||||
u32 InstanceID = SCLY.ReadLong();
|
||||
mpObj = new CScriptObject(InstanceID, mpArea, mpLayer, pTemplate);
|
||||
|
||||
// Load connections
|
||||
u32 NumConnections = SCLY.ReadShort();
|
||||
|
@ -359,7 +359,7 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& SCLY)
|
|||
SCLY.Seek(0x1, SEEK_CUR); // Skipping version. todo: verify this?
|
||||
u32 NumObjects = SCLY.ReadLong();
|
||||
|
||||
mpLayer = new CScriptLayer();
|
||||
mpLayer = new CScriptLayer(mpArea);
|
||||
mpLayer->Reserve(NumObjects);
|
||||
|
||||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||
|
@ -372,9 +372,10 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(IInputStream& SCLY)
|
|||
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;
|
||||
Loader.mVersion = Version;
|
||||
|
@ -391,7 +392,7 @@ CScriptLayer* CScriptLoader::LoadLayer(IInputStream &SCLY, CGameArea *pArea, EGa
|
|||
CTemplateLoader::LoadGameTemplates(Version);
|
||||
|
||||
if (Version <= ePrime)
|
||||
return Loader.LoadLayerMP1(SCLY);
|
||||
return Loader.LoadLayerMP1(rSCLY);
|
||||
else
|
||||
return Loader.LoadLayerMP2(SCLY);
|
||||
return Loader.LoadLayerMP2(rSCLY);
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ public:
|
|||
void SetSender(u32 NewSenderID, u32 Index = -1)
|
||||
{
|
||||
u32 OldSenderID = mSenderID;
|
||||
CScriptObject *pOldSender = mpArea->GetInstanceByID(OldSenderID);
|
||||
CScriptObject *pNewSender = mpArea->GetInstanceByID(NewSenderID);
|
||||
CScriptObject *pOldSender = mpArea->InstanceByID(OldSenderID);
|
||||
CScriptObject *pNewSender = mpArea->InstanceByID(NewSenderID);
|
||||
|
||||
mSenderID = NewSenderID;
|
||||
pOldSender->RemoveLink(eOutgoing, this);
|
||||
|
@ -63,8 +63,8 @@ public:
|
|||
void SetReceiver(u32 NewReceiverID, u32 Index = -1)
|
||||
{
|
||||
u32 OldReceiverID = mSenderID;
|
||||
CScriptObject *pOldReceiver = mpArea->GetInstanceByID(OldReceiverID);
|
||||
CScriptObject *pNewReceiver = mpArea->GetInstanceByID(NewReceiverID);
|
||||
CScriptObject *pOldReceiver = mpArea->InstanceByID(OldReceiverID);
|
||||
CScriptObject *pNewReceiver = mpArea->InstanceByID(NewReceiverID);
|
||||
|
||||
mReceiverID = NewReceiverID;
|
||||
pOldReceiver->RemoveLink(eIncoming, this);
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
|
||||
u32 SenderIndex() const
|
||||
{
|
||||
CScriptObject *pSender = mpArea->GetInstanceByID(mSenderID);
|
||||
CScriptObject *pSender = mpArea->InstanceByID(mSenderID);
|
||||
|
||||
for (u32 iLink = 0; iLink < pSender->NumLinks(eOutgoing); iLink++)
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
u32 ReceiverIndex() const
|
||||
{
|
||||
CScriptObject *pReceiver = mpArea->GetInstanceByID(mReceiverID);
|
||||
CScriptObject *pReceiver = mpArea->InstanceByID(mReceiverID);
|
||||
|
||||
for (u32 iLink = 0; iLink < pReceiver->NumLinks(eIncoming); iLink++)
|
||||
{
|
||||
|
@ -117,8 +117,8 @@ public:
|
|||
u32 Message() const { return mMessageID; }
|
||||
u32 SenderID() const { return mSenderID; }
|
||||
u32 ReceiverID() const { return mReceiverID; }
|
||||
CScriptObject* Sender() const { return mpArea->GetInstanceByID(mSenderID); }
|
||||
CScriptObject* Receiver() const { return mpArea->GetInstanceByID(mReceiverID); }
|
||||
CScriptObject* Sender() const { return mpArea->InstanceByID(mSenderID); }
|
||||
CScriptObject* Receiver() const { return mpArea->InstanceByID(mReceiverID); }
|
||||
|
||||
void SetState(u32 StateID) { mStateID = StateID; }
|
||||
void SetMessage(u32 MessageID) { mMessageID = MessageID; }
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
|
||||
class CScriptLayer
|
||||
{
|
||||
CGameArea *mpArea;
|
||||
TString mLayerName;
|
||||
bool mActive;
|
||||
bool mVisible;
|
||||
std::vector<CScriptObject*> mInstances;
|
||||
public:
|
||||
CScriptLayer()
|
||||
: mLayerName("New Layer")
|
||||
CScriptLayer(CGameArea *pArea)
|
||||
: mpArea(pArea)
|
||||
, mLayerName("New Layer")
|
||||
, mActive(true)
|
||||
, mVisible(true)
|
||||
{
|
||||
|
@ -27,8 +29,16 @@ public:
|
|||
}
|
||||
|
||||
// Data Manipulation
|
||||
void AddInstance(CScriptObject *pObject)
|
||||
void AddInstance(CScriptObject *pObject, u32 Index = -1)
|
||||
{
|
||||
if (Index != -1 && Index < mInstances.size())
|
||||
{
|
||||
auto it = mInstances.begin();
|
||||
std::advance(it, Index);
|
||||
mInstances.insert(it, pObject);
|
||||
}
|
||||
|
||||
else
|
||||
mInstances.push_back(pObject);
|
||||
}
|
||||
|
||||
|
@ -67,6 +77,7 @@ public:
|
|||
}
|
||||
|
||||
// Accessors
|
||||
inline CGameArea* Area() const { return mpArea; }
|
||||
inline TString Name() const { return mLayerName; }
|
||||
inline bool IsActive() const { return mActive; }
|
||||
inline bool IsVisible() const { return mVisible; }
|
||||
|
@ -88,6 +99,17 @@ public:
|
|||
inline void SetActive(bool Active) { mActive = Active; }
|
||||
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
|
||||
CScriptObject* operator[](u32 Index) { return InstanceByIndex(Index); }
|
||||
};
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#include "CMasterTemplate.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)
|
||||
, mpArea(pArea)
|
||||
, mpLayer(pLayer)
|
||||
, mVersion(0)
|
||||
, mInstanceID(InstanceID)
|
||||
, mpDisplayModel(nullptr)
|
||||
, mpCollision(nullptr)
|
||||
, 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)
|
||||
{
|
||||
mpLayer->RemoveInstance(this);
|
||||
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
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
if (mpInstanceName)
|
||||
|
|
|
@ -50,7 +50,7 @@ class CScriptObject
|
|||
mutable bool mIsCheckingNearVisibleActivation;
|
||||
|
||||
public:
|
||||
CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
|
||||
CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
|
||||
~CScriptObject();
|
||||
|
||||
void EvaluateProperties();
|
||||
|
@ -59,7 +59,8 @@ public:
|
|||
void EvaluateCollisionModel();
|
||||
void EvaluateVolume();
|
||||
bool IsEditorProperty(IProperty *pProp);
|
||||
void SetLayer(CScriptLayer *pLayer);
|
||||
void SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex = -1);
|
||||
u32 LayerIndex() const;
|
||||
bool HasNearVisibleActivation() const;
|
||||
|
||||
CScriptTemplate* Template() const;
|
||||
|
@ -78,6 +79,7 @@ public:
|
|||
CLink* Link(ELinkType Type, u32 Index) const;
|
||||
void AddLink(ELinkType Type, CLink *pLink, u32 Index = -1);
|
||||
void RemoveLink(ELinkType Type, CLink *pLink);
|
||||
void BreakAllLinks();
|
||||
|
||||
CVector3f Position() const;
|
||||
CVector3f Rotation() const;
|
||||
|
|
|
@ -65,6 +65,18 @@ CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
|
|||
|
||||
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
|
||||
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++;
|
||||
return pNode;
|
||||
}
|
||||
|
@ -79,6 +91,48 @@ CLightNode* CScene::CreateLightNode(CLight *pLight)
|
|||
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)
|
||||
{
|
||||
// Clear existing area
|
||||
|
@ -121,20 +175,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
|||
for (u32 iObj = 0; iObj < NumObjects; iObj++)
|
||||
{
|
||||
CScriptObject *pObj = pLayer->InstanceByIndex(iObj);
|
||||
CScriptNode *pNode = 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;
|
||||
}
|
||||
CreateScriptNode(pObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,10 +185,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
|
|||
for (u32 iObj = 0; iObj < pGenLayer->NumInstances(); iObj++)
|
||||
{
|
||||
CScriptObject *pObj = pGenLayer->InstanceByIndex(iObj);
|
||||
CScriptNode *pNode = CreateScriptNode(pObj);
|
||||
|
||||
// Add to map
|
||||
mScriptNodeMap[pObj->InstanceID()] = pNode;
|
||||
CreateScriptNode(pObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,16 +255,10 @@ void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
|
|||
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (ViewInfo.GameMode || It->IsVisible())
|
||||
It->AddToRenderer(pRenderer, ViewInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,16 +268,10 @@ SRayIntersection CScene::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo
|
|||
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);
|
||||
CRayCollisionTester Tester(Ray);
|
||||
|
||||
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
|
||||
for (CSceneIterator It(this, NodeFlags, false); It; ++It)
|
||||
{
|
||||
if (NodeFlags & it->first)
|
||||
{
|
||||
std::vector<CSceneNode*>& rNodeVec = it->second;
|
||||
|
||||
for (u32 iNode = 0; iNode < rNodeVec.size(); iNode++)
|
||||
if (rNodeVec[iNode]->IsVisible())
|
||||
rNodeVec[iNode]->RayAABoxIntersectTest(Tester, ViewInfo);
|
||||
}
|
||||
if (It->IsVisible())
|
||||
It->RayAABoxIntersectTest(Tester, ViewInfo);
|
||||
}
|
||||
|
||||
return Tester.TestNodes(ViewInfo);
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
|
||||
CScriptNode* CreateScriptNode(CScriptObject *pObj);
|
||||
CLightNode* CreateLightNode(CLight *pLight);
|
||||
void DeleteNode(CSceneNode *pNode);
|
||||
void SetActiveArea(CGameArea *pArea);
|
||||
void SetActiveWorld(CWorld *pWorld);
|
||||
void PostLoad();
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
inline operator bool() const
|
||||
{
|
||||
return DoneIterating();
|
||||
return !DoneIterating();
|
||||
}
|
||||
|
||||
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
|
||||
#define CNODESELECTION_H
|
||||
|
||||
#include <Core/Scene/CSceneIterator.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;
|
||||
std::vector<CSceneNode*> mSelectedNodes;
|
||||
Q_OBJECT
|
||||
|
||||
FNodeFlags mAllowedNodes;
|
||||
QList<CSceneNode*> mSelectedNodes;
|
||||
|
||||
mutable CAABox mCachedBounds;
|
||||
mutable bool mBoundsDirty;
|
||||
|
||||
public:
|
||||
CSceneSelection(CScene *pScene);
|
||||
void SelectNode(CSceneNode *pNode);
|
||||
void DeselectNode(CSceneNode *pNode);
|
||||
u32 SelectionSize();
|
||||
CSceneNode* NodeByIndex(u32 Index);
|
||||
void ClearSelection();
|
||||
CNodeSelection()
|
||||
: mAllowedNodes(eAllNodeTypes)
|
||||
, mBoundsDirty(true) {}
|
||||
|
||||
// Operators
|
||||
CSceneNode* operator[](u32 Index);
|
||||
~CNodeSelection()
|
||||
{
|
||||
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
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "CSceneViewport.h"
|
||||
#include "CSelectionIterator.h"
|
||||
#include "UICommon.h"
|
||||
#include "Editor/Undo/UndoCommands.h"
|
||||
#include <Core/Render/CDrawUtil.h>
|
||||
|
@ -386,10 +387,8 @@ void CSceneViewport::OnToggleSelect()
|
|||
|
||||
void CSceneViewport::OnHideSelection()
|
||||
{
|
||||
const QList<CSceneNode*>& rkSelection = mpEditor->GetSelection();
|
||||
|
||||
foreach (CSceneNode *pNode, rkSelection)
|
||||
pNode->SetVisible(false);
|
||||
for (CSelectionIterator It(mpEditor->Selection()); It; ++It)
|
||||
It->SetVisible(false);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
mpWorld->SetAreaLayerInfo(pArea, mSelectedAreaIndex);
|
||||
mpWorldEditor->SetArea(mpWorld, pArea, mSelectedAreaIndex);
|
||||
pArea->SetWorldIndex(mSelectedAreaIndex);
|
||||
mpWorld->SetAreaLayerInfo(pArea);
|
||||
mpWorldEditor->SetArea(mpWorld, pArea);
|
||||
gResCache.Clean();
|
||||
|
||||
mpWorldEditor->setWindowModality(Qt::WindowModal);
|
||||
|
|
|
@ -149,17 +149,19 @@ HEADERS += \
|
|||
Undo/CAddLinkCommand.h \
|
||||
Undo/CDeleteLinksCommand.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
|
||||
SOURCES += \
|
||||
ModelEditor/CModelEditorViewport.cpp \
|
||||
ModelEditor/CModelEditorWindow.cpp \
|
||||
Undo/CClearSelectionCommand.cpp \
|
||||
Undo/CDeselectNodeCommand.cpp \
|
||||
Undo/CRotateNodeCommand.cpp \
|
||||
Undo/CScaleNodeCommand.cpp \
|
||||
Undo/CSelectNodeCommand.cpp \
|
||||
Undo/CTranslateNodeCommand.cpp \
|
||||
Widgets/IPreviewPanel.cpp \
|
||||
Widgets/WAnimParamsEditor.cpp \
|
||||
|
@ -185,7 +187,6 @@ SOURCES += \
|
|||
CBasicViewport.cpp \
|
||||
CDarkStyle.cpp \
|
||||
CGizmo.cpp \
|
||||
CNodeSelection.cpp \
|
||||
CSceneViewport.cpp \
|
||||
CStartWindow.cpp \
|
||||
INodeEditor.cpp \
|
||||
|
@ -193,8 +194,6 @@ SOURCES += \
|
|||
TestDialog.cpp \
|
||||
UICommon.cpp \
|
||||
CErrorLogDialog.cpp \
|
||||
Undo/CSelectAllCommand.cpp \
|
||||
Undo/CInvertSelectionCommand.cpp \
|
||||
WorldEditor/CPoiMapEditDialog.cpp \
|
||||
WorldEditor/CPoiMapModel.cpp \
|
||||
PropertyEdit/CPropertyModel.cpp \
|
||||
|
@ -211,7 +210,9 @@ SOURCES += \
|
|||
WorldEditor/CSelectInstanceDialog.cpp \
|
||||
Undo/CAddLinkCommand.cpp \
|
||||
Undo/CDeleteLinksCommand.cpp \
|
||||
Undo/CEditLinkCommand.cpp
|
||||
Undo/CEditLinkCommand.cpp \
|
||||
Undo/CDeleteSelectionCommand.cpp \
|
||||
Undo/CCreateInstanceCommand.cpp
|
||||
|
||||
# UI Files
|
||||
FORMS += \
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#include "INodeEditor.h"
|
||||
#include "CSelectionIterator.h"
|
||||
#include "Editor/Undo/UndoCommands.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
INodeEditor::INodeEditor(QWidget *pParent)
|
||||
: QMainWindow(pParent)
|
||||
, mPickMode(false)
|
||||
, mSelectionNodeFlags(eAllNodeTypes)
|
||||
, mpSelection(new CNodeSelection)
|
||||
, mSelectionLocked(false)
|
||||
, mShowGizmo(false)
|
||||
, mGizmoHovering(false)
|
||||
|
@ -53,10 +54,12 @@ INodeEditor::INodeEditor(QWidget *pParent)
|
|||
connect(mGizmoActions[2], SIGNAL(triggered()), this, SLOT(OnRotateTriggered()));
|
||||
connect(mGizmoActions[3], SIGNAL(triggered()), this, SLOT(OnScaleTriggered()));
|
||||
connect(mpTransformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTransformSpaceChanged(int)));
|
||||
connect(mpSelection, SIGNAL(Modified()), this, SLOT(OnSelectionModified()));
|
||||
}
|
||||
|
||||
INodeEditor::~INodeEditor()
|
||||
{
|
||||
delete mpSelection;
|
||||
}
|
||||
|
||||
QUndoStack* INodeEditor::UndoStack()
|
||||
|
@ -76,7 +79,7 @@ CGizmo* INodeEditor::Gizmo()
|
|||
|
||||
bool INodeEditor::IsGizmoVisible()
|
||||
{
|
||||
return (mShowGizmo && !mSelection.empty());
|
||||
return (mShowGizmo && !mpSelection->IsEmpty());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!mSelectionLocked)
|
||||
{
|
||||
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 (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 (!mSelection.empty())
|
||||
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
||||
if (!mpSelection->IsEmpty())
|
||||
mUndoStack.push(new CClearSelectionCommand(mpSelection));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,17 +147,17 @@ void INodeEditor::ClearAndSelectNode(CSceneNode *pNode)
|
|||
{
|
||||
if (!mSelectionLocked)
|
||||
{
|
||||
if (mSelection.empty())
|
||||
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
||||
if (mpSelection->IsEmpty())
|
||||
mUndoStack.push(new CSelectNodeCommand(mpSelection, pNode));
|
||||
|
||||
else if ((mSelection.size() == 1) && (mSelection.front() == pNode))
|
||||
else if ((mpSelection->Size() == 1) && (mpSelection->Front() == pNode))
|
||||
return;
|
||||
|
||||
else
|
||||
{
|
||||
mUndoStack.beginMacro("Select");
|
||||
mUndoStack.push(new CClearSelectionCommand(this, mSelection));
|
||||
mUndoStack.push(new CSelectNodeCommand(this, pNode, mSelection));
|
||||
mUndoStack.push(new CClearSelectionCommand(mpSelection));
|
||||
mUndoStack.push(new CSelectNodeCommand(mpSelection, pNode));
|
||||
mUndoStack.endMacro();
|
||||
}
|
||||
}
|
||||
|
@ -184,13 +166,13 @@ void INodeEditor::ClearAndSelectNode(CSceneNode *pNode)
|
|||
void INodeEditor::SelectAll(FNodeFlags NodeFlags)
|
||||
{
|
||||
if (!mSelectionLocked)
|
||||
mUndoStack.push(new CSelectAllCommand(this, mSelection, &mScene, NodeFlags));
|
||||
mUndoStack.push(new CSelectAllCommand(mpSelection, &mScene, NodeFlags));
|
||||
}
|
||||
|
||||
void INodeEditor::InvertSelection(FNodeFlags NodeFlags)
|
||||
{
|
||||
if (!mSelectionLocked)
|
||||
mUndoStack.push(new CInvertSelectionCommand(this, mSelection, &mScene, NodeFlags));
|
||||
mUndoStack.push(new CInvertSelectionCommand(mpSelection, &mScene, NodeFlags));
|
||||
}
|
||||
|
||||
void INodeEditor::SetSelectionLocked(bool Locked)
|
||||
|
@ -200,12 +182,12 @@ void INodeEditor::SetSelectionLocked(bool Locked)
|
|||
|
||||
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*/)
|
||||
|
@ -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();
|
||||
emit SelectionModified();
|
||||
}
|
||||
|
||||
void INodeEditor::NotifySelectionTransformed()
|
||||
{
|
||||
foreach (CSceneNode *pNode, mSelection)
|
||||
pNode->OnTransformed();
|
||||
|
||||
emit SelectionTransformed();
|
||||
}
|
||||
|
||||
// ************ PUBLIC SLOTS ************
|
||||
void INodeEditor::OnGizmoMoved()
|
||||
{
|
||||
switch (mGizmo.Mode())
|
||||
|
@ -254,26 +256,25 @@ void INodeEditor::OnGizmoMoved()
|
|||
case CGizmo::eTranslate:
|
||||
{
|
||||
CVector3f delta = mGizmo.DeltaTranslation();
|
||||
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
||||
mUndoStack.push(new CTranslateNodeCommand(this, mpSelection->SelectedNodeList(), delta, mTranslateSpace));
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eRotate:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
case CGizmo::eScale:
|
||||
{
|
||||
CVector3f delta = mGizmo.DeltaScale();
|
||||
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
||||
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RecalculateSelectionBounds();
|
||||
UpdateGizmoUI();
|
||||
}
|
||||
|
||||
|
@ -285,7 +286,7 @@ void INodeEditor::OnViewportClick(const SRayIntersection& rkRayIntersect, QMouse
|
|||
// Not in pick mode: process node selection/deselection
|
||||
if (!mPickMode)
|
||||
{
|
||||
bool ValidNode = (pNode && (pNode->NodeType() & mSelectionNodeFlags));
|
||||
bool ValidNode = (pNode && mpSelection->IsAllowedType(pNode));
|
||||
bool AltPressed = ((pEvent->modifiers() & Qt::AltModifier) != 0);
|
||||
bool CtrlPressed = ((pEvent->modifiers() & Qt::ControlModifier) != 0);
|
||||
|
||||
|
@ -364,11 +365,11 @@ void INodeEditor::UpdateTransformActionsEnabled()
|
|||
bool AllowTranslate = true, AllowRotate = true, AllowScale = true;
|
||||
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)->AllowsRotate()) AllowRotate = false;
|
||||
if (!(*it)->AllowsScale()) AllowScale = false;
|
||||
if (!It->AllowsTranslate()) AllowTranslate = false;
|
||||
if (!It->AllowsRotate()) AllowRotate = false;
|
||||
if (!It->AllowsScale()) AllowScale = false;
|
||||
}
|
||||
|
||||
mGizmoActions[1]->setEnabled(AllowTranslate);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define INODEEDITOR_H
|
||||
|
||||
#include "CGizmo.h"
|
||||
#include "CNodeSelection.h"
|
||||
#include <Math/ETransformSpace.h>
|
||||
#include <Core/Scene/CScene.h>
|
||||
|
||||
|
@ -23,9 +24,7 @@ protected:
|
|||
|
||||
// Node management
|
||||
CScene mScene;
|
||||
QList<CSceneNode*> mSelection;
|
||||
FNodeFlags mSelectionNodeFlags;
|
||||
CAABox mSelectionBounds;
|
||||
CNodeSelection *mpSelection;
|
||||
bool mSelectionLocked;
|
||||
|
||||
// Gizmo
|
||||
|
@ -62,8 +61,6 @@ public:
|
|||
void EndGizmoTransform();
|
||||
ETransformSpace CurrentTransformSpace();
|
||||
|
||||
void RecalculateSelectionBounds();
|
||||
void ExpandSelectionBounds(CSceneNode *pNode);
|
||||
void SelectNode(CSceneNode *pNode);
|
||||
void DeselectNode(CSceneNode *pNode);
|
||||
void ClearSelection();
|
||||
|
@ -72,15 +69,22 @@ public:
|
|||
void InvertSelection(FNodeFlags NodeFlags);
|
||||
void SetSelectionLocked(bool Locked);
|
||||
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 ExitPickMode();
|
||||
|
||||
void NotifySelectionModified();
|
||||
void NotifySelectionTransformed();
|
||||
virtual void NotifyNodeAboutToBeSpawned();
|
||||
virtual void NotifyNodeSpawned(CSceneNode *pNode);
|
||||
virtual void NotifyNodeAboutToBeDeleted(CSceneNode *pNode);
|
||||
virtual void NotifyNodeDeleted();
|
||||
|
||||
signals:
|
||||
void NodeAboutToBeSpawned();
|
||||
void NodeSpawned(CSceneNode *pNode);
|
||||
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
||||
void NodeDeleted();
|
||||
void SelectionModified();
|
||||
void SelectionTransformed();
|
||||
|
||||
|
@ -90,6 +94,7 @@ signals:
|
|||
void PickModeHoverChanged(const SRayIntersection& rkRayIntersect, QMouseEvent *pEvent);
|
||||
|
||||
public slots:
|
||||
void OnSelectionModified();
|
||||
void OnGizmoMoved();
|
||||
virtual void UpdateGizmoUI() = 0;
|
||||
virtual void UpdateSelectionUI() = 0;
|
||||
|
|
|
@ -499,7 +499,7 @@ Qt::ItemFlags CPropertyModel::flags(const QModelIndex& rkIndex) const
|
|||
else return (Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
void CPropertyModel::NotifyPropertyModified(IProperty *pProp)
|
||||
void CPropertyModel::NotifyPropertyModified(class CScriptObject*, IProperty *pProp)
|
||||
{
|
||||
NotifyPropertyModified(IndexForProperty(pProp));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
inline void SetBoldModifiedProperties(bool Enable) { mBoldModifiedProperties = Enable; }
|
||||
|
||||
public slots:
|
||||
void NotifyPropertyModified(IProperty *pProp);
|
||||
void NotifyPropertyModified(class CScriptObject *pInst, IProperty *pProp);
|
||||
void NotifyPropertyModified(const QModelIndex& rkIndex);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -75,7 +75,7 @@ void CPropertyView::SetEditor(CWorldEditor *pEditor)
|
|||
{
|
||||
mpEditor = 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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
QList<CSceneNode*> mSelectionState;
|
||||
QList<CSceneNode*> *mpSelection;
|
||||
QList<CSceneNode*> mOldSelection;
|
||||
CNodeSelection *mpSelection;
|
||||
|
||||
public:
|
||||
CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection);
|
||||
~CClearSelectionCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
CClearSelectionCommand(CNodeSelection *pSelection)
|
||||
: IUndoCommand("Clear Selection"),
|
||||
mOldSelection(pSelection->SelectedNodeList()),
|
||||
mpSelection(pSelection)
|
||||
{}
|
||||
|
||||
void undo() { mpSelection->SetSelectedNodes(mOldSelection); }
|
||||
void redo() { mpSelection->Clear(); }
|
||||
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
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
CSceneNode *mpNode;
|
||||
QList<CSceneNode*> *mpSelection;
|
||||
CNodeSelection *mpSelection;
|
||||
public:
|
||||
CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||
void undo();
|
||||
void redo();
|
||||
CDeselectNodeCommand(CNodeSelection *pSelection, CSceneNode *pNode)
|
||||
: IUndoCommand("Deselect")
|
||||
, mpNode(pNode)
|
||||
, mpSelection(pSelection)
|
||||
{}
|
||||
|
||||
void undo() { mpSelection->SelectNode(mpNode); }
|
||||
void redo() { mpSelection->DeselectNode(mpNode); }
|
||||
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
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
CNodeSelection *mpSelection;
|
||||
QList<CSceneNode*> mOldSelection;
|
||||
QList<CSceneNode*> mNewSelection;
|
||||
QList<CSceneNode*> *mpSelection;
|
||||
|
||||
public:
|
||||
CInvertSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags);
|
||||
~CInvertSelectionCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
virtual bool AffectsCleanState() const { return false; }
|
||||
CInvertSelectionCommand(CNodeSelection *pSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||
: IUndoCommand("Invert Selection")
|
||||
, mpSelection(pSelection)
|
||||
{
|
||||
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
|
||||
|
|
|
@ -79,7 +79,6 @@ void CRotateNodeCommand::undo()
|
|||
rotate.pNode->SetRotation(rotate.initialRot);
|
||||
}
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
mpEditor->UpdateGizmoUI();
|
||||
}
|
||||
|
@ -94,7 +93,6 @@ void CRotateNodeCommand::redo()
|
|||
rotate.pNode->SetRotation(rotate.newRot);
|
||||
}
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
mpEditor->UpdateGizmoUI();
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ void CScaleNodeCommand::undo()
|
|||
scale.pNode->SetScale(scale.initialScale);
|
||||
}
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
mpEditor->UpdateGizmoUI();
|
||||
}
|
||||
|
@ -94,7 +93,6 @@ void CScaleNodeCommand::redo()
|
|||
scale.pNode->SetScale(scale.newScale);
|
||||
}
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
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
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
QList<CSceneNode*> mOldSelection;
|
||||
QList<CSceneNode*> mNewSelection;
|
||||
QList<CSceneNode*> *mpSelection;
|
||||
CNodeSelection *mpSelection;
|
||||
|
||||
public:
|
||||
CSelectAllCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags);
|
||||
~CSelectAllCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
CSelectAllCommand(CNodeSelection *pSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||
: IUndoCommand("Select All")
|
||||
, mOldSelection(pSelection->SelectedNodeList())
|
||||
, 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; }
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
CSceneNode *mpNode;
|
||||
QList<CSceneNode*> *mpSelection;
|
||||
CNodeSelection *mpSelection;
|
||||
|
||||
public:
|
||||
CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||
void undo();
|
||||
void redo();
|
||||
CSelectNodeCommand(CNodeSelection *pSelection, CSceneNode *pNode)
|
||||
: IUndoCommand("Select")
|
||||
, mpNode(pNode)
|
||||
, mpSelection(pSelection)
|
||||
{}
|
||||
|
||||
void undo() { mpSelection->DeselectNode(mpNode); }
|
||||
void redo() { mpSelection->SelectNode(mpNode); }
|
||||
bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ void CTranslateNodeCommand::undo()
|
|||
foreach (SNodeTranslate translate, mNodeList)
|
||||
translate.pNode->SetPosition(translate.initialPos);
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
mpEditor->UpdateGizmoUI();
|
||||
}
|
||||
|
@ -83,7 +82,6 @@ void CTranslateNodeCommand::redo()
|
|||
foreach (SNodeTranslate translate, mNodeList)
|
||||
translate.pNode->SetPosition(translate.newPos);
|
||||
|
||||
mpEditor->RecalculateSelectionBounds();
|
||||
mpEditor->NotifySelectionTransformed();
|
||||
mpEditor->UpdateGizmoUI();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef UNDOCOMMANDS
|
||||
#define UNDOCOMMANDS
|
||||
|
||||
#include "CCreateInstanceCommand.h"
|
||||
|
||||
#include "CTranslateNodeCommand.h"
|
||||
#include "CRotateNodeCommand.h"
|
||||
#include "CScaleNodeCommand.h"
|
||||
|
@ -10,6 +12,7 @@
|
|||
#include "CClearSelectionCommand.h"
|
||||
#include "CSelectAllCommand.h"
|
||||
#include "CInvertSelectionCommand.h"
|
||||
#include "CDeleteSelectionCommand.h"
|
||||
|
||||
#include "CEditScriptPropertyCommand.h"
|
||||
#include "CResizeScriptArrayCommand.h"
|
||||
|
|
|
@ -26,11 +26,6 @@
|
|||
#define TYPES_NODE_TYPE_SHIFT 1
|
||||
#define TYPES_ITEM_TYPE_SHIFT 0
|
||||
|
||||
bool SortTemplatesAlphabetical(CScriptTemplate *pA, CScriptTemplate *pB)
|
||||
{
|
||||
return (pA->Name() < pB->Name());
|
||||
}
|
||||
|
||||
CInstancesModel::CInstancesModel(QObject *pParent) : QAbstractItemModel(pParent)
|
||||
{
|
||||
mpEditor = nullptr;
|
||||
|
@ -40,6 +35,7 @@ CInstancesModel::CInstancesModel(QObject *pParent) : QAbstractItemModel(pParent)
|
|||
mModelType = eLayers;
|
||||
mShowColumnEnabled = true;
|
||||
mBaseItems << "Script";
|
||||
mAddingOrRemovingRows = false;
|
||||
}
|
||||
|
||||
CInstancesModel::~CInstancesModel()
|
||||
|
@ -319,6 +315,11 @@ void CInstancesModel::SetEditor(CWorldEditor *pEditor)
|
|||
|
||||
mpEditor = pEditor;
|
||||
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(InstancesLayerChanged(QList<CScriptNode*>)), this, SLOT(InstancesLayerPostChange(QList<CScriptNode*>)));
|
||||
}
|
||||
|
@ -347,52 +348,6 @@ void CInstancesModel::SetShowColumnEnabled(bool Enabled)
|
|||
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
|
||||
{
|
||||
if ((mModelType != eLayers) || (IndexNodeType(index) != eScriptType) || (IndexType(index) != eObjectTypeIndex))
|
||||
|
@ -420,6 +375,107 @@ CScriptObject* CInstancesModel::IndexObject(const QModelIndex& index) const
|
|||
}
|
||||
|
||||
// ************ 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()
|
||||
{
|
||||
// This is only really needed on layers, which have rows moved.
|
||||
|
@ -501,7 +557,9 @@ void CInstancesModel::GenerateList()
|
|||
mTemplateList << pTemp;
|
||||
}
|
||||
|
||||
qSort(mTemplateList.begin(), mTemplateList.end(), SortTemplatesAlphabetical);
|
||||
qSort(mTemplateList.begin(), mTemplateList.end(), [](CScriptTemplate *pLeft, CScriptTemplate *pRight) -> bool {
|
||||
return (pLeft->Name() < pRight->Name());
|
||||
});
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
|
|
@ -37,6 +37,7 @@ private:
|
|||
QList<CScriptTemplate*> mTemplateList;
|
||||
QStringList mBaseItems;
|
||||
bool mShowColumnEnabled;
|
||||
bool mAddingOrRemovingRows;
|
||||
|
||||
public:
|
||||
explicit CInstancesModel(QObject *pParent = 0);
|
||||
|
@ -53,13 +54,17 @@ public:
|
|||
void SetArea(CGameArea *pArea);
|
||||
void SetModelType(EInstanceModelType type);
|
||||
void SetShowColumnEnabled(bool Enabled);
|
||||
void NodeCreated(CSceneNode *pNode);
|
||||
void NodeDeleted(CSceneNode *pNode);
|
||||
CScriptLayer* IndexLayer(const QModelIndex& index) const;
|
||||
CScriptTemplate* IndexTemplate(const QModelIndex& index) const;
|
||||
CScriptObject* IndexObject(const QModelIndex& index) const;
|
||||
|
||||
public slots:
|
||||
void NodeAboutToBeCreated();
|
||||
void NodeCreated(CSceneNode *pNode);
|
||||
void NodeAboutToBeDeleted(CSceneNode *pNode);
|
||||
void NodeDeleted();
|
||||
|
||||
void PropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||
void InstancesLayerPreChange();
|
||||
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
|
||||
{
|
||||
u32 TargetID = (mType == eIncoming ? pLink->SenderID() : pLink->ReceiverID());
|
||||
CScriptObject *pTarget = mpObject->Area()->GetInstanceByID(TargetID);
|
||||
CScriptObject *pTarget = mpObject->Area()->InstanceByID(TargetID);
|
||||
|
||||
if (pTarget) {
|
||||
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()))
|
||||
{
|
||||
const CPoiToWorld::SPoiMap *pkMap = mpPoiToWorld->MapByIndex(rkIndex.row());
|
||||
CScriptObject *pPOI = mpArea->GetInstanceByID(pkMap->PoiID);
|
||||
CScriptObject *pPOI = mpArea->InstanceByID(pkMap->PoiID);
|
||||
|
||||
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 "ui_CWorldEditor.h"
|
||||
|
||||
#include "CConfirmUnlinkDialog.h"
|
||||
#include "CLayerEditor.h"
|
||||
#include "CTemplateMimeData.h"
|
||||
#include "WModifyTab.h"
|
||||
#include "WInstancesTab.h"
|
||||
|
||||
#include "Editor/CBasicViewport.h"
|
||||
#include "Editor/CSelectionIterator.h"
|
||||
#include "Editor/UICommon.h"
|
||||
#include "Editor/PropertyEdit/CPropertyView.h"
|
||||
#include "Editor/Widgets/WDraggableSpinBox.h"
|
||||
#include "Editor/Widgets/WVectorEditor.h"
|
||||
#include "Editor/Undo/UndoCommands.h"
|
||||
#include "Editor/UICommon.h"
|
||||
|
||||
#include <Core/Render/CDrawUtil.h>
|
||||
#include <Core/Resource/Cooker/CAreaCooker.h>
|
||||
|
@ -38,7 +39,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
Log::Write("Creating World Editor");
|
||||
ui->setupUi(this);
|
||||
|
||||
mSelectionNodeFlags = eScriptNode | eLightNode;
|
||||
mpSelection->SetAllowedNodeTypes(eScriptNode | eLightNode);
|
||||
|
||||
// Start refresh timer
|
||||
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
||||
|
@ -51,6 +52,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
|
||||
// Initialize UI stuff
|
||||
ui->MainViewport->SetScene(this, &mScene);
|
||||
ui->CreateTabContents->SetEditor(this);
|
||||
ui->ModifyTabContents->SetEditor(this);
|
||||
ui->InstancesTabContents->SetEditor(this, &mScene);
|
||||
ui->TransformSpinBox->SetOrientation(Qt::Horizontal);
|
||||
|
@ -66,6 +68,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
// Initialize actions
|
||||
addAction(ui->ActionIncrementGizmo);
|
||||
addAction(ui->ActionDecrementGizmo);
|
||||
addAction(ui->ActionDelete);
|
||||
|
||||
QAction *pToolBarUndo = mUndoStack.createUndoAction(this);
|
||||
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->ActionLink, SIGNAL(toggled(bool)), this, SLOT(OnLinkButtonToggled(bool)));
|
||||
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(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save()));
|
||||
|
@ -100,6 +104,7 @@ CWorldEditor::CWorldEditor(QWidget *parent)
|
|||
ui->CreateTabEditorProperties->SyncToEditor(this);
|
||||
ui->ModifyTabEditorProperties->SyncToEditor(this);
|
||||
ui->InstancesTabEditorProperties->SyncToEditor(this);
|
||||
ui->MainViewport->setAcceptDrops(true);
|
||||
}
|
||||
|
||||
CWorldEditor::~CWorldEditor()
|
||||
|
@ -127,12 +132,7 @@ void CWorldEditor::closeEvent(QCloseEvent *pEvent)
|
|||
}
|
||||
}
|
||||
|
||||
bool CWorldEditor::eventFilter(QObject * /*pObj*/, QEvent * /*pEvent*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||
{
|
||||
ExitPickMode();
|
||||
ui->MainViewport->ResetHover();
|
||||
|
@ -181,6 +181,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
|||
|
||||
// Set up sidebar tabs
|
||||
CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(mpArea->Version());
|
||||
ui->CreateTabContents->SetMaster(pMaster);
|
||||
ui->InstancesTabContents->SetMaster(pMaster);
|
||||
|
||||
// Set up dialogs
|
||||
|
@ -192,8 +193,8 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
|||
|
||||
if (CurrentGame() < eReturns)
|
||||
{
|
||||
CStringTable *pAreaNameTable = mpWorld->GetAreaName(AreaIndex);
|
||||
TWideString AreaName = pAreaNameTable ? pAreaNameTable->GetString("ENGL", 0) : (TWideString("!") + mpWorld->GetAreaInternalName(AreaIndex).ToUTF16());
|
||||
CStringTable *pAreaNameTable = mpWorld->GetAreaName(mpArea->WorldIndex());
|
||||
TWideString AreaName = pAreaNameTable ? pAreaNameTable->GetString("ENGL", 0) : (TWideString("!") + mpWorld->GetAreaInternalName(mpArea->WorldIndex()).ToUTF16());
|
||||
|
||||
if (AreaName.IsEmpty())
|
||||
AreaName = "[Untitled Area]";
|
||||
|
@ -206,7 +207,7 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
|||
{
|
||||
QString LevelName;
|
||||
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));
|
||||
Log::Write("Loaded level: World " + mpWorld->Source() + " / Area " + mpArea->Source() + " (" + TO_TSTRING(LevelName) + ")");
|
||||
|
@ -238,7 +239,20 @@ bool CWorldEditor::CheckUnsavedChanges()
|
|||
return OkToClear;
|
||||
}
|
||||
|
||||
CSceneViewport* CWorldEditor::Viewport() const
|
||||
{
|
||||
return ui->MainViewport;
|
||||
}
|
||||
|
||||
// ************ PUBLIC SLOTS ************
|
||||
void CWorldEditor::NotifyNodeAboutToBeDeleted(CSceneNode *pNode)
|
||||
{
|
||||
INodeEditor::NotifyNodeAboutToBeDeleted(pNode);
|
||||
|
||||
if (ui->MainViewport->HoverNode() == pNode)
|
||||
ui->MainViewport->ResetHover();
|
||||
}
|
||||
|
||||
bool CWorldEditor::Save()
|
||||
{
|
||||
TString Out = mpArea->FullSource();
|
||||
|
@ -273,9 +287,9 @@ void CWorldEditor::OnPropertyModified(IProperty *pProp)
|
|||
{
|
||||
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);
|
||||
|
||||
// Check editor property
|
||||
|
@ -295,13 +309,13 @@ void CWorldEditor::OnPropertyModified(IProperty *pProp)
|
|||
CFileTemplate *pFile = static_cast<CFileTemplate*>(pProp->Template());
|
||||
|
||||
if (pFile->AcceptsExtension("CMDL") || pFile->AcceptsExtension("ANCS") || pFile->AcceptsExtension("CHAR"))
|
||||
NotifySelectionModified();
|
||||
SelectionModified();
|
||||
}
|
||||
else if (pProp->Type() == eCharacterProperty)
|
||||
NotifySelectionModified();
|
||||
SelectionModified();
|
||||
|
||||
// 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
|
||||
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();
|
||||
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
|
||||
// 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();
|
||||
IProperty *pName = pInst->InstanceNameProperty();
|
||||
|
||||
|
@ -363,16 +377,23 @@ void CWorldEditor::SetSelectionLayer(CScriptLayer *pLayer)
|
|||
{
|
||||
QList<CScriptNode*> ScriptNodes;
|
||||
|
||||
foreach (CSceneNode *pNode, mSelection)
|
||||
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||
{
|
||||
if (pNode->NodeType() == eScriptNode)
|
||||
ScriptNodes << static_cast<CScriptNode*>(pNode);
|
||||
if (It->NodeType() == eScriptNode)
|
||||
ScriptNodes << static_cast<CScriptNode*>(*It);
|
||||
}
|
||||
|
||||
if (!ScriptNodes.isEmpty())
|
||||
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()
|
||||
{
|
||||
// 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();
|
||||
|
||||
if (pHoverNode && (pHoverNode->NodeType() & mSelectionNodeFlags))
|
||||
if (pHoverNode && mpSelection->IsAllowedType(pHoverNode))
|
||||
StatusText = TO_QSTRING(pHoverNode->Name());
|
||||
}
|
||||
}
|
||||
|
@ -409,26 +430,26 @@ void CWorldEditor::UpdateGizmoUI()
|
|||
case CGizmo::eTranslate:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalTranslation();
|
||||
else if (!mSelection.empty())
|
||||
spinBoxValue = mSelection.front()->AbsolutePosition();
|
||||
else if (!mpSelection->IsEmpty())
|
||||
spinBoxValue = mpSelection->Front()->AbsolutePosition();
|
||||
break;
|
||||
|
||||
case CGizmo::eRotate:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalRotation();
|
||||
else if (!mSelection.empty())
|
||||
spinBoxValue = mSelection.front()->AbsoluteRotation().ToEuler();
|
||||
else if (!mpSelection->IsEmpty())
|
||||
spinBoxValue = mpSelection->Front()->AbsoluteRotation().ToEuler();
|
||||
break;
|
||||
|
||||
case CGizmo::eScale:
|
||||
if (mGizmoTransforming && mGizmo.HasTransformed())
|
||||
spinBoxValue = mGizmo.TotalScale();
|
||||
else if (!mSelection.empty())
|
||||
spinBoxValue = mSelection.front()->AbsoluteScale();
|
||||
else if (!mpSelection->IsEmpty())
|
||||
spinBoxValue = mpSelection->Front()->AbsoluteScale();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!mSelection.empty()) spinBoxValue = mSelection.front()->AbsolutePosition();
|
||||
else if (!mpSelection->IsEmpty()) spinBoxValue = mpSelection->Front()->AbsolutePosition();
|
||||
|
||||
ui->TransformSpinBox->blockSignals(true);
|
||||
ui->TransformSpinBox->SetValue(spinBoxValue);
|
||||
|
@ -439,26 +460,23 @@ void CWorldEditor::UpdateGizmoUI()
|
|||
if (!mGizmoTransforming)
|
||||
{
|
||||
// Set gizmo transform
|
||||
if (!mSelection.empty())
|
||||
if (!mpSelection->IsEmpty())
|
||||
{
|
||||
mGizmo.SetPosition(mSelection.front()->AbsolutePosition());
|
||||
mGizmo.SetLocalRotation(mSelection.front()->AbsoluteRotation());
|
||||
mGizmo.SetPosition(mpSelection->Front()->AbsolutePosition());
|
||||
mGizmo.SetLocalRotation(mpSelection->Front()->AbsoluteRotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::UpdateSelectionUI()
|
||||
{
|
||||
// Update sidebar
|
||||
ui->ModifyTabContents->GenerateUI(mSelection);
|
||||
|
||||
// Update selection info text
|
||||
QString SelectionText;
|
||||
|
||||
if (mSelection.size() == 1)
|
||||
SelectionText = TO_QSTRING(mSelection.front()->Name());
|
||||
else if (mSelection.size() > 1)
|
||||
SelectionText = QString("%1 objects selected").arg(mSelection.size());
|
||||
if (mpSelection->Size() == 1)
|
||||
SelectionText = TO_QSTRING(mpSelection->Front()->Name());
|
||||
else if (mpSelection->Size() > 1)
|
||||
SelectionText = QString("%1 objects selected").arg(mpSelection->Size());
|
||||
|
||||
QFontMetrics Metrics(ui->SelectionInfoLabel->font());
|
||||
SelectionText = Metrics.elidedText(SelectionText, Qt::ElideRight, ui->SelectionInfoFrame->width() - 10);
|
||||
|
@ -478,7 +496,7 @@ void CWorldEditor::UpdateCursor()
|
|||
|
||||
if (ui->MainViewport->IsHoveringGizmo())
|
||||
ui->MainViewport->SetCursorState(Qt::SizeAllCursor);
|
||||
else if ((pHoverNode) && (pHoverNode->NodeType() & mSelectionNodeFlags))
|
||||
else if ((pHoverNode) && mpSelection->IsAllowedType(pHoverNode))
|
||||
ui->MainViewport->SetCursorState(Qt::PointingHandCursor);
|
||||
else
|
||||
ui->MainViewport->SetCursorState(Qt::ArrowCursor);
|
||||
|
@ -604,10 +622,10 @@ void CWorldEditor::OnUnlinkClicked()
|
|||
{
|
||||
QList<CScriptNode*> SelectedScriptNodes;
|
||||
|
||||
foreach (CSceneNode *pNode, mSelection)
|
||||
for (CSelectionIterator It(mpSelection); It; ++It)
|
||||
{
|
||||
if (pNode->NodeType() == eScriptNode)
|
||||
SelectedScriptNodes << static_cast<CScriptNode*>(pNode);
|
||||
if (It->NodeType() == eScriptNode)
|
||||
SelectedScriptNodes << static_cast<CScriptNode*>(*It);
|
||||
}
|
||||
|
||||
if (!SelectedScriptNodes.isEmpty())
|
||||
|
@ -727,8 +745,8 @@ void CWorldEditor::UpdateCameraOrbit()
|
|||
{
|
||||
CCamera *pCamera = &ui->MainViewport->Camera();
|
||||
|
||||
if (!mSelection.isEmpty())
|
||||
pCamera->SetOrbit(mSelectionBounds);
|
||||
if (!mpSelection->IsEmpty())
|
||||
pCamera->SetOrbit(mpSelection->Bounds());
|
||||
else if (mpArea)
|
||||
pCamera->SetOrbit(mpArea->AABox(), 1.5f);
|
||||
}
|
||||
|
@ -745,34 +763,33 @@ void CWorldEditor::OnCameraSpeedChange(double speed)
|
|||
|
||||
void CWorldEditor::OnTransformSpinBoxModified(CVector3f value)
|
||||
{
|
||||
if (mSelection.empty()) return;
|
||||
if (mpSelection->IsEmpty()) return;
|
||||
|
||||
switch (mGizmo.Mode())
|
||||
{
|
||||
// Use absolute position/rotation, but relative scale. (This way spinbox doesn't show preview multiplier)
|
||||
case CGizmo::eTranslate:
|
||||
{
|
||||
CVector3f delta = value - mSelection.front()->AbsolutePosition();
|
||||
mUndoStack.push(new CTranslateNodeCommand(this, mSelection, delta, mTranslateSpace));
|
||||
CVector3f delta = value - mpSelection->Front()->AbsolutePosition();
|
||||
mUndoStack.push(new CTranslateNodeCommand(this, mpSelection->SelectedNodeList(), delta, mTranslateSpace));
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eRotate:
|
||||
{
|
||||
CQuaternion delta = CQuaternion::FromEuler(value) * mSelection.front()->AbsoluteRotation().Inverse();
|
||||
mUndoStack.push(new CRotateNodeCommand(this, mSelection, CVector3f::skZero, delta, mRotateSpace));
|
||||
CQuaternion delta = CQuaternion::FromEuler(value) * mpSelection->Front()->AbsoluteRotation().Inverse();
|
||||
mUndoStack.push(new CRotateNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta, mRotateSpace));
|
||||
break;
|
||||
}
|
||||
|
||||
case CGizmo::eScale:
|
||||
{
|
||||
CVector3f delta = value / mSelection.front()->AbsoluteScale();
|
||||
mUndoStack.push(new CScaleNodeCommand(this, mSelection, CVector3f::skZero, delta));
|
||||
CVector3f delta = value / mpSelection->Front()->AbsoluteScale();
|
||||
mUndoStack.push(new CScaleNodeCommand(this, mpSelection->SelectedNodeList(), CVector3f::skZero, delta));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RecalculateSelectionBounds();
|
||||
UpdateGizmoUI();
|
||||
}
|
||||
|
||||
|
@ -782,7 +799,7 @@ void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
|
|||
ui->TransformSpinBox->blockSignals(true);
|
||||
ui->MainViewport->setFocus();
|
||||
ui->TransformSpinBox->blockSignals(false);
|
||||
if (mSelection.empty()) return;
|
||||
if (mpSelection->IsEmpty()) return;
|
||||
|
||||
if (mGizmo.Mode() == CGizmo::eTranslate) mUndoStack.push(CTranslateNodeCommand::End());
|
||||
else if (mGizmo.Mode() == CGizmo::eRotate) mUndoStack.push(CRotateNodeCommand::End());
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "CPoiMapEditDialog.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include "Editor/CGizmo.h"
|
||||
#include "Editor/CSceneViewport.h"
|
||||
|
||||
#include <Common/CTimer.h>
|
||||
#include <Common/EKeyInputs.h>
|
||||
|
@ -47,21 +48,24 @@ public:
|
|||
explicit CWorldEditor(QWidget *parent = 0);
|
||||
~CWorldEditor();
|
||||
void closeEvent(QCloseEvent *pEvent);
|
||||
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
||||
void SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex);
|
||||
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||
bool CheckUnsavedChanges();
|
||||
|
||||
inline CGameArea* ActiveArea() const { return mpArea; }
|
||||
inline EGame CurrentGame() const { return mpArea ? mpArea->Version() : eUnknownVersion; }
|
||||
inline CLinkDialog* LinkDialog() const { return mpLinkDialog; }
|
||||
CSceneViewport* Viewport() const;
|
||||
|
||||
public slots:
|
||||
virtual void NotifyNodeAboutToBeDeleted(CSceneNode *pNode);
|
||||
|
||||
bool Save();
|
||||
void OnLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||
void OnPropertyModified(IProperty *pProp);
|
||||
void SetSelectionActive(bool Active);
|
||||
void SetSelectionInstanceNames(const QString& rkNewName, bool IsDone);
|
||||
void SetSelectionLayer(CScriptLayer *pLayer);
|
||||
void DeleteSelection();
|
||||
|
||||
void UpdateStatusBar();
|
||||
void UpdateGizmoUI();
|
||||
|
@ -116,7 +120,7 @@ signals:
|
|||
void InstancesLayerAboutToChange();
|
||||
void InstancesLayerChanged(const QList<CScriptNode*>& rkInstanceList);
|
||||
void InstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||
void PropertyModified(IProperty *pProp, bool IsEditorProperty);
|
||||
void PropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||
};
|
||||
|
||||
#endif // CWORLDEDITOR_H
|
||||
|
|
|
@ -229,7 +229,7 @@
|
|||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
|
@ -268,17 +268,14 @@
|
|||
<widget class="WEditorProperties" name="CreateTabEditorProperties" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="WCreateTab" name="CreateTabContents" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -755,6 +752,14 @@
|
|||
<string>Edit POI to World Map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -792,6 +797,12 @@
|
|||
<header>Editor/WorldEditor/WEditorProperties.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>WCreateTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Editor/WorldEditor/WCreateTab.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../Icons.qrc"/>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "WCreateTab.h"
|
||||
#include "ui_WCreateTab.h"
|
||||
#include "CTemplateMimeData.h"
|
||||
#include "CWorldEditor.h"
|
||||
#include "Editor/Undo/UndoCommands.h"
|
||||
|
||||
WCreateTab::WCreateTab(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
|
@ -12,3 +15,47 @@ WCreateTab::~WCreateTab()
|
|||
{
|
||||
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
|
||||
#define WCREATETAB_H
|
||||
|
||||
#include "CWorldEditor.h"
|
||||
#include <Core/Resource/Script/CMasterTemplate.h>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
|
@ -10,11 +12,14 @@ class WCreateTab;
|
|||
class WCreateTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
CWorldEditor *mpEditor;
|
||||
|
||||
public:
|
||||
explicit WCreateTab(QWidget *parent = 0);
|
||||
~WCreateTab();
|
||||
|
||||
bool eventFilter(QObject *, QEvent *);
|
||||
void SetEditor(CWorldEditor *pEditor);
|
||||
void SetMaster(CMasterTemplate *pMaster);
|
||||
private:
|
||||
Ui::WCreateTab *ui;
|
||||
};
|
||||
|
|
|
@ -6,14 +6,90 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>216</width>
|
||||
<height>421</height>
|
||||
<width>290</width>
|
||||
<height>470</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</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>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>CTemplateListView</class>
|
||||
<extends>QListView</extends>
|
||||
<header>Editor/WorldEditor/CTemplateListView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -65,7 +65,7 @@ void WEditorProperties::SyncToEditor(CWorldEditor *pEditor)
|
|||
connect(mpEditor, SIGNAL(SelectionModified()), this, SLOT(OnSelectionModified()));
|
||||
connect(mpEditor, SIGNAL(LayersModified()), this, SLOT(OnLayersModified()));
|
||||
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();
|
||||
}
|
||||
|
@ -100,16 +100,16 @@ void WEditorProperties::SetLayerComboBox()
|
|||
// ************ PUBLIC SLOTS ************
|
||||
void WEditorProperties::OnSelectionModified()
|
||||
{
|
||||
const QList<CSceneNode*>& rkSelection = mpEditor->GetSelection();
|
||||
mpDisplayNode = (rkSelection.size() == 1 ? rkSelection.front() : nullptr);
|
||||
CNodeSelection *pSelection = mpEditor->Selection();
|
||||
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->setEnabled(false);
|
||||
mpInstanceNameLineEdit->setEnabled(false);
|
||||
|
||||
if (rkSelection.empty())
|
||||
if (pSelection->IsEmpty())
|
||||
{
|
||||
mpInstanceInfoLabel->setText("<i>[No selection]</i>");
|
||||
mpInstanceNameLineEdit->clear();
|
||||
|
@ -121,7 +121,7 @@ void WEditorProperties::OnSelectionModified()
|
|||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -139,11 +139,11 @@ void WEditorProperties::OnSelectionModified()
|
|||
SetLayerComboBox();
|
||||
}
|
||||
|
||||
void WEditorProperties::OnPropertyModified(IProperty* /*pProp*/, bool IsEditorProperty)
|
||||
void WEditorProperties::OnPropertyModified(CScriptObject *pInstance, IProperty *pProp)
|
||||
{
|
||||
if (!mpInstanceNameLineEdit->hasFocus())
|
||||
{
|
||||
if (mpDisplayNode->NodeType() == eScriptNode && IsEditorProperty)
|
||||
if (mpDisplayNode->NodeType() == eScriptNode && pInstance->IsEditorProperty(pProp))
|
||||
UpdatePropertyValues();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
|
||||
public slots:
|
||||
void OnSelectionModified();
|
||||
void OnPropertyModified(IProperty *pProp, bool IsEditorProperty);
|
||||
void OnPropertyModified(CScriptObject *pInst, IProperty *pProp);
|
||||
void OnInstancesLayerChanged(const QList<CScriptNode*>& rkNodeList);
|
||||
void OnLayersModified();
|
||||
void UpdatePropertyValues();
|
||||
|
|
|
@ -64,18 +64,28 @@ void WModifyTab::SetEditor(CWorldEditor *pEditor)
|
|||
ui->PropertyView->SetEditor(mpWorldEditor);
|
||||
connect(mpWorldEditor, SIGNAL(SelectionTransformed()), this, SLOT(OnWorldSelectionTransformed()));
|
||||
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)
|
||||
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
|
||||
if (mpSelectedNode->NodeType() == eScriptNode)
|
||||
|
@ -100,15 +110,6 @@ void WModifyTab::GenerateUI(QList<CSceneNode*>& Selection)
|
|||
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)
|
||||
{
|
||||
if (mpSelectedNode && mpSelectedNode->NodeType() == eScriptNode)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "CLinkDialog.h"
|
||||
#include "CLinkModel.h"
|
||||
#include "Editor/CNodeSelection.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
#include <Core/Scene/CScriptNode.h>
|
||||
|
||||
|
@ -36,10 +37,10 @@ public:
|
|||
explicit WModifyTab(QWidget *pParent = 0);
|
||||
~WModifyTab();
|
||||
void SetEditor(CWorldEditor *pEditor);
|
||||
void GenerateUI(QList<CSceneNode*>& Selection);
|
||||
void ClearUI();
|
||||
|
||||
public slots:
|
||||
void GenerateUI();
|
||||
void OnInstanceLinksModified(const QList<CScriptObject*>& rkInstances);
|
||||
void OnWorldSelectionTransformed();
|
||||
|
||||
|
|
|
@ -20,22 +20,22 @@ CQuaternion::CQuaternion(float _w, float _x, float _y, float _z)
|
|||
z = _z;
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::XAxis()
|
||||
CVector3f CQuaternion::XAxis() const
|
||||
{
|
||||
return (*this * CVector3f::skUnitX);
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::YAxis()
|
||||
CVector3f CQuaternion::YAxis() const
|
||||
{
|
||||
return (*this * CVector3f::skUnitY);
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::ZAxis()
|
||||
CVector3f CQuaternion::ZAxis() const
|
||||
{
|
||||
return (*this * CVector3f::skUnitZ);
|
||||
}
|
||||
|
||||
CQuaternion CQuaternion::Inverse()
|
||||
CQuaternion CQuaternion::Inverse() const
|
||||
{
|
||||
float fNorm = (w * w) + (x * x) + (y * y) + (z * z);
|
||||
|
||||
|
@ -48,7 +48,7 @@ CQuaternion CQuaternion::Inverse()
|
|||
return CQuaternion::skZero;
|
||||
}
|
||||
|
||||
CVector3f CQuaternion::ToEuler()
|
||||
CVector3f CQuaternion::ToEuler() const
|
||||
{
|
||||
// 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,
|
||||
|
|
|
@ -11,11 +11,11 @@ public:
|
|||
CQuaternion();
|
||||
CQuaternion(float _w, float _x, float _y, float _z);
|
||||
|
||||
CVector3f XAxis();
|
||||
CVector3f YAxis();
|
||||
CVector3f ZAxis();
|
||||
CQuaternion Inverse();
|
||||
CVector3f ToEuler();
|
||||
CVector3f XAxis() const;
|
||||
CVector3f YAxis() const;
|
||||
CVector3f ZAxis() const;
|
||||
CQuaternion Inverse() const;
|
||||
CVector3f ToEuler() const;
|
||||
|
||||
// Operators
|
||||
CVector3f operator*(const CVector3f& vec) const;
|
||||
|
|
Loading…
Reference in New Issue