Added TPropCast property casting function, added support for clean/dirty state in the world editor + check for unsaved changes when the window is closed
This commit is contained in:
parent
6669dd4367
commit
1a07a9c083
|
@ -18,7 +18,7 @@ class CLightParameters
|
|||
EGame mGame;
|
||||
|
||||
TLongProperty *mpLightLayer;
|
||||
TLongProperty *mpWorldLightingOptions;
|
||||
TEnumProperty *mpWorldLightingOptions;
|
||||
|
||||
public:
|
||||
CLightParameters(CPropertyStruct *pStruct, EGame Game)
|
||||
|
@ -31,13 +31,13 @@ public:
|
|||
{
|
||||
if (mGame <= ePrime)
|
||||
{
|
||||
mpWorldLightingOptions = (TLongProperty*) mpStruct->PropertyByIndex(0x7);
|
||||
mpLightLayer = (TLongProperty*) mpStruct->PropertyByIndex(0xD);
|
||||
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByIndex(0x7));
|
||||
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByIndex(0xD));
|
||||
}
|
||||
else
|
||||
{
|
||||
mpWorldLightingOptions = (TLongProperty*) mpStruct->PropertyByIndex(0x6B5E7509);
|
||||
mpLightLayer = (TLongProperty*) mpStruct->PropertyByID(0x1F715FD3);
|
||||
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByID(0x6B5E7509));
|
||||
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByID(0x1F715FD3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ public:
|
|||
|
||||
~TTypedProperty() {}
|
||||
virtual EPropertyType Type() const { return TypeEnum; }
|
||||
static inline EPropertyType StaticType() { return TypeEnum; }
|
||||
|
||||
virtual TString ToString() const { return mValue.ToString(); }
|
||||
virtual IPropertyValue* RawValue() { return &mValue; }
|
||||
|
||||
|
@ -124,6 +126,7 @@ public:
|
|||
}
|
||||
|
||||
EPropertyType Type() const { return eStructProperty; }
|
||||
static inline EPropertyType StaticType() { return eStructProperty; }
|
||||
|
||||
virtual void Copy(const IProperty *pkProp);
|
||||
|
||||
|
@ -161,6 +164,7 @@ public:
|
|||
: CPropertyStruct(pTemp, pParent) {}
|
||||
|
||||
EPropertyType Type() const { return eArrayProperty; }
|
||||
static inline EPropertyType StaticType() { return eArrayProperty; }
|
||||
|
||||
virtual IProperty* Clone(CPropertyStruct *pParent) const
|
||||
{
|
||||
|
@ -179,5 +183,14 @@ public:
|
|||
TString ElementName() const;
|
||||
};
|
||||
|
||||
/*
|
||||
* Function for casting properties. Returns null if the property is not actually the requested type.
|
||||
*/
|
||||
template <class PropertyClass>
|
||||
PropertyClass* TPropCast(IProperty *pProp)
|
||||
{
|
||||
return (pProp && pProp->Type() == PropertyClass::StaticType() ? static_cast<PropertyClass*>(pProp) : nullptr);
|
||||
}
|
||||
|
||||
#endif // IPROPERTY
|
||||
|
||||
|
|
|
@ -76,9 +76,6 @@ ENodeType CScriptNode::NodeType()
|
|||
|
||||
void CScriptNode::OnTransformed()
|
||||
{
|
||||
if (mpExtra)
|
||||
mpExtra->OnTransformed();
|
||||
|
||||
if (mpInstance)
|
||||
{
|
||||
CScriptTemplate *pTemplate = Template();
|
||||
|
@ -92,6 +89,9 @@ void CScriptNode::OnTransformed()
|
|||
if (pTemplate->HasScale() && LocalScale() != mpInstance->Scale())
|
||||
mpInstance->SetScale(LocalScale());
|
||||
}
|
||||
|
||||
if (mpExtra)
|
||||
mpExtra->OnTransformed();
|
||||
}
|
||||
|
||||
void CScriptNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
|
||||
|
@ -167,7 +167,6 @@ void CScriptNode::Draw(FRenderOptions Options, int ComponentIndex, const SViewIn
|
|||
else
|
||||
{
|
||||
LoadLights(ViewInfo);
|
||||
CGraphics::UpdateLightBlock();
|
||||
}
|
||||
|
||||
LoadModelMatrix();
|
||||
|
|
|
@ -16,36 +16,18 @@ CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CScen
|
|||
CPropertyStruct *pBaseStruct = pInstance->Properties();
|
||||
|
||||
// Fetch render side
|
||||
mpRenderSideProp = (TEnumProperty*) pBaseStruct->PropertyByIndex(0x5);
|
||||
|
||||
if (mpRenderSideProp && mpRenderSideProp->Type() != eEnumProperty)
|
||||
mpRenderSideProp = nullptr;
|
||||
|
||||
mpRenderSideProp = TPropCast<TEnumProperty>(pBaseStruct->PropertyByIndex(0x5));
|
||||
if (mpRenderSideProp) PropertyModified(mpRenderSideProp);
|
||||
|
||||
// Fetch scale
|
||||
mpSizeProp = (TVector3Property*) pBaseStruct->PropertyByIndex(0x2);
|
||||
|
||||
if (mpSizeProp && mpSizeProp->Type() != eVector3Property)
|
||||
mpSizeProp = nullptr;
|
||||
|
||||
if (mpSizeProp) PropertyModified (mpSizeProp);
|
||||
mpSizeProp = TPropCast<TVector3Property>(pBaseStruct->PropertyByIndex(0x2));
|
||||
if (mpSizeProp) PropertyModified(mpSizeProp);
|
||||
|
||||
// Fetch textures
|
||||
for (u32 iTex = 0; iTex < 3; iTex++)
|
||||
{
|
||||
mpTextureProps[iTex] = (TFileProperty*) pBaseStruct->PropertyByIndex(0x6 + iTex);
|
||||
|
||||
if (mpTextureProps[iTex])
|
||||
{
|
||||
if (mpTextureProps[iTex]->Type() == eFileProperty)
|
||||
PropertyModified(mpTextureProps[iTex]);
|
||||
else
|
||||
mpTextureProps[iTex] = nullptr;
|
||||
}
|
||||
|
||||
else
|
||||
mpTextures[iTex] = nullptr;
|
||||
mpTextureProps[iTex] = TPropCast<TFileProperty>(pBaseStruct->PropertyByIndex(0x6 + iTex));
|
||||
if (mpTextureProps[iTex]) PropertyModified(mpTextureProps[iTex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +129,12 @@ void CDamageableTriggerExtra::UpdatePlaneTransform()
|
|||
MarkTransformChanged();
|
||||
}
|
||||
|
||||
void CDamageableTriggerExtra::OnTransformed()
|
||||
{
|
||||
mPlaneSize = mpSizeProp->Get();
|
||||
UpdatePlaneTransform();
|
||||
}
|
||||
|
||||
void CDamageableTriggerExtra::PropertyModified(IProperty *pProperty)
|
||||
{
|
||||
if (pProperty == mpRenderSideProp)
|
||||
|
@ -209,7 +197,7 @@ void CDamageableTriggerExtra::Draw(FRenderOptions Options, int /*ComponentIndex*
|
|||
|
||||
// Note: The plane the game renders this onto is 5x4.5, which is why we divide the tex coords by this value
|
||||
CVector2f TexUL(0.f, mCoordScale.y / 4.5f);
|
||||
CVector2f TexUR(mCoordScale.x / 5.f, mCoordScale.y / 4.5f);
|
||||
CVector2f TexUR(mCoordScale.x / 5.f, mCoordScale.y / 4.5f);
|
||||
CVector2f TexBR(mCoordScale.x / 5.f, 0.f);
|
||||
CVector2f TexBL(0.f, 0.f);
|
||||
CDrawUtil::DrawSquare(TexUL, TexUR, TexBR, TexBL);
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
~CDamageableTriggerExtra();
|
||||
void CreateMaterial();
|
||||
void UpdatePlaneTransform();
|
||||
void OnTransformed();
|
||||
void PropertyModified(IProperty *pProperty);
|
||||
bool ShouldDrawNormalAssets();
|
||||
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
|
||||
|
|
|
@ -9,31 +9,19 @@ CDoorExtra::CDoorExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pPa
|
|||
{
|
||||
CPropertyStruct *pBaseStruct = pInstance->Properties();
|
||||
|
||||
mpShieldModelProp = (TFileProperty*) pBaseStruct->PropertyByID(0xB20CC271);
|
||||
if (mpShieldModelProp && (mpShieldModelProp->Type() != eFileProperty))
|
||||
mpShieldModelProp = nullptr;
|
||||
|
||||
if (mpShieldModelProp)
|
||||
PropertyModified(mpShieldModelProp);
|
||||
mpShieldModelProp = TPropCast<TFileProperty>(pBaseStruct->PropertyByID(0xB20CC271));
|
||||
if (mpShieldModelProp) PropertyModified(mpShieldModelProp);
|
||||
|
||||
if (mGame >= eEchoes)
|
||||
{
|
||||
mpShieldColorProp = (TColorProperty*) pBaseStruct->PropertyByID(0x47B4E863);
|
||||
if (mpShieldColorProp && (mpShieldColorProp->Type() != eColorProperty))
|
||||
mpShieldColorProp = nullptr;
|
||||
|
||||
if (mpShieldColorProp)
|
||||
PropertyModified(mpShieldColorProp);
|
||||
mpShieldColorProp = TPropCast<TColorProperty>(pBaseStruct->PropertyByID(0x47B4E863));
|
||||
if (mpShieldColorProp) PropertyModified(mpShieldColorProp);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
mpDisabledProp = (TBoolProperty*) pBaseStruct->PropertyByID(0xDEE730F5);
|
||||
if (mpDisabledProp && (mpDisabledProp->Type() != eBoolProperty))
|
||||
mpDisabledProp = nullptr;
|
||||
|
||||
if (mpDisabledProp)
|
||||
PropertyModified(mpDisabledProp);
|
||||
mpDisabledProp = TPropCast<TBoolProperty>(pBaseStruct->PropertyByID(0xDEE730F5));
|
||||
if (mpDisabledProp) PropertyModified(mpDisabledProp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,32 +11,9 @@ CPointOfInterestExtra::CPointOfInterestExtra(CScriptObject *pInstance, CScene *p
|
|||
// Fetch scan data property
|
||||
CPropertyStruct *pBaseProp = pInstance->Properties();
|
||||
|
||||
switch (mGame)
|
||||
{
|
||||
case ePrimeDemo:
|
||||
case ePrime:
|
||||
mpScanProperty = (TFileProperty*) pBaseProp->PropertyByIDString("0x04:0x00");
|
||||
break;
|
||||
|
||||
case eEchoesDemo:
|
||||
case eEchoes:
|
||||
case eCorruptionProto:
|
||||
case eCorruption:
|
||||
mpScanProperty = (TFileProperty*) pBaseProp->PropertyByIDString("0xBDBEC295:0xB94E9BE7");
|
||||
break;
|
||||
|
||||
default:
|
||||
mpScanProperty = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mpScanProperty)
|
||||
{
|
||||
if (mpScanProperty->Type() == eFileProperty)
|
||||
PropertyModified(mpScanProperty);
|
||||
else
|
||||
mpScanProperty = nullptr;
|
||||
}
|
||||
if (mGame <= ePrime) mpScanProperty = TPropCast<TFileProperty>(pBaseProp->PropertyByIDString("0x04:0x00"));
|
||||
else mpScanProperty = (TFileProperty*) pBaseProp->PropertyByIDString("0xBDBEC295:0xB94E9BE7");
|
||||
if (mpScanProperty) PropertyModified(mpScanProperty);
|
||||
}
|
||||
|
||||
void CPointOfInterestExtra::PropertyModified(IProperty* pProperty)
|
||||
|
|
|
@ -11,16 +11,16 @@ CRadiusSphereExtra::CRadiusSphereExtra(CScriptObject *pInstance, CScene *pScene,
|
|||
switch (mObjectType)
|
||||
{
|
||||
case 0x63: // Repulsor (MP1)
|
||||
mpRadius = (TFloatProperty*) pInstance->Properties()->PropertyByID(0x3);
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x3));
|
||||
break;
|
||||
|
||||
case 0x68: // RadialDamage (MP1)
|
||||
mpRadius = (TFloatProperty*) pInstance->Properties()->PropertyByID(0x4);
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x4));
|
||||
break;
|
||||
|
||||
case 0x5245504C: // "REPL" Repulsor (MP2/MP3)
|
||||
case 0x52414444: // "RADD" RadialDamage (MP2/MP3/DKCR)
|
||||
mpRadius = (TFloatProperty*) pInstance->Properties()->PropertyByID(0x78C507EB);
|
||||
mpRadius = TPropCast<TFloatProperty>(pInstance->Properties()->PropertyByID(0x78C507EB));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,21 +12,10 @@ CSpacePirateExtra::CSpacePirateExtra(CScriptObject *pInstance, CScene *pScene, C
|
|||
|
||||
if (pVulns && pVulns->Type() == eStructProperty)
|
||||
{
|
||||
mpPowerVuln = (TLongProperty*) pVulns->PropertyByID(0x0);
|
||||
if (mpPowerVuln && mpPowerVuln->Type() != eLongProperty && mpPowerVuln->Type() != eEnumProperty)
|
||||
mpPowerVuln = nullptr;
|
||||
|
||||
mpWaveVuln = (TLongProperty*) pVulns->PropertyByID(0x2);
|
||||
if (mpWaveVuln && mpWaveVuln->Type() != eLongProperty && mpWaveVuln->Type() != eEnumProperty)
|
||||
mpWaveVuln = nullptr;
|
||||
|
||||
mpIceVuln = (TLongProperty*) pVulns->PropertyByID(0x1);
|
||||
if (mpIceVuln && mpIceVuln->Type() != eLongProperty && mpIceVuln->Type() != eEnumProperty)
|
||||
mpIceVuln = nullptr;
|
||||
|
||||
mpPlasmaVuln = (TLongProperty*) pVulns->PropertyByID(0x3);
|
||||
if (mpPlasmaVuln && mpPlasmaVuln->Type() != eLongProperty && mpPlasmaVuln->Type() != eEnumProperty)
|
||||
mpPlasmaVuln = nullptr;
|
||||
mpPowerVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x0));
|
||||
mpWaveVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x2));
|
||||
mpIceVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x1));
|
||||
mpPlasmaVuln = TPropCast<TEnumProperty>(pVulns->PropertyByID(0x3));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
class CSpacePirateExtra : public CScriptExtra
|
||||
{
|
||||
// Render beam troopers with the correct color
|
||||
TLongProperty *mpPowerVuln;
|
||||
TLongProperty *mpWaveVuln;
|
||||
TLongProperty *mpIceVuln;
|
||||
TLongProperty *mpPlasmaVuln;
|
||||
TEnumProperty *mpPowerVuln;
|
||||
TEnumProperty *mpWaveVuln;
|
||||
TEnumProperty *mpIceVuln;
|
||||
TEnumProperty *mpPlasmaVuln;
|
||||
|
||||
public:
|
||||
explicit CSpacePirateExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pParent = 0);
|
||||
|
|
|
@ -134,7 +134,7 @@ void CStartWindow::FillAreaUI()
|
|||
if (AttachedAreaSTRG)
|
||||
AttachedStr = TO_QSTRING(AttachedAreaSTRG->GetString("ENGL", 0));
|
||||
else
|
||||
AttachedStr = QString("!!") + TO_QSTRING(mpWorld->GetAreaInternalName(AttachedAreaIndex));
|
||||
AttachedStr = QString("!") + TO_QSTRING(mpWorld->GetAreaInternalName(AttachedAreaIndex));
|
||||
|
||||
ui->AttachedAreasList->addItem(AttachedStr);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ void CStartWindow::on_LaunchWorldEditorButton_clicked()
|
|||
else
|
||||
{
|
||||
mpWorld->SetAreaLayerInfo(pArea, mSelectedAreaIndex);
|
||||
mpWorldEditor->SetArea(mpWorld, pArea);
|
||||
mpWorldEditor->SetArea(mpWorld, pArea, mSelectedAreaIndex);
|
||||
mpWorldEditor->setWindowModality(Qt::WindowModal);
|
||||
mpWorldEditor->showMaximized();
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@ HEADERS += \
|
|||
WorldEditor/CInstancesModel.h \
|
||||
Undo/CEditScriptPropertyCommand.h \
|
||||
Undo/CResizeScriptArrayCommand.h \
|
||||
Undo/CBasicPropertyCommand.h
|
||||
Undo/CBasicPropertyCommand.h \
|
||||
Undo/IUndoCommand.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <Core/Resource/Script/IPropertyTemplate.h>
|
||||
|
||||
CBasicPropertyCommand::CBasicPropertyCommand(CPropertyModel *pModel, const QModelIndex& rkIndex)
|
||||
: QUndoCommand("Edit Property")
|
||||
: IUndoCommand("Edit Property")
|
||||
, mpModel(pModel)
|
||||
, mpProperty(pModel->PropertyForIndex(rkIndex, true))
|
||||
, mpTemplate(mpProperty->Template())
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef CBASICPROPERTYCOMMAND_H
|
||||
#define CBASICPROPERTYCOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/PropertyEdit/CPropertyModel.h"
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CBasicPropertyCommand : public QUndoCommand
|
||||
class CBasicPropertyCommand : public IUndoCommand
|
||||
{
|
||||
protected:
|
||||
CPropertyModel *mpModel;
|
||||
|
@ -18,6 +18,7 @@ protected:
|
|||
public:
|
||||
CBasicPropertyCommand(CPropertyModel *pModel, const QModelIndex& rkIndex);
|
||||
virtual void UpdateArraySubProperty();
|
||||
virtual bool AffectsCleanState() const { return true; }
|
||||
};
|
||||
|
||||
#endif // CBASICPROPERTYCOMMAND_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CClearSelectionCommand::CClearSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& selection)
|
||||
: QUndoCommand("Clear Selection"),
|
||||
: IUndoCommand("Clear Selection"),
|
||||
mpEditor(pEditor),
|
||||
mSelectionState(selection),
|
||||
mpSelection(&selection)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CCLEARSELECTIONCOMMAND_H
|
||||
#define CCLEARSELECTIONCOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CClearSelectionCommand : public QUndoCommand
|
||||
class CClearSelectionCommand : public IUndoCommand
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
QList<CSceneNode*> mSelectionState;
|
||||
|
@ -16,6 +15,7 @@ public:
|
|||
~CClearSelectionCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
#endif // CCLEARSELECTIONCOMMAND_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CDeselectNodeCommand::CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
||||
: QUndoCommand("Deselect"),
|
||||
: IUndoCommand("Deselect"),
|
||||
mpEditor(pEditor),
|
||||
mpNode(pNode),
|
||||
mpSelection(&selection)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CDESELECTNODECOMMAND_H
|
||||
#define CDESELECTNODECOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CDeselectNodeCommand : public QUndoCommand
|
||||
class CDeselectNodeCommand : public IUndoCommand
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
CSceneNode *mpNode;
|
||||
|
@ -15,6 +14,7 @@ public:
|
|||
CDeselectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
#endif // CDESELECTNODECOMMAND_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <Core/Scene/CSceneIterator.h>
|
||||
|
||||
CInvertSelectionCommand::CInvertSelectionCommand(INodeEditor *pEditor, QList<CSceneNode*>& rSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||
: QUndoCommand("Invert Selection")
|
||||
: IUndoCommand("Invert Selection")
|
||||
, mpEditor(pEditor)
|
||||
, mOldSelection(rSelection)
|
||||
, mpSelection(&rSelection)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CINVERTSELECTIONCOMMAND_H
|
||||
#define CINVERTSELECTIONCOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CInvertSelectionCommand : public QUndoCommand
|
||||
class CInvertSelectionCommand : public IUndoCommand
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
QList<CSceneNode*> mOldSelection;
|
||||
|
@ -18,6 +17,7 @@ public:
|
|||
~CInvertSelectionCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
virtual bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
#endif // CINVERTSELECTIONCOMMAND_H
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CRotateNodeCommand::CRotateNodeCommand()
|
||||
: QUndoCommand("Rotate"),
|
||||
: IUndoCommand("Rotate"),
|
||||
mpEditor(nullptr),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
}
|
||||
|
||||
CRotateNodeCommand::CRotateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& /*pivot*/, const CQuaternion& delta, ETransformSpace transformSpace)
|
||||
: QUndoCommand("Rotate"),
|
||||
: IUndoCommand("Rotate"),
|
||||
mpEditor(pEditor),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#ifndef CROTATENODECOMMAND_H
|
||||
#define CROTATENODECOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QList>
|
||||
|
||||
class CRotateNodeCommand : public QUndoCommand
|
||||
class CRotateNodeCommand : public IUndoCommand
|
||||
{
|
||||
struct SNodeRotate
|
||||
{
|
||||
|
@ -29,6 +28,7 @@ public:
|
|||
bool mergeWith(const QUndoCommand *other);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return true; }
|
||||
static CRotateNodeCommand* End();
|
||||
};
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CScaleNodeCommand::CScaleNodeCommand()
|
||||
: QUndoCommand("Scale"),
|
||||
: IUndoCommand("Scale"),
|
||||
mpEditor(nullptr),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
}
|
||||
|
||||
CScaleNodeCommand::CScaleNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& /*pivot*/, const CVector3f& delta)
|
||||
: QUndoCommand("Scale"),
|
||||
: IUndoCommand("Scale"),
|
||||
mpEditor(pEditor),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#ifndef CSCALENODECOMMAND_H
|
||||
#define CSCALENODECOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QList>
|
||||
|
||||
class CScaleNodeCommand : public QUndoCommand
|
||||
class CScaleNodeCommand : public IUndoCommand
|
||||
{
|
||||
struct SNodeScale
|
||||
{
|
||||
|
@ -29,6 +28,7 @@ public:
|
|||
bool mergeWith(const QUndoCommand *other);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return true; }
|
||||
static CScaleNodeCommand* End();
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <Core/Scene/CSceneIterator.h>
|
||||
|
||||
CSelectAllCommand::CSelectAllCommand(INodeEditor *pEditor, QList<CSceneNode *> &rSelection, CScene *pScene, FNodeFlags NodeFlags)
|
||||
: QUndoCommand("Select All")
|
||||
: IUndoCommand("Select All")
|
||||
, mpEditor(pEditor)
|
||||
, mOldSelection(rSelection)
|
||||
, mpSelection(&rSelection)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CSELECTALLCOMMAND_H
|
||||
#define CSELECTALLCOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CSelectAllCommand : public QUndoCommand
|
||||
class CSelectAllCommand : public IUndoCommand
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
QList<CSceneNode*> mOldSelection;
|
||||
|
@ -18,6 +17,7 @@ public:
|
|||
~CSelectAllCommand();
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
#endif // CSELECTALLCOMMAND_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CSelectNodeCommand::CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection)
|
||||
: QUndoCommand("Select"),
|
||||
: IUndoCommand("Select"),
|
||||
mpEditor(pEditor),
|
||||
mpNode(pNode),
|
||||
mpSelection(&selection)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#ifndef CSELECTNODECOMMAND_H
|
||||
#define CSELECTNODECOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include "Editor/INodeEditor.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class CSelectNodeCommand : public QUndoCommand
|
||||
class CSelectNodeCommand : public IUndoCommand
|
||||
{
|
||||
INodeEditor *mpEditor;
|
||||
CSceneNode *mpNode;
|
||||
|
@ -15,6 +14,7 @@ public:
|
|||
CSelectNodeCommand(INodeEditor *pEditor, CSceneNode *pNode, QList<CSceneNode*>& selection);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return false; }
|
||||
};
|
||||
|
||||
#endif // CSELECTNODECOMMAND_H
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
#include "Editor/INodeEditor.h"
|
||||
|
||||
CTranslateNodeCommand::CTranslateNodeCommand()
|
||||
: QUndoCommand("Translate"),
|
||||
: IUndoCommand("Translate"),
|
||||
mpEditor(nullptr),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
}
|
||||
|
||||
CTranslateNodeCommand::CTranslateNodeCommand(INodeEditor *pEditor, const QList<CSceneNode*>& nodes, const CVector3f& delta, ETransformSpace transformSpace)
|
||||
: QUndoCommand("Translate"),
|
||||
: IUndoCommand("Translate"),
|
||||
mpEditor(pEditor),
|
||||
mCommandEnded(false)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#ifndef CTRANSLATENODECOMMAND_H
|
||||
#define CTRANSLATENODECOMMAND_H
|
||||
|
||||
#include "IUndoCommand.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
#include "Editor/INodeEditor.h"
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QList>
|
||||
|
||||
class CTranslateNodeCommand : public QUndoCommand
|
||||
class CTranslateNodeCommand : public IUndoCommand
|
||||
{
|
||||
struct SNodeTranslate
|
||||
{
|
||||
|
@ -27,6 +26,7 @@ public:
|
|||
bool mergeWith(const QUndoCommand *other);
|
||||
void undo();
|
||||
void redo();
|
||||
bool AffectsCleanState() const { return true; }
|
||||
static CTranslateNodeCommand* End();
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef IUNDOCOMMAND
|
||||
#define IUNDOCOMMAND
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
class IUndoCommand : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
IUndoCommand(QUndoCommand *pParent = 0)
|
||||
: QUndoCommand(pParent) {}
|
||||
|
||||
IUndoCommand(const QString& rkText, QUndoCommand *pParent = 0)
|
||||
: QUndoCommand(rkText, pParent) {}
|
||||
|
||||
virtual bool AffectsCleanState() const = 0;
|
||||
};
|
||||
|
||||
#endif // IUNDOCOMMAND
|
||||
|
|
@ -77,6 +77,9 @@ CWorldEditor::CWorldEditor(QWidget *parent) :
|
|||
connect(ui->TransformSpinBox, SIGNAL(ValueChanged(CVector3f)), this, SLOT(OnTransformSpinBoxModified(CVector3f)));
|
||||
connect(ui->TransformSpinBox, SIGNAL(EditingDone(CVector3f)), this, SLOT(OnTransformSpinBoxEdited(CVector3f)));
|
||||
connect(ui->CamSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnCameraSpeedChange(double)));
|
||||
connect(&mUndoStack, SIGNAL(indexChanged(int)), this, SLOT(OnUndoStackIndexChanged()));
|
||||
|
||||
connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save()));
|
||||
}
|
||||
|
||||
CWorldEditor::~CWorldEditor()
|
||||
|
@ -84,10 +87,33 @@ CWorldEditor::~CWorldEditor()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void CWorldEditor::closeEvent(QCloseEvent *)
|
||||
void CWorldEditor::closeEvent(QCloseEvent *pEvent)
|
||||
{
|
||||
if (mpPoiDialog)
|
||||
mpPoiDialog->close();
|
||||
bool ShouldClose = true;
|
||||
|
||||
if (isWindowModified())
|
||||
{
|
||||
int Result = QMessageBox::warning(this, "Save", "You have unsaved changes. Save?", QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel);
|
||||
|
||||
if (Result == QMessageBox::Yes)
|
||||
ShouldClose = Save();
|
||||
|
||||
else if (Result == QMessageBox::No)
|
||||
ShouldClose = true;
|
||||
|
||||
else if (Result == QMessageBox::Cancel)
|
||||
ShouldClose = false;
|
||||
}
|
||||
|
||||
if (ShouldClose)
|
||||
{
|
||||
if (mpPoiDialog)
|
||||
mpPoiDialog->close();
|
||||
}
|
||||
else
|
||||
{
|
||||
pEvent->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
bool CWorldEditor::eventFilter(QObject * /*pObj*/, QEvent * /*pEvent*/)
|
||||
|
@ -95,7 +121,7 @@ bool CWorldEditor::eventFilter(QObject * /*pObj*/, QEvent * /*pEvent*/)
|
|||
return false;
|
||||
}
|
||||
|
||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
||||
void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex)
|
||||
{
|
||||
ExitPickMode();
|
||||
ui->MainViewport->ResetHover();
|
||||
|
@ -153,6 +179,18 @@ void CWorldEditor::SetArea(CWorld *pWorld, CGameArea *pArea)
|
|||
// Set up sidebar tabs
|
||||
CMasterTemplate *pMaster = CMasterTemplate::GetMasterForGame(mpArea->Version());
|
||||
ui->InstancesTabContents->SetMaster(pMaster);
|
||||
|
||||
// Set window title
|
||||
CStringTable *pWorldNameTable = mpWorld->GetWorldName();
|
||||
TWideString WorldName = pWorldNameTable ? pWorldNameTable->GetString("ENGL", 0) : "[Untitled World]";
|
||||
|
||||
CStringTable *pAreaNameTable = mpWorld->GetAreaName(AreaIndex);
|
||||
TWideString AreaName = pAreaNameTable ? pAreaNameTable->GetString("ENGL", 0) : (TWideString("!") + mpWorld->GetAreaInternalName(AreaIndex).ToUTF16());
|
||||
|
||||
if (AreaName.IsEmpty())
|
||||
AreaName = "[Untitled Area]";
|
||||
|
||||
setWindowTitle(QString("Prime World Editor - %1 - %2[*]").arg(TO_QSTRING(WorldName)).arg(TO_QSTRING(AreaName)));
|
||||
}
|
||||
|
||||
CGameArea* CWorldEditor::ActiveArea()
|
||||
|
@ -160,7 +198,26 @@ CGameArea* CWorldEditor::ActiveArea()
|
|||
return mpArea;
|
||||
}
|
||||
|
||||
// ************ PROTECTED SLOTS ************
|
||||
// ************ PUBLIC SLOTS ************
|
||||
bool CWorldEditor::Save()
|
||||
{
|
||||
TString Out = mpArea->FullSource();
|
||||
CFileOutStream MREA(Out.ToStdString(), IOUtil::eBigEndian);
|
||||
|
||||
if (MREA.IsValid())
|
||||
{
|
||||
CAreaCooker::WriteCookedArea(mpArea, MREA);
|
||||
mUndoStack.setClean();
|
||||
setWindowModified(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, "Error", "Unable to save error; couldn't open output file " + TO_QSTRING(Out));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::UpdateStatusBar()
|
||||
{
|
||||
// Would be cool to do more frequent status bar updates with more info. Unfortunately, this causes lag.
|
||||
|
@ -281,6 +338,55 @@ void CWorldEditor::GizmoModeChanged(CGizmo::EGizmoMode mode)
|
|||
}
|
||||
|
||||
// ************ PRIVATE SLOTS ************
|
||||
void CWorldEditor::OnUndoStackIndexChanged()
|
||||
{
|
||||
// Check the commands that have been executed on the undo stack and find out whether any of them affect the clean state.
|
||||
// This is to prevent commands like select/deselect from altering the clean state.
|
||||
int CurrentIndex = mUndoStack.index();
|
||||
int CleanIndex = mUndoStack.cleanIndex();
|
||||
|
||||
if (CurrentIndex == CleanIndex)
|
||||
setWindowModified(false);
|
||||
|
||||
else
|
||||
{
|
||||
bool IsClean = true;
|
||||
int LowIndex = (CurrentIndex > CleanIndex ? CleanIndex + 1 : CurrentIndex);
|
||||
int HighIndex = (CurrentIndex > CleanIndex ? CurrentIndex - 1 : CleanIndex);
|
||||
|
||||
for (int iIdx = LowIndex; iIdx <= HighIndex; iIdx++)
|
||||
{
|
||||
const QUndoCommand *pkQCmd = mUndoStack.command(iIdx);
|
||||
|
||||
if (pkQCmd->childCount() > 0)
|
||||
{
|
||||
for (int iChild = 0; iChild < pkQCmd->childCount(); iChild++)
|
||||
{
|
||||
const IUndoCommand *pkCmd = static_cast<const IUndoCommand*>(pkQCmd->child(iChild));
|
||||
|
||||
if (pkCmd->AffectsCleanState())
|
||||
{
|
||||
IsClean = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
const IUndoCommand *pkCmd = static_cast<const IUndoCommand*>(pkQCmd);
|
||||
|
||||
if (pkCmd->AffectsCleanState())
|
||||
IsClean = false;
|
||||
}
|
||||
|
||||
if (!IsClean) break;
|
||||
}
|
||||
|
||||
setWindowModified(!IsClean);
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::OnPickModeEnter(QCursor Cursor)
|
||||
{
|
||||
ui->MainViewport->SetCursorState(Cursor);
|
||||
|
@ -530,11 +636,3 @@ void CWorldEditor::on_ActionEditPoiToWorldMap_triggered()
|
|||
mpPoiDialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionSave_triggered()
|
||||
{
|
||||
TString Out = mpArea->FullSource();
|
||||
CFileOutStream MREA(Out.ToStdString(), IOUtil::eBigEndian);
|
||||
CAreaCooker::WriteCookedArea(mpArea, MREA);
|
||||
QMessageBox::information(this, "Success", "Successfully saved area to " + TO_QSTRING(Out));
|
||||
}
|
||||
|
|
|
@ -40,12 +40,14 @@ class CWorldEditor : public INodeEditor
|
|||
public:
|
||||
explicit CWorldEditor(QWidget *parent = 0);
|
||||
~CWorldEditor();
|
||||
void closeEvent(QCloseEvent *);
|
||||
void closeEvent(QCloseEvent *pEvent);
|
||||
bool eventFilter(QObject *pObj, QEvent *pEvent);
|
||||
void SetArea(CWorld *pWorld, CGameArea *pArea);
|
||||
void SetArea(CWorld *pWorld, CGameArea *pArea, u32 AreaIndex);
|
||||
CGameArea* ActiveArea();
|
||||
|
||||
public slots:
|
||||
bool Save();
|
||||
|
||||
void UpdateStatusBar();
|
||||
void UpdateGizmoUI();
|
||||
void UpdateSelectionUI();
|
||||
|
@ -55,6 +57,7 @@ protected:
|
|||
void GizmoModeChanged(CGizmo::EGizmoMode mode);
|
||||
|
||||
private slots:
|
||||
void OnUndoStackIndexChanged();
|
||||
void OnPickModeEnter(QCursor Cursor);
|
||||
void OnPickModeExit();
|
||||
void RefreshViewport();
|
||||
|
@ -85,7 +88,6 @@ private slots:
|
|||
void on_ActionSelectAll_triggered();
|
||||
void on_ActionInvertSelection_triggered();
|
||||
void on_ActionEditPoiToWorldMap_triggered();
|
||||
void on_ActionSave_triggered();
|
||||
};
|
||||
|
||||
#endif // CWORLDEDITOR_H
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<property ID="0x04" name="Unknown 1" type="vector3f"/>
|
||||
<property ID="0x05" name="Unknown 2" type="long"/>
|
||||
<property ID="0x06" name="Unknown 3" type="bool"/>
|
||||
<property ID="0x07" name="Unknown 4" type="bool"/>
|
||||
<property ID="0x07" name="Display Fluid Surface" type="bool"/>
|
||||
<property ID="0x08" name="Texture 1" type="file" extensions="TXTR"/>
|
||||
<property ID="0x09" name="Texture 2" type="file" extensions="TXTR"/>
|
||||
<property ID="0x0A" name="Texture 3" type="file" extensions="TXTR"/>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<property ID="0x0F" name="Unknown 6" type="float"/>
|
||||
<property ID="0x10" name="Unknown 7" type="float"/>
|
||||
<property ID="0x11" name="Unknown 8" type="float"/>
|
||||
<property ID="0x12" name="Unknown 9" type="bool"/>
|
||||
<property ID="0x12" name="Active" type="bool"/>
|
||||
<property ID="0x13" name="Unknown 10" type="long"/>
|
||||
<property ID="0x14" name="Unknown 11" type="bool"/>
|
||||
<property ID="0x15" name="Unknown 12" type="float"/>
|
||||
|
@ -55,7 +55,9 @@
|
|||
<property ID="0x1E" name="Unknown 37" type="float"/>
|
||||
<property ID="0x1F" name="Unknown 38" type="color"/>
|
||||
<property ID="0x20" name="Unknown 39" type="color"/>
|
||||
<property ID="0x21" name="Particle 1" type="file" extensions="PART"/>
|
||||
<property ID="0x21" name="Enter Particle" type="file" extensions="PART">
|
||||
<description>This particle plays when an actor/projectile enters the water. It also plays when the morph ball is rolling in it at surface level.</description>
|
||||
</property>
|
||||
<property ID="0x22" name="Particle 2" type="file" extensions="PART"/>
|
||||
<property ID="0x23" name="Particle 3" type="file" extensions="PART"/>
|
||||
<property ID="0x24" name="Particle 4" type="file" extensions="PART"/>
|
||||
|
@ -73,10 +75,10 @@
|
|||
<property ID="0x30" name="Unknown 45" type="float"/>
|
||||
<property ID="0x31" name="Unknown 46" type="float"/>
|
||||
<property ID="0x32" name="Unknown 47" type="float"/>
|
||||
<property ID="0x33" name="Unknown 48" type="float"/>
|
||||
<property ID="0x34" name="Unknown 49" type="float"/>
|
||||
<property ID="0x35" name="Unknown 50" type="color"/>
|
||||
<property ID="0x36" name="Texture 7" type="file" extensions="TXTR"/>
|
||||
<property ID="0x33" name="Heat Wave Height" type="float"/>
|
||||
<property ID="0x34" name="Heat Wave Speed" type="float"/>
|
||||
<property ID="0x35" name="Heat Wave Color" type="color"/>
|
||||
<property ID="0x36" name="Lightmap Texture" type="file" extensions="TXTR"/>
|
||||
<property ID="0x37" name="Unknown 51" type="float"/>
|
||||
<property ID="0x38" name="Unknown 52" type="float"/>
|
||||
<property ID="0x39" name="Unknown 53" type="float"/>
|
||||
|
@ -91,6 +93,7 @@
|
|||
<property name="InstanceName" ID="0x00"/>
|
||||
<property name="Position" ID="0x01"/>
|
||||
<property name="Scale" ID="0x02"/>
|
||||
<property name="Active" ID="0x09"/>
|
||||
</properties>
|
||||
<assets/>
|
||||
<rotation_type>disabled</rotation_type>
|
||||
|
|
Loading…
Reference in New Issue