Notify script nodes when their properties are modified
This commit is contained in:
parent
b4c8226e15
commit
2e6024b413
|
@ -31,11 +31,10 @@ CScriptObject::~CScriptObject()
|
|||
mpActive = mpTemplate->FindActive(mpProperties);
|
||||
mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
|
||||
mHasInGameModel = mpTemplate->HasInGameModel(mpProperties);
|
||||
mVolumeShape = mpTemplate->VolumeShape(this);
|
||||
mVolumeScale = mpTemplate->VolumeScale(this);
|
||||
EvaluateDisplayModel();
|
||||
EvaluateBillboard();
|
||||
EvaluateCollisionModel();
|
||||
EvaluateVolume();
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateDisplayModel()
|
||||
|
@ -53,6 +52,23 @@ void CScriptObject::EvaluateCollisionModel()
|
|||
mpCollision = mpTemplate->FindCollision(mpProperties);
|
||||
}
|
||||
|
||||
void CScriptObject::EvaluateVolume()
|
||||
{
|
||||
mVolumeShape = mpTemplate->VolumeShape(this);
|
||||
mVolumeScale = mpTemplate->VolumeScale(this);
|
||||
}
|
||||
|
||||
bool CScriptObject::IsEditorProperty(IProperty *pProp)
|
||||
{
|
||||
return ( (pProp == mpInstanceName) ||
|
||||
(pProp == mpPosition) ||
|
||||
(pProp == mpRotation) ||
|
||||
(pProp == mpScale) ||
|
||||
(pProp == mpActive) ||
|
||||
(pProp->Parent() == mpLightParameters)
|
||||
);
|
||||
}
|
||||
|
||||
// ************ GETTERS ************
|
||||
IProperty* CScriptObject::PropertyByIndex(u32 index) const
|
||||
{
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
void EvaluateDisplayModel();
|
||||
void EvaluateBillboard();
|
||||
void EvaluateCollisionModel();
|
||||
void EvaluateVolume();
|
||||
bool IsEditorProperty(IProperty *pProp);
|
||||
|
||||
CScriptTemplate* Template() const;
|
||||
CMasterTemplate* MasterTemplate() const;
|
||||
|
|
|
@ -283,6 +283,13 @@ public:
|
|||
mAcceptedExtensions = rkExtensions;
|
||||
}
|
||||
|
||||
bool AcceptsExtension(const TString& rkExtension)
|
||||
{
|
||||
for (auto it = mAcceptedExtensions.begin(); it != mAcceptedExtensions.end(); it++)
|
||||
if (*it == rkExtension) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const TStringList& Extensions() const
|
||||
{
|
||||
return mAcceptedExtensions;
|
||||
|
@ -404,10 +411,16 @@ class CBitfieldTemplate : public TLongTemplate
|
|||
|
||||
public:
|
||||
CBitfieldTemplate(u32 ID, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, pParent) {}
|
||||
: TLongTemplate(ID, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
CBitfieldTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CStructTemplate *pParent = 0)
|
||||
: TLongTemplate(ID, rkName, CookPreference, pParent) {}
|
||||
: TLongTemplate(ID, rkName, CookPreference, pParent)
|
||||
{
|
||||
mDefaultValue.SetHexStringOutput(true);
|
||||
}
|
||||
|
||||
virtual EPropertyType Type() const { return eBitfieldProperty; }
|
||||
virtual bool CanHaveDefault() const { return true; }
|
||||
|
|
|
@ -28,6 +28,7 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
|
|||
CScriptTemplate *pTemp = Template();
|
||||
|
||||
// Determine transform
|
||||
mHasValidPosition = pTemp->HasPosition();
|
||||
mPosition = mpInstance->Position();
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
mScale = mpInstance->Scale();
|
||||
|
@ -41,36 +42,15 @@ CScriptNode::CScriptNode(CScene *pScene, CSceneNode *pParent, CScriptObject *pOb
|
|||
mpCollisionNode->SetCollision(mpInstance->GetCollision());
|
||||
|
||||
// Create preview volume node
|
||||
mHasValidPosition = pTemp->HasPosition();
|
||||
mpVolumePreviewNode = new CModelNode(pScene, this, nullptr);
|
||||
|
||||
if (pTemp->ScaleType() == CScriptTemplate::eScaleVolume)
|
||||
{
|
||||
EVolumeShape shape = mpInstance->VolumeShape();
|
||||
TResPtr<CModel> pVolumeModel = nullptr;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case eAxisAlignedBoxShape:
|
||||
case eBoxShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeBox.cmdl");
|
||||
break;
|
||||
|
||||
case eEllipsoidShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeSphere.cmdl");
|
||||
break;
|
||||
|
||||
case eCylinderShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeCylinder.cmdl");
|
||||
break;
|
||||
}
|
||||
|
||||
mHasVolumePreview = (pVolumeModel != nullptr);
|
||||
UpdatePreviewVolume();
|
||||
|
||||
if (mHasVolumePreview)
|
||||
{
|
||||
mpVolumePreviewNode = new CModelNode(pScene, this, pVolumeModel);
|
||||
mpVolumePreviewNode->SetInheritance(true, (shape != eAxisAlignedBoxShape), true);
|
||||
mpVolumePreviewNode->SetScale(mpInstance->VolumeScale());
|
||||
mpVolumePreviewNode->SetInheritance(true, (mpInstance->VolumeShape() != eAxisAlignedBoxShape), true);
|
||||
mpVolumePreviewNode->ForceAlphaEnabled(true);
|
||||
}
|
||||
}
|
||||
|
@ -395,6 +375,89 @@ CColor CScriptNode::TintColor(const SViewInfo &ViewInfo) const
|
|||
return BaseColor;
|
||||
}
|
||||
|
||||
void CScriptNode::PropertyModified(IProperty *pProp)
|
||||
{
|
||||
// Update volume
|
||||
if ( (pProp->Type() == eBoolProperty) || (pProp->Type() == eByteProperty) || (pProp->Type() == eShortProperty) ||
|
||||
(pProp->Type() == eLongProperty) || (pProp->Type() == eEnumProperty) )
|
||||
{
|
||||
mpInstance->EvaluateVolume();
|
||||
UpdatePreviewVolume();
|
||||
}
|
||||
|
||||
// Update resources
|
||||
if (pProp->Type() == eCharacterProperty)
|
||||
{
|
||||
mpInstance->EvaluateDisplayModel();
|
||||
mpActiveModel = mpInstance->GetDisplayModel();
|
||||
}
|
||||
else if (pProp->Type() == eFileProperty)
|
||||
{
|
||||
CFileTemplate *pFile = static_cast<CFileTemplate*>(pProp->Template());
|
||||
|
||||
if (pFile->AcceptsExtension("CMDL") || pFile->AcceptsExtension("ANCS") || pFile->AcceptsExtension("CHAR"))
|
||||
{
|
||||
mpInstance->EvaluateDisplayModel();
|
||||
mpActiveModel = mpInstance->GetDisplayModel();
|
||||
}
|
||||
else if (pFile->AcceptsExtension("TXTR"))
|
||||
{
|
||||
mpInstance->EvaluateBillboard();
|
||||
mpBillboard = mpInstance->GetBillboard();
|
||||
}
|
||||
else if (pFile->AcceptsExtension("DCLN"))
|
||||
{
|
||||
mpInstance->EvaluateCollisionModel();
|
||||
mpCollisionNode->SetCollision(mpInstance->GetCollision());
|
||||
}
|
||||
}
|
||||
|
||||
// Update other editor properties
|
||||
if (mpInstance->IsEditorProperty(pProp))
|
||||
{
|
||||
SetName("[" + mpInstance->Template()->Name() + "] " + mpInstance->InstanceName());
|
||||
mPosition = mpInstance->Position();
|
||||
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
|
||||
mScale = mpInstance->Scale();
|
||||
MarkTransformChanged();
|
||||
|
||||
SetLightLayerIndex(mpLightParameters->LightLayerIndex());
|
||||
}
|
||||
|
||||
// Update script extra
|
||||
if (mpExtra) mpExtra->PropertyModified(pProp);
|
||||
}
|
||||
|
||||
void CScriptNode::UpdatePreviewVolume()
|
||||
{
|
||||
EVolumeShape Shape = mpInstance->VolumeShape();
|
||||
TResPtr<CModel> pVolumeModel = nullptr;
|
||||
|
||||
switch (Shape)
|
||||
{
|
||||
case eAxisAlignedBoxShape:
|
||||
case eBoxShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeBox.cmdl");
|
||||
break;
|
||||
|
||||
case eEllipsoidShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeSphere.cmdl");
|
||||
break;
|
||||
|
||||
case eCylinderShape:
|
||||
pVolumeModel = gResCache.GetResource("../resources/VolumeCylinder.cmdl");
|
||||
break;
|
||||
}
|
||||
|
||||
mHasVolumePreview = (pVolumeModel != nullptr);
|
||||
|
||||
if (mHasVolumePreview)
|
||||
{
|
||||
mpVolumePreviewNode->SetModel(pVolumeModel);
|
||||
mpVolumePreviewNode->SetScale(mpInstance->VolumeScale());
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptNode::GeneratePosition()
|
||||
{
|
||||
if (!mHasValidPosition)
|
||||
|
|
|
@ -38,6 +38,8 @@ public:
|
|||
CColor TintColor(const SViewInfo &ViewInfo) const;
|
||||
CColor WireframeColor() const;
|
||||
|
||||
void PropertyModified(IProperty *pProp);
|
||||
void UpdatePreviewVolume();
|
||||
void GeneratePosition();
|
||||
CScriptObject* Object() const;
|
||||
CScriptTemplate* Template() const;
|
||||
|
|
|
@ -42,15 +42,21 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
{
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
pOut = new QCheckBox(pParent);
|
||||
{
|
||||
QCheckBox *pCheckBox = new QCheckBox(pParent);
|
||||
CONNECT_RELAY(pCheckBox, rkIndex, toggled(bool))
|
||||
pOut = pCheckBox;
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT16_MIN);
|
||||
pSpinBox->setMaximum(INT16_MAX);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int))
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
@ -60,6 +66,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(INT32_MIN);
|
||||
pSpinBox->setMaximum(INT32_MAX);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int))
|
||||
pOut = pSpinBox;
|
||||
break;
|
||||
}
|
||||
|
@ -67,9 +74,9 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
case eFloatProperty:
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
pSpinBox->setSingleStep(0.1);
|
||||
pOut = pSpinBox;
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -82,17 +89,23 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
}
|
||||
|
||||
case eStringProperty:
|
||||
pOut = new QLineEdit(pParent);
|
||||
{
|
||||
QLineEdit *pLineEdit = new QLineEdit(pParent);
|
||||
CONNECT_RELAY(pLineEdit, rkIndex, textEdited(QString))
|
||||
pOut = pLineEdit;
|
||||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
{
|
||||
QComboBox *pComboBox = new QComboBox(pParent);
|
||||
|
||||
CEnumTemplate *pTemp = static_cast<CEnumTemplate*>(pProp->Template());
|
||||
|
||||
for (u32 iEnum = 0; iEnum < pTemp->NumEnumerators(); iEnum++)
|
||||
pComboBox->addItem(TO_QSTRING(pTemp->EnumeratorName(iEnum)));
|
||||
|
||||
CONNECT_RELAY(pComboBox, rkIndex, currentIndexChanged(int))
|
||||
pOut = pComboBox;
|
||||
break;
|
||||
}
|
||||
|
@ -102,12 +115,15 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
WResourceSelector *pSelector = new WResourceSelector(pParent);
|
||||
CFileTemplate *pTemp = static_cast<CFileTemplate*>(pProp->Template());
|
||||
pSelector->SetAllowedExtensions(pTemp->Extensions());
|
||||
|
||||
CONNECT_RELAY(pSelector, rkIndex, ResourceChanged(QString))
|
||||
pOut = pSelector;
|
||||
break;
|
||||
}
|
||||
|
||||
case eArrayProperty:
|
||||
{
|
||||
// No relay here, would prefer user to be sure of their change before it's reflected on the UI
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
pSpinBox->setMinimum(0);
|
||||
pSpinBox->setMaximum(999);
|
||||
|
@ -129,13 +145,16 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
|
||||
// Handle bitfield
|
||||
else if (pProp->Type() == eBitfieldProperty)
|
||||
pOut = new QCheckBox(pParent);
|
||||
{
|
||||
QCheckBox *pCheckBox = new QCheckBox(pParent);
|
||||
CONNECT_RELAY(pCheckBox, rkIndex, toggled(bool))
|
||||
pOut = pCheckBox;
|
||||
}
|
||||
|
||||
// Handle vector/color
|
||||
else
|
||||
{
|
||||
WDraggableSpinBox *pSpinBox = new WDraggableSpinBox(pParent);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
pSpinBox->setSingleStep(0.1);
|
||||
|
||||
// Limit to range of 0-1 on colors
|
||||
|
@ -147,6 +166,7 @@ QWidget* CPropertyDelegate::createEditor(QWidget *pParent, const QStyleOptionVie
|
|||
pSpinBox->setMaximum(1.0);
|
||||
}
|
||||
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(double))
|
||||
pOut = pSpinBox;
|
||||
}
|
||||
}
|
||||
|
@ -442,9 +462,12 @@ void CPropertyDelegate::setModelData(QWidget *pEditor, QAbstractItemModel* /*pMo
|
|||
pColor->Set(Value);
|
||||
}
|
||||
|
||||
mpModel->dataChanged(rkIndex.parent(), rkIndex.parent());
|
||||
QModelIndex ParentWidgetIndex = mpModel->index(rkIndex.parent().row(), 1, rkIndex.parent().parent());
|
||||
mpModel->dataChanged(ParentWidgetIndex, ParentWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
emit PropertyEdited(rkIndex, true);
|
||||
}
|
||||
|
||||
bool CPropertyDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
|
||||
|
@ -483,12 +506,14 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
|
|||
else
|
||||
pSelector->SetAllowedExtensions("CHAR");
|
||||
|
||||
CONNECT_RELAY(pSelector, rkIndex, ResourceChanged(QString))
|
||||
return pSelector;
|
||||
}
|
||||
|
||||
if (Type == eEnumProperty)
|
||||
{
|
||||
QComboBox *pComboBox = new QComboBox(pParent);
|
||||
|
||||
CAnimSet *pAnimSet = Params.AnimSet();
|
||||
|
||||
if (pAnimSet)
|
||||
|
@ -497,11 +522,16 @@ QWidget* CPropertyDelegate::CreateCharacterEditor(QWidget *pParent, const QModel
|
|||
pComboBox->addItem(TO_QSTRING(pAnimSet->getNodeName(iChr)));
|
||||
}
|
||||
|
||||
CONNECT_RELAY(pComboBox, rkIndex, currentIndexChanged(int))
|
||||
return pComboBox;
|
||||
}
|
||||
|
||||
if (Type == eLongProperty)
|
||||
return new WIntegralSpinBox(pParent);
|
||||
{
|
||||
WIntegralSpinBox *pSpinBox = new WIntegralSpinBox(pParent);
|
||||
CONNECT_RELAY(pSpinBox, rkIndex, valueChanged(int))
|
||||
return pSpinBox;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ public:
|
|||
|
||||
public slots:
|
||||
void WidgetEdited(QWidget *pWidget, const QModelIndex& rkIndex);
|
||||
|
||||
signals:
|
||||
void PropertyEdited(const QModelIndex& rkIndex, bool IsDone) const;
|
||||
};
|
||||
|
||||
#endif // CPROPERTYDELEGATE_H
|
||||
|
|
|
@ -16,6 +16,7 @@ CPropertyView::CPropertyView(QWidget *pParent)
|
|||
|
||||
connect(mpModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(SetPersistentEditors(QModelIndex)));
|
||||
connect(mpDelegate, SIGNAL(PropertyEdited(QModelIndex,bool)), this, SIGNAL(PropertyModified(QModelIndex,bool)));
|
||||
}
|
||||
|
||||
void CPropertyView::setModel(QAbstractItemModel *pModel)
|
||||
|
|
|
@ -18,8 +18,13 @@ public:
|
|||
bool event(QEvent *pEvent);
|
||||
void SetBaseStruct(CPropertyStruct *pStruct);
|
||||
|
||||
inline CPropertyModel* PropertyModel() const { return mpModel; }
|
||||
|
||||
public slots:
|
||||
void SetPersistentEditors(const QModelIndex& rkIndex);
|
||||
|
||||
signals:
|
||||
void PropertyModified(const QModelIndex& rkIndex, bool IsDone);
|
||||
};
|
||||
|
||||
#endif // CPROPERTYVIEW_H
|
||||
|
|
|
@ -16,6 +16,7 @@ WModifyTab::WModifyTab(QWidget *pParent) :
|
|||
ui->PropertyView->header()->resizeSection(0, PropViewWidth * 0.3);
|
||||
ui->PropertyView->header()->resizeSection(1, PropViewWidth * 0.3);
|
||||
ui->PropertyView->header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||
connect(ui->PropertyView, SIGNAL(PropertyModified(QModelIndex,bool)), this, SLOT(OnPropertyModified(QModelIndex,bool)));
|
||||
|
||||
mpInLinkModel = new CLinkModel(this);
|
||||
mpInLinkModel->SetConnectionType(CLinkModel::eIncoming);
|
||||
|
@ -75,6 +76,16 @@ void WModifyTab::ClearUI()
|
|||
ui->LightGroupBox->hide();
|
||||
}
|
||||
|
||||
void WModifyTab::OnPropertyModified(const QModelIndex& rkIndex, bool /*IsDone*/)
|
||||
{
|
||||
if (mpSelectedNode->NodeType() == eScriptNode)
|
||||
{
|
||||
CScriptNode *pNode = static_cast<CScriptNode*>(mpSelectedNode);
|
||||
IProperty *pProperty = ui->PropertyView->PropertyModel()->PropertyForIndex(rkIndex, true);
|
||||
pNode->PropertyModified(pProperty);
|
||||
}
|
||||
}
|
||||
|
||||
void WModifyTab::OnLinkTableDoubleClick(QModelIndex Index)
|
||||
{
|
||||
if (Index.column() == 0)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "CLinkModel.h"
|
||||
#include <Core/Scene/CSceneNode.h>
|
||||
#include <Core/Scene/CScriptNode.h>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QScrollArea>
|
||||
|
@ -33,6 +34,9 @@ public:
|
|||
void GenerateUI(QList<CSceneNode*>& Selection);
|
||||
void ClearUI();
|
||||
|
||||
public slots:
|
||||
void OnPropertyModified(const QModelIndex& rkIndex, bool IsDone);
|
||||
|
||||
private:
|
||||
Ui::WModifyTab *ui;
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<enumerators>
|
||||
<enumerator ID="0x482B22F1" name="Box"/>
|
||||
<enumerator ID="0x779DB545" name="Box"/>
|
||||
<enumerator ID="0x8392F5E4" name="Cylinder"/>
|
||||
<enumerator ID="0x39ED7B8E" name="Ellipsoid"/>
|
||||
<enumerator ID="0x8392F5E4" name="Ellipsoid"/>
|
||||
<enumerator ID="0x39ED7B8E" name="Cylinder"/>
|
||||
</enumerators>
|
||||
</enum>
|
||||
<struct ID="0x77A27411" template="Structs/TriggerInfo.xml"/>
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
<enum ID="0x09ECEE0C">
|
||||
<default>0x482B22F1</default>
|
||||
<enumerators>
|
||||
<enumerator ID="0x482B22F1" name="Unknown 1"/>
|
||||
<enumerator ID="0x779DB545" name="Unknown 2"/>
|
||||
<enumerator ID="0x8392F5E4" name="Unknown 3"/>
|
||||
<enumerator ID="0x39ED7B8E" name="Unknown 4"/>
|
||||
<enumerator ID="0x482B22F1" name="Box"/>
|
||||
<enumerator ID="0x779DB545" name="Box"/>
|
||||
<enumerator ID="0x8392F5E4" name="Ellipsoid"/>
|
||||
<enumerator ID="0x39ED7B8E" name="Cylinder"/>
|
||||
</enumerators>
|
||||
</enum>
|
||||
<struct ID="0x77A27411" template="Structs/TriggerInfo.xml"/>
|
||||
|
|
Loading…
Reference in New Issue