git mv Code\Sandbox\Editor Code/Editor
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyAnimationCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
|
||||
// Editor
|
||||
#include "Util/UIEnumerations.h"
|
||||
#include "IResourceSelectorHost.h"
|
||||
|
||||
AnimationPropertyCtrl::AnimationPropertyCtrl(QWidget *pParent)
|
||||
: QWidget(pParent)
|
||||
{
|
||||
m_animationLabel = new QLabel;
|
||||
|
||||
m_pApplyButton = new QToolButton;
|
||||
m_pApplyButton->setIcon(QIcon(":/reflectedPropertyCtrl/img/apply.png"));
|
||||
|
||||
m_pApplyButton->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
QHBoxLayout *pLayout = new QHBoxLayout(this);
|
||||
pLayout->setContentsMargins(0, 0, 0, 0);
|
||||
pLayout->addWidget(m_animationLabel, 1);
|
||||
pLayout->addWidget(m_pApplyButton);
|
||||
|
||||
connect(m_pApplyButton, &QAbstractButton::clicked, this, &AnimationPropertyCtrl::OnApplyClicked);
|
||||
};
|
||||
|
||||
AnimationPropertyCtrl::~AnimationPropertyCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void AnimationPropertyCtrl::SetValue(const CReflectedVarAnimation &animation)
|
||||
{
|
||||
m_animation = animation;
|
||||
m_animationLabel->setText(animation.m_animation.c_str());
|
||||
}
|
||||
|
||||
CReflectedVarAnimation AnimationPropertyCtrl::value() const
|
||||
{
|
||||
return m_animation;
|
||||
}
|
||||
|
||||
void AnimationPropertyCtrl::OnApplyClicked()
|
||||
{
|
||||
QStringList cSelectedAnimations;
|
||||
size_t nTotalAnimations(0);
|
||||
size_t nCurrentAnimation(0);
|
||||
|
||||
QString combinedString = GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("animation");
|
||||
SplitString(combinedString, cSelectedAnimations, ',');
|
||||
|
||||
nTotalAnimations = cSelectedAnimations.size();
|
||||
for (nCurrentAnimation = 0; nCurrentAnimation < nTotalAnimations; ++nCurrentAnimation)
|
||||
{
|
||||
QString& rstrCurrentAnimAction = cSelectedAnimations[nCurrentAnimation];
|
||||
if (!rstrCurrentAnimAction.isEmpty())
|
||||
{
|
||||
m_animation.m_animation = rstrCurrentAnimAction.toUtf8().data();
|
||||
m_animationLabel->setText(m_animation.m_animation.c_str());
|
||||
emit ValueChanged(m_animation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* AnimationPropertyCtrl::GetFirstInTabOrder()
|
||||
{
|
||||
return m_pApplyButton;
|
||||
}
|
||||
QWidget* AnimationPropertyCtrl::GetLastInTabOrder()
|
||||
{
|
||||
return m_pApplyButton;
|
||||
}
|
||||
|
||||
void AnimationPropertyCtrl::UpdateTabOrder()
|
||||
{
|
||||
setTabOrder(m_pApplyButton, m_pApplyButton);
|
||||
}
|
||||
|
||||
|
||||
QWidget* AnimationPropertyWidgetHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
AnimationPropertyCtrl* newCtrl = aznew AnimationPropertyCtrl(pParent);
|
||||
connect(newCtrl, &AnimationPropertyCtrl::ValueChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
|
||||
void AnimationPropertyWidgetHandler::ConsumeAttribute(AnimationPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
Q_UNUSED(GUI);
|
||||
Q_UNUSED(attrib);
|
||||
Q_UNUSED(attrValue);
|
||||
Q_UNUSED(debugName);
|
||||
}
|
||||
|
||||
void AnimationPropertyWidgetHandler::WriteGUIValuesIntoProperty(size_t index, AnimationPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarAnimation val = GUI->value();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
|
||||
bool AnimationPropertyWidgetHandler::ReadValuesIntoGUI(size_t index, AnimationPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarAnimation val = instance;
|
||||
GUI->SetValue(val);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyAnimationCtrl.cpp>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#endif
|
||||
|
||||
class QToolButton;
|
||||
class QLabel;
|
||||
class QHBoxLayout;
|
||||
|
||||
class AnimationPropertyCtrl
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnimationPropertyCtrl, AZ::SystemAllocator, 0);
|
||||
|
||||
AnimationPropertyCtrl(QWidget* pParent = nullptr);
|
||||
virtual ~AnimationPropertyCtrl();
|
||||
|
||||
CReflectedVarAnimation value() const;
|
||||
|
||||
QWidget* GetFirstInTabOrder();
|
||||
QWidget* GetLastInTabOrder();
|
||||
void UpdateTabOrder();
|
||||
|
||||
signals:
|
||||
void ValueChanged(CReflectedVarAnimation value);
|
||||
|
||||
public slots:
|
||||
void SetValue(const CReflectedVarAnimation& animation);
|
||||
|
||||
protected slots:
|
||||
void OnApplyClicked();
|
||||
|
||||
private:
|
||||
QToolButton* m_pApplyButton;
|
||||
QLabel* m_animationLabel;
|
||||
|
||||
CReflectedVarAnimation m_animation;
|
||||
};
|
||||
|
||||
class AnimationPropertyWidgetHandler
|
||||
: QObject
|
||||
, public AzToolsFramework::PropertyHandler < CReflectedVarAnimation, AnimationPropertyCtrl >
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(AnimationPropertyWidgetHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Animation", 0x8d5284dc); }
|
||||
virtual bool IsDefaultHandler() const override { return true; }
|
||||
virtual QWidget* GetFirstInTabOrder(AnimationPropertyCtrl* widget) override { return widget->GetFirstInTabOrder(); }
|
||||
virtual QWidget* GetLastInTabOrder(AnimationPropertyCtrl* widget) override { return widget->GetLastInTabOrder(); }
|
||||
virtual void UpdateWidgetInternalTabbing(AnimationPropertyCtrl* widget) override { widget->UpdateTabOrder(); }
|
||||
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override;
|
||||
virtual void ConsumeAttribute(AnimationPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, AnimationPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
virtual bool ReadValuesIntoGUI(size_t index, AnimationPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYANIMATIONCTRL_H
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
// Editor
|
||||
#include "PropertyCtrl.h"
|
||||
#include "PropertyAnimationCtrl.h"
|
||||
#include "PropertyResourceCtrl.h"
|
||||
#include "PropertyGenericCtrl.h"
|
||||
#include "PropertyMiscCtrl.h"
|
||||
#include "PropertyMotionCtrl.h"
|
||||
|
||||
void RegisterReflectedVarHandlers()
|
||||
{
|
||||
static bool registered = false;
|
||||
if (!registered)
|
||||
{
|
||||
registered = true;
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LightAnimationPropertyHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew UserPopupWidgetHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ColorCurveHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FloatCurveHandler());
|
||||
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew MotionPropertyWidgetHandler());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYCTRL_H
|
||||
#pragma once
|
||||
|
||||
void RegisterReflectedVarHandlers();
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYCTRL_H
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyGenericCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QMessageBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QStringListModel>
|
||||
#include <QToolButton>
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/ILocalizationManager.h>
|
||||
|
||||
// Editor
|
||||
#include "SelectLightAnimationDialog.h"
|
||||
#include "SelectSequenceDialog.h"
|
||||
#include "SelectEAXPresetDlg.h"
|
||||
#include "QtViewPaneManager.h"
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
#include <QtWidgets/QListView>
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
|
||||
GenericPopupPropertyEditor::GenericPopupPropertyEditor(QWidget *pParent, bool showTwoButtons)
|
||||
:QWidget(pParent)
|
||||
{
|
||||
m_valueLabel = new QLabel;
|
||||
|
||||
QToolButton *mainButton = new QToolButton;
|
||||
mainButton->setAutoRaise(true);
|
||||
mainButton->setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/browse-edit.svg")));
|
||||
connect(mainButton, &QToolButton::clicked, this, &GenericPopupPropertyEditor::onEditClicked);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->addWidget(m_valueLabel, 1);
|
||||
mainLayout->addWidget(mainButton);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
if (showTwoButtons)
|
||||
{
|
||||
QToolButton *button2 = new QToolButton;
|
||||
button2->setAutoRaise(true);
|
||||
button2->setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/more.svg")));
|
||||
connect(button2, &QToolButton::clicked, this, &GenericPopupPropertyEditor::onButton2Clicked);
|
||||
mainLayout->insertWidget(1, button2);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericPopupPropertyEditor::SetValue(const QString &value, bool notify)
|
||||
{
|
||||
if (m_value != value)
|
||||
{
|
||||
m_value = value;
|
||||
m_valueLabel->setText(m_value);
|
||||
if (notify)
|
||||
emit ValueChanged(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericPopupPropertyEditor::SetPropertyType(PropertyType type)
|
||||
{
|
||||
m_propertyType = type;
|
||||
}
|
||||
|
||||
void ReverbPresetPropertyEditor::onEditClicked()
|
||||
{
|
||||
CSelectEAXPresetDlg PresetDlg(this);
|
||||
PresetDlg.SetCurrPreset(GetValue());
|
||||
if (PresetDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
SetValue(PresetDlg.GetCurrPreset());
|
||||
}
|
||||
}
|
||||
|
||||
void SequencePropertyEditor::onEditClicked()
|
||||
{
|
||||
CSelectSequenceDialog gtDlg(this);
|
||||
gtDlg.PreSelectItem(GetValue());
|
||||
if (gtDlg.exec() == QDialog::Accepted)
|
||||
SetValue(gtDlg.GetSelectedItem());
|
||||
}
|
||||
|
||||
void SequenceIdPropertyEditor::onEditClicked()
|
||||
{
|
||||
CSelectSequenceDialog gtDlg;
|
||||
uint32 id = GetValue().toUInt();
|
||||
IAnimSequence *pSeq = GetIEditor()->GetMovieSystem()->FindSequenceById(id);
|
||||
if (pSeq)
|
||||
gtDlg.PreSelectItem(pSeq->GetName());
|
||||
if (gtDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
pSeq = GetIEditor()->GetMovieSystem()->FindLegacySequenceByName(gtDlg.GetSelectedItem().toUtf8().data());
|
||||
assert(pSeq);
|
||||
if (pSeq->GetId() > 0)
|
||||
{
|
||||
// This sequence is a new one with a valid ID.
|
||||
SetValue(QString::number(pSeq->GetId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// This sequence is an old one without an ID.
|
||||
QMessageBox::warning(this, tr("Old Sequence"), tr("This is an old sequence without an ID.\nSo it cannot be used with the new ID-based linking."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStringPropertyEditor::onEditClicked()
|
||||
{
|
||||
std::vector<IVariable::IGetCustomItems::SItem> items;
|
||||
ILocalizationManager* pMgr = gEnv->pSystem->GetLocalizationManager();
|
||||
if (!pMgr)
|
||||
return;
|
||||
int nCount = pMgr->GetLocalizedStringCount();
|
||||
if (nCount <= 0)
|
||||
return;
|
||||
items.reserve(nCount);
|
||||
IVariable::IGetCustomItems::SItem item;
|
||||
SLocalizedInfoEditor sInfo;
|
||||
for (int i = 0; i < nCount; ++i)
|
||||
{
|
||||
if (pMgr->GetLocalizedInfoByIndex(i, sInfo))
|
||||
{
|
||||
item.desc = tr("English Text:\r\n");
|
||||
item.desc += QString::fromWCharArray(Unicode::Convert<wstring>(sInfo.sUtf8TranslatedText).c_str());
|
||||
item.name = sInfo.sKey;
|
||||
items.push_back(item);
|
||||
}
|
||||
}
|
||||
CGenericSelectItemDialog gtDlg;
|
||||
const bool bUseTree = true;
|
||||
if (bUseTree)
|
||||
{
|
||||
gtDlg.SetMode(CGenericSelectItemDialog::eMODE_TREE);
|
||||
gtDlg.SetTreeSeparator("/");
|
||||
}
|
||||
gtDlg.SetItems(items);
|
||||
gtDlg.setWindowTitle(tr("Choose Localized String"));
|
||||
QString preselect = GetValue();
|
||||
if (!preselect.isEmpty() && preselect.at(0) == '@')
|
||||
preselect = preselect.mid(1);
|
||||
gtDlg.PreSelectItem(preselect);
|
||||
if (gtDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
preselect = "@";
|
||||
preselect += gtDlg.GetSelectedItem();
|
||||
SetValue(preselect);
|
||||
}
|
||||
}
|
||||
|
||||
void LightAnimationPropertyEditor::onEditClicked()
|
||||
{
|
||||
// First, check if there is any light animation defined.
|
||||
bool bLightAnimationExists = false;
|
||||
IMovieSystem *pMovieSystem = GetIEditor()->GetMovieSystem();
|
||||
for (int i = 0; i < pMovieSystem->GetNumSequences(); ++i)
|
||||
{
|
||||
IAnimSequence *pSequence = pMovieSystem->GetSequence(i);
|
||||
if (pSequence->GetFlags() & IAnimSequence::eSeqFlags_LightAnimationSet)
|
||||
{
|
||||
bLightAnimationExists = pSequence->GetNodeCount() > 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bLightAnimationExists) // If exists, show the selection dialog.
|
||||
{
|
||||
CSelectLightAnimationDialog dlg;
|
||||
dlg.PreSelectItem(GetValue());
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
SetValue(dlg.GetSelectedItem());
|
||||
}
|
||||
else // If not, remind the user of creating one in TrackView.
|
||||
{
|
||||
QMessageBox::warning(this, tr("No Available Animation"), tr("There is no available light animation.\nPlease create one in TrackView, first."));
|
||||
}
|
||||
}
|
||||
|
||||
ListEditWidget::ListEditWidget(QWidget *pParent /*= nullptr*/)
|
||||
:QWidget(pParent)
|
||||
{
|
||||
m_valueEdit = new QLineEdit;
|
||||
|
||||
m_model = new QStringListModel(this);
|
||||
|
||||
m_listView = new QListView;
|
||||
m_listView->setModel(m_model);
|
||||
m_listView->setMaximumHeight(50);
|
||||
m_listView->setVisible(false);
|
||||
|
||||
QToolButton *expandButton = new QToolButton();
|
||||
expandButton->setCheckable(true);
|
||||
expandButton->setText("+");
|
||||
|
||||
QToolButton *editButton = new QToolButton();
|
||||
editButton->setText("..");
|
||||
|
||||
connect(editButton, &QAbstractButton::clicked, this, &ListEditWidget::OnEditClicked);
|
||||
connect(expandButton, &QAbstractButton::toggled, m_listView, &QWidget::setVisible);
|
||||
|
||||
connect(m_model, &QAbstractItemModel::dataChanged, this, &ListEditWidget::OnModelDataChange);
|
||||
connect(m_valueEdit, &QLineEdit::editingFinished, this, [this](){SetValue(m_valueEdit->text(), true); } );
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
QHBoxLayout *topLayout = new QHBoxLayout;
|
||||
topLayout->addWidget(expandButton);
|
||||
topLayout->addWidget(m_valueEdit,1);
|
||||
topLayout->addWidget(editButton);
|
||||
|
||||
mainLayout->addLayout(topLayout);
|
||||
mainLayout->addWidget(m_listView,1);
|
||||
mainLayout->setContentsMargins(1,1,1,1);
|
||||
}
|
||||
|
||||
void ListEditWidget::SetValue(const QString &value, bool notify /*= true*/)
|
||||
{
|
||||
if (m_value != value)
|
||||
{
|
||||
m_value = value;
|
||||
m_valueEdit->setText(value);
|
||||
QStringList list = m_value.split(",", Qt::SkipEmptyParts);
|
||||
m_model->setStringList(list);
|
||||
|
||||
if (notify)
|
||||
emit ValueChanged(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ListEditWidget::OnModelDataChange()
|
||||
{
|
||||
m_value = m_model->stringList().join(",");
|
||||
m_valueEdit->setText(m_value);
|
||||
emit ValueChanged(m_value);
|
||||
}
|
||||
|
||||
|
||||
QWidget* ListEditWidget::GetFirstInTabOrder()
|
||||
{
|
||||
return m_valueEdit;
|
||||
}
|
||||
|
||||
QWidget* ListEditWidget::GetLastInTabOrder()
|
||||
{
|
||||
return m_listView;
|
||||
}
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyGenericCtrl.cpp>
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYGENERICCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYGENERICCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include "Util/VariablePropertyType.h"
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
class QStringListModel;
|
||||
class QListView;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
|
||||
class GenericPopupPropertyEditor
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(GenericPopupPropertyEditor, AZ::SystemAllocator, 0);
|
||||
GenericPopupPropertyEditor(QWidget* pParent = nullptr, bool showTwoButtons = false);
|
||||
|
||||
void SetValue(const QString& value, bool notify = true);
|
||||
QString GetValue() const { return m_value; }
|
||||
void SetPropertyType(PropertyType type);
|
||||
PropertyType GetPropertyType() const { return m_propertyType; }
|
||||
|
||||
//override in derived classes to show appropriate editor
|
||||
virtual void onEditClicked() {};
|
||||
virtual void onButton2Clicked() {};
|
||||
|
||||
signals:
|
||||
void ValueChanged(const QString& value);
|
||||
|
||||
private:
|
||||
QLabel* m_valueLabel;
|
||||
PropertyType m_propertyType;
|
||||
QString m_value;
|
||||
};
|
||||
|
||||
template <class T, AZ::u32 CRC>
|
||||
class GenericPopupWidgetHandler
|
||||
: public QObject
|
||||
, public AzToolsFramework::PropertyHandler < CReflectedVarGenericProperty, GenericPopupPropertyEditor >
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(GenericPopupWidgetHandler, AZ::SystemAllocator, 0);
|
||||
virtual bool IsDefaultHandler() const override { return false; }
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override { return CRC; }
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override
|
||||
{
|
||||
GenericPopupPropertyEditor* newCtrl = aznew T(pParent);
|
||||
connect(newCtrl, &GenericPopupPropertyEditor::ValueChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
virtual void ConsumeAttribute(GenericPopupPropertyEditor* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override
|
||||
{
|
||||
Q_UNUSED(GUI);
|
||||
Q_UNUSED(attrib);
|
||||
Q_UNUSED(attrValue);
|
||||
Q_UNUSED(debugName);
|
||||
}
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, GenericPopupPropertyEditor* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarGenericProperty val = instance;
|
||||
val.m_propertyType = GUI->GetPropertyType();
|
||||
val.m_value = GUI->GetValue().toUtf8().data();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
virtual bool ReadValuesIntoGUI(size_t index, GenericPopupPropertyEditor* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarGenericProperty val = instance;
|
||||
GUI->SetPropertyType(val.m_propertyType);
|
||||
GUI->SetValue(val.m_value.c_str(), false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class ReverbPresetPropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
ReverbPresetPropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
class MissionObjPropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
MissionObjPropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
class SequencePropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
SequencePropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
class SequenceIdPropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
SequenceIdPropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
class LocalStringPropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
LocalStringPropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
class LightAnimationPropertyEditor
|
||||
: public GenericPopupPropertyEditor
|
||||
{
|
||||
public:
|
||||
LightAnimationPropertyEditor(QWidget* pParent = nullptr)
|
||||
: GenericPopupPropertyEditor(pParent){}
|
||||
void onEditClicked() override;
|
||||
};
|
||||
|
||||
|
||||
// AZ_CRC changed recently - it used to be evaluated by the preprocessor to AZ::u32(value); now it evaluates to Az::Crc32, and can't be used as a const template parameter
|
||||
// So we use our own
|
||||
#define CONST_AZ_CRC(name, value) AZ::u32(value)
|
||||
|
||||
using ReverbPresetPropertyHandler = GenericPopupWidgetHandler<ReverbPresetPropertyEditor, CONST_AZ_CRC("ePropertyReverbPreset", 0x51469f38)>;
|
||||
using MissionObjPropertyHandler = GenericPopupWidgetHandler<MissionObjPropertyEditor, CONST_AZ_CRC("ePropertyMissionObj", 0x4a2d0dc8)>;
|
||||
using SequencePropertyHandler = GenericPopupWidgetHandler<SequencePropertyEditor, CONST_AZ_CRC("ePropertySequence", 0xdd1c7d44)>;
|
||||
using SequenceIdPropertyHandler = GenericPopupWidgetHandler<SequenceIdPropertyEditor, CONST_AZ_CRC("ePropertySequenceId", 0x05983dcc)>;
|
||||
using LocalStringPropertyHandler = GenericPopupWidgetHandler<LocalStringPropertyEditor, CONST_AZ_CRC("ePropertyLocalString", 0x0cd9609a)>;
|
||||
using LightAnimationPropertyHandler = GenericPopupWidgetHandler<LightAnimationPropertyEditor, CONST_AZ_CRC("ePropertyLightAnimation", 0x277097da)>;
|
||||
|
||||
class ListEditWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ListEditWidget, AZ::SystemAllocator, 0);
|
||||
ListEditWidget(QWidget *pParent = nullptr);
|
||||
|
||||
void SetValue(const QString &value, bool notify = true);
|
||||
QString GetValue() const { return m_value; }
|
||||
|
||||
QWidget* GetFirstInTabOrder();
|
||||
QWidget* GetLastInTabOrder();
|
||||
|
||||
signals:
|
||||
void ValueChanged(const QString &value);
|
||||
|
||||
private:
|
||||
void OnModelDataChange();
|
||||
virtual void OnEditClicked() {};
|
||||
|
||||
protected:
|
||||
QLineEdit *m_valueEdit;
|
||||
QString m_value;
|
||||
QListView *m_listView;
|
||||
QStringListModel *m_model;
|
||||
};
|
||||
|
||||
template <class T, AZ::u32 CRC>
|
||||
class ListEditWidgetHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarGenericProperty, ListEditWidget >
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ListEditWidgetHandler, AZ::SystemAllocator, 0);
|
||||
virtual bool IsDefaultHandler() const override { return false; }
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override { return CRC; }
|
||||
virtual QWidget* CreateGUI(QWidget *pParent) override
|
||||
{
|
||||
ListEditWidget* newCtrl = aznew T(pParent);
|
||||
connect(newCtrl, &ListEditWidget::ValueChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
virtual void ConsumeAttribute(ListEditWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override {
|
||||
Q_UNUSED(GUI); Q_UNUSED(attrib); Q_UNUSED(attrValue); Q_UNUSED(debugName);
|
||||
}
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, ListEditWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarGenericProperty val = instance;
|
||||
val.m_value = GUI->GetValue().toUtf8().data();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
virtual bool ReadValuesIntoGUI(size_t index, ListEditWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarGenericProperty val = instance;
|
||||
GUI->SetValue(val.m_value.c_str(), false);
|
||||
return false;
|
||||
}
|
||||
QWidget* GetFirstInTabOrder(ListEditWidget* widget) override { return widget->GetFirstInTabOrder(); }
|
||||
QWidget* GetLastInTabOrder(ListEditWidget* widget) override {return widget->GetLastInTabOrder(); }
|
||||
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYGENERICCTRL_H
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyMiscCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QtWidgets/QToolButton>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtUtilWin.h>
|
||||
|
||||
// Editor
|
||||
#include "GenericSelectItemDialog.h"
|
||||
#include "QtViewPaneManager.h"
|
||||
|
||||
|
||||
UserPropertyEditor::UserPropertyEditor(QWidget *pParent /*= nullptr*/)
|
||||
: QWidget(pParent)
|
||||
, m_canEdit(false)
|
||||
, m_useTree(false)
|
||||
{
|
||||
m_valueLabel = new QLabel;
|
||||
|
||||
QToolButton *mainButton = new QToolButton;
|
||||
mainButton->setText("..");
|
||||
connect(mainButton, &QToolButton::clicked, this, &UserPropertyEditor::onEditClicked);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->addWidget(m_valueLabel, 1);
|
||||
mainLayout->addWidget(mainButton);
|
||||
mainLayout->setContentsMargins(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void UserPropertyEditor::SetValue(const QString &value, bool notify /*= true*/)
|
||||
{
|
||||
if (m_value != value)
|
||||
{
|
||||
m_value = value;
|
||||
m_valueLabel->setText(m_value);
|
||||
if (notify)
|
||||
{
|
||||
emit ValueChanged(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UserPropertyEditor::SetData(bool canEdit, bool useTree, const QString &treeSeparator, const QString &dialogTitle, const std::vector<IVariable::IGetCustomItems::SItem>& items)
|
||||
{
|
||||
m_canEdit = canEdit;
|
||||
m_useTree = useTree;
|
||||
m_treeSeparator = treeSeparator;
|
||||
m_dialogTitle = dialogTitle;
|
||||
m_items = items;
|
||||
}
|
||||
|
||||
void UserPropertyEditor::onEditClicked()
|
||||
{
|
||||
// call the user supplied callback to fill-in items and get dialog title
|
||||
emit RefreshItems();
|
||||
if (m_canEdit) // if func didn't veto, show the dialog
|
||||
{
|
||||
CGenericSelectItemDialog gtDlg;
|
||||
if (m_useTree)
|
||||
{
|
||||
gtDlg.SetMode(CGenericSelectItemDialog::eMODE_TREE);
|
||||
if (!m_treeSeparator.isEmpty())
|
||||
{
|
||||
gtDlg.SetTreeSeparator(m_treeSeparator);
|
||||
}
|
||||
}
|
||||
gtDlg.SetItems(m_items);
|
||||
if (m_dialogTitle.isEmpty() == false)
|
||||
gtDlg.setWindowTitle(m_dialogTitle);
|
||||
gtDlg.PreSelectItem(GetValue());
|
||||
if (gtDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
QString selectedItemStr = gtDlg.GetSelectedItem();
|
||||
|
||||
if (selectedItemStr.isEmpty() == false)
|
||||
{
|
||||
SetValue(selectedItemStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QWidget* UserPopupWidgetHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
UserPropertyEditor* newCtrl = aznew UserPropertyEditor(pParent);
|
||||
connect(newCtrl, &UserPropertyEditor::ValueChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
void UserPopupWidgetHandler::ConsumeAttribute(UserPropertyEditor* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
Q_UNUSED(GUI);
|
||||
Q_UNUSED(attrib);
|
||||
Q_UNUSED(attrValue);
|
||||
Q_UNUSED(debugName);
|
||||
}
|
||||
|
||||
void UserPopupWidgetHandler::WriteGUIValuesIntoProperty(size_t index, UserPropertyEditor* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarUser val = instance;
|
||||
val.m_value = GUI->GetValue().toUtf8().data();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
|
||||
bool UserPopupWidgetHandler::ReadValuesIntoGUI(size_t index, UserPropertyEditor* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarUser val = instance;
|
||||
|
||||
assert(val.m_itemNames.size() == val.m_itemDescriptions.size());
|
||||
|
||||
std::vector<IVariable::IGetCustomItems::SItem> items(val.m_itemNames.size());
|
||||
int i = -1;
|
||||
std::generate(items.begin(), items.end(), [&val, &i]() { ++i; return IVariable::IGetCustomItems::SItem(val.m_itemNames[i].c_str(), val.m_itemDescriptions[i].c_str());});
|
||||
|
||||
GUI->SetData(val.m_enableEdit, val.m_useTree, val.m_treeSeparator.c_str(), val.m_dialogTitle.c_str(), items);
|
||||
GUI->SetValue(val.m_value.c_str(), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyMiscCtrl.cpp>
|
||||
|
||||
QWidget* FloatCurveHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
CSplineCtrl *cSpline = new CSplineCtrl(pParent);
|
||||
cSpline->SetUpdateCallback(AZStd::bind(&FloatCurveHandler::OnSplineChange, this, AZStd::placeholders::_1));
|
||||
cSpline->SetTimeRange(0, 1);
|
||||
cSpline->SetValueRange(0, 1);
|
||||
cSpline->SetGrid(12, 12);
|
||||
cSpline->setFixedHeight(52);
|
||||
return cSpline;
|
||||
}
|
||||
void FloatCurveHandler::OnSplineChange(CSplineCtrl*)
|
||||
{
|
||||
// EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, splineWidget);
|
||||
}
|
||||
|
||||
void FloatCurveHandler::ConsumeAttribute(CSplineCtrl *, AZ::u32, AzToolsFramework::PropertyAttributeReader*, const char*)
|
||||
{}
|
||||
|
||||
void FloatCurveHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, [[maybe_unused]] CSplineCtrl* GUI, [[maybe_unused]] property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
//nothing to do here. the spline itself will have it's new values.
|
||||
}
|
||||
|
||||
bool FloatCurveHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, CSplineCtrl* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
GUI->SetSpline(reinterpret_cast<ISplineInterpolator*>(instance.m_spline));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QWidget* ColorCurveHandler::CreateGUI(QWidget *pParent)
|
||||
{
|
||||
CColorGradientCtrl* gradientCtrl = new CColorGradientCtrl(pParent);
|
||||
//connect(gradientCtrl, &CColorGradientCtrl::change, [gradientCtrl]()
|
||||
//{
|
||||
// EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, gradientCtrl);
|
||||
//});
|
||||
gradientCtrl->SetTimeRange(0, 1);
|
||||
gradientCtrl->setFixedHeight(36);
|
||||
return gradientCtrl;
|
||||
|
||||
}
|
||||
|
||||
void ColorCurveHandler::ConsumeAttribute(CColorGradientCtrl*, AZ::u32, AzToolsFramework::PropertyAttributeReader*, const char*)
|
||||
{}
|
||||
|
||||
void ColorCurveHandler::WriteGUIValuesIntoProperty([[maybe_unused]] size_t index, [[maybe_unused]] CColorGradientCtrl* GUI, [[maybe_unused]] property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{}
|
||||
|
||||
bool ColorCurveHandler::ReadValuesIntoGUI([[maybe_unused]] size_t index, CColorGradientCtrl* GUI, const property_t& instance, [[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
GUI->SetSpline(reinterpret_cast<ISplineInterpolator*>(instance.m_spline));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include "Util/VariablePropertyType.h"
|
||||
#include "Controls/ColorGradientCtrl.h"
|
||||
#include "Controls/SplineCtrl.h"
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
|
||||
class UserPropertyEditor : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(UserPropertyEditor, AZ::SystemAllocator, 0);
|
||||
UserPropertyEditor(QWidget *pParent = nullptr);
|
||||
|
||||
void SetValue(const QString &value, bool notify = true);
|
||||
QString GetValue() const { return m_value; }
|
||||
|
||||
void SetData(bool canEdit, bool useTree, const QString &treeSeparator, const QString &dialogTitle, const std::vector<IVariable::IGetCustomItems::SItem>& items);
|
||||
void onEditClicked();
|
||||
|
||||
signals:
|
||||
void ValueChanged(const QString &value);
|
||||
void RefreshItems();
|
||||
|
||||
private:
|
||||
QLabel *m_valueLabel;
|
||||
QString m_value;
|
||||
|
||||
bool m_canEdit;
|
||||
bool m_useTree;
|
||||
QString m_treeSeparator;
|
||||
QString m_dialogTitle;
|
||||
std::vector<IVariable::IGetCustomItems::SItem> m_items;
|
||||
};
|
||||
|
||||
class UserPopupWidgetHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarUser, UserPropertyEditor>
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(UserPopupWidgetHandler, AZ::SystemAllocator, 0);
|
||||
bool IsDefaultHandler() const override { return false; }
|
||||
QWidget* CreateGUI(QWidget *pParent) override;
|
||||
|
||||
AZ::u32 GetHandlerName(void) const override {return AZ_CRC("ePropertyUser", 0x65b972c0); }
|
||||
void ConsumeAttribute(UserPropertyEditor* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
void WriteGUIValuesIntoProperty(size_t index, UserPropertyEditor* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
bool ReadValuesIntoGUI(size_t index, UserPropertyEditor* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
|
||||
};
|
||||
|
||||
class FloatCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CSplineCtrl>
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FloatCurveHandler, AZ::SystemAllocator, 0);
|
||||
bool IsDefaultHandler() const override { return false; }
|
||||
QWidget* CreateGUI(QWidget *pParent) override;
|
||||
|
||||
AZ::u32 GetHandlerName(void) const override { return AZ_CRC("ePropertyFloatCurve", 0x7440ccce); }
|
||||
|
||||
void ConsumeAttribute(CSplineCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
void WriteGUIValuesIntoProperty(size_t index, CSplineCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
bool ReadValuesIntoGUI(size_t index, CSplineCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
|
||||
void OnSplineChange(CSplineCtrl*);
|
||||
};
|
||||
|
||||
class ColorCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CColorGradientCtrl>
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ColorCurveHandler, AZ::SystemAllocator, 0);
|
||||
bool IsDefaultHandler() const override { return false; }
|
||||
QWidget* CreateGUI(QWidget *pParent) override;
|
||||
|
||||
AZ::u32 GetHandlerName(void) const override { return AZ_CRC("ePropertyColorCurve", 0xa30da4ec); }
|
||||
|
||||
void ConsumeAttribute(CColorGradientCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
void WriteGUIValuesIntoProperty(size_t index, CColorGradientCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
bool ReadValuesIntoGUI(size_t index, CColorGradientCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyMotionCtrl.h"
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
|
||||
QWidget* MotionPropertyWidgetHandler::CreateGUI(QWidget* pParent)
|
||||
{
|
||||
AzToolsFramework::PropertyAssetCtrl* newCtrl = aznew AzToolsFramework::PropertyAssetCtrl(pParent);
|
||||
connect(
|
||||
newCtrl, &AzToolsFramework::PropertyAssetCtrl::OnAssetIDChanged, this, [newCtrl]([[maybe_unused]] AZ::Data::AssetId newAssetId) {
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
|
||||
&AzToolsFramework::PropertyEditorGUIMessages::Bus::Handler::OnEditingFinished, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
void MotionPropertyWidgetHandler::ConsumeAttribute(
|
||||
[[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, [[maybe_unused]] AZ::u32 attrib,
|
||||
[[maybe_unused]] AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
|
||||
{
|
||||
}
|
||||
|
||||
void MotionPropertyWidgetHandler::WriteGUIValuesIntoProperty(
|
||||
[[maybe_unused]] size_t index, [[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, property_t& instance,
|
||||
[[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
CReflectedVarMotion val;
|
||||
val.m_motion = GUI->GetCurrentAssetHint();
|
||||
val.m_assetId = GUI->GetSelectedAssetID();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
|
||||
bool MotionPropertyWidgetHandler::ReadValuesIntoGUI(
|
||||
[[maybe_unused]] size_t index, [[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, const property_t& instance,
|
||||
[[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
static const AZ::Data::AssetType emotionFXMotionAssetType(
|
||||
"{00494B8E-7578-4BA2-8B28-272E90680787}"); // from MotionAsset.h in EMotionFX Gem
|
||||
|
||||
GUI->blockSignals(true);
|
||||
GUI->SetSelectedAssetID(instance.m_assetId);
|
||||
GUI->SetCurrentAssetType(emotionFXMotionAssetType);
|
||||
GUI->blockSignals(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyMotionCtrl.cpp>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ReflectedVar.h"
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
#endif
|
||||
|
||||
class MotionPropertyWidgetHandler : QObject,
|
||||
public AzToolsFramework::PropertyHandler<CReflectedVarMotion, AzToolsFramework::PropertyAssetCtrl>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MotionPropertyWidgetHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override
|
||||
{
|
||||
return AZ_CRC("Motion", 0xf5fea1e8);
|
||||
}
|
||||
|
||||
virtual bool IsDefaultHandler() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual QWidget* GetFirstInTabOrder(AzToolsFramework::PropertyAssetCtrl* widget) override
|
||||
{
|
||||
return widget->GetFirstInTabOrder();
|
||||
}
|
||||
|
||||
virtual QWidget* GetLastInTabOrder(AzToolsFramework::PropertyAssetCtrl* widget) override
|
||||
{
|
||||
return widget->GetLastInTabOrder();
|
||||
}
|
||||
|
||||
virtual void UpdateWidgetInternalTabbing(AzToolsFramework::PropertyAssetCtrl* widget) override
|
||||
{
|
||||
widget->UpdateTabOrder();
|
||||
}
|
||||
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override;
|
||||
virtual void ConsumeAttribute(
|
||||
AzToolsFramework::PropertyAssetCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue,
|
||||
const char* debugName) override;
|
||||
virtual void WriteGUIValuesIntoProperty(
|
||||
size_t index, AzToolsFramework::PropertyAssetCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
virtual bool ReadValuesIntoGUI(
|
||||
size_t index, AzToolsFramework::PropertyAssetCtrl* GUI, const property_t& instance,
|
||||
AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "PropertyResourceCtrl.h"
|
||||
|
||||
// Qt
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
|
||||
// Editor
|
||||
#include "IResourceSelectorHost.h"
|
||||
#include "Controls/QToolTipWidget.h"
|
||||
#include "Controls/BitmapToolTip.h"
|
||||
|
||||
|
||||
BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/)
|
||||
: QToolButton(parent)
|
||||
, m_propertyType(type)
|
||||
{
|
||||
setAutoRaise(true);
|
||||
setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/browse-edit.svg")));
|
||||
connect(this, &QAbstractButton::clicked, this, &BrowseButton::OnClicked);
|
||||
}
|
||||
|
||||
void BrowseButton::SetPathAndEmit(const QString& path)
|
||||
{
|
||||
//only emit if path changes, except for ePropertyGeomCache. Old property control
|
||||
if (path != m_path || m_propertyType == ePropertyGeomCache)
|
||||
{
|
||||
m_path = path;
|
||||
emit PathChanged(m_path);
|
||||
}
|
||||
}
|
||||
|
||||
class FileBrowseButton
|
||||
: public BrowseButton
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FileBrowseButton, AZ::SystemAllocator, 0);
|
||||
FileBrowseButton(PropertyType type, QWidget* pParent = nullptr)
|
||||
: BrowseButton(type, pParent)
|
||||
{
|
||||
setToolTip("Browse...");
|
||||
}
|
||||
|
||||
private:
|
||||
void OnClicked() override
|
||||
{
|
||||
QString tempValue("");
|
||||
QString ext("");
|
||||
if (m_path.isEmpty() == false)
|
||||
{
|
||||
if (Path::GetExt(m_path) == "")
|
||||
{
|
||||
tempValue = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
tempValue = m_path;
|
||||
}
|
||||
}
|
||||
|
||||
AssetSelectionModel selection;
|
||||
|
||||
if (m_propertyType == ePropertyTexture)
|
||||
{
|
||||
// Filters for texture.
|
||||
selection = AssetSelectionModel::AssetGroupSelection("Texture");
|
||||
}
|
||||
else if (m_propertyType == ePropertyModel)
|
||||
{
|
||||
// Filters for models.
|
||||
selection = AssetSelectionModel::AssetGroupSelection("Geometry");
|
||||
}
|
||||
else if (m_propertyType == ePropertyGeomCache)
|
||||
{
|
||||
// Filters for geom caches.
|
||||
selection = AssetSelectionModel::AssetTypeSelection("Geom Cache");
|
||||
}
|
||||
else if (m_propertyType == ePropertyFile)
|
||||
{
|
||||
// Filters for files.
|
||||
selection = AssetSelectionModel::AssetTypeSelection("File");
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
|
||||
if (selection.IsValid())
|
||||
{
|
||||
QString newPath = Path::FullPathToGamePath(selection.GetResult()->GetFullPath().c_str()).c_str();
|
||||
|
||||
switch (m_propertyType)
|
||||
{
|
||||
case ePropertyTexture:
|
||||
case ePropertyModel:
|
||||
newPath.replace("\\\\", "/");
|
||||
}
|
||||
switch (m_propertyType)
|
||||
{
|
||||
case ePropertyTexture:
|
||||
case ePropertyModel:
|
||||
case ePropertyFile:
|
||||
if (newPath.size() > MAX_PATH)
|
||||
{
|
||||
newPath.resize(MAX_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
SetPathAndEmit(newPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ResourceSelectorButton
|
||||
: public BrowseButton
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ResourceSelectorButton, AZ::SystemAllocator, 0);
|
||||
|
||||
ResourceSelectorButton(PropertyType type, QWidget* pParent = nullptr)
|
||||
: BrowseButton(type, pParent)
|
||||
{
|
||||
setToolTip(tr("Select resource"));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnClicked() override
|
||||
{
|
||||
SResourceSelectorContext x;
|
||||
x.parentWidget = this;
|
||||
x.typeName = Prop::GetPropertyTypeToResourceType(m_propertyType);
|
||||
QString newPath = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, m_path);
|
||||
SetPathAndEmit(newPath);
|
||||
}
|
||||
};
|
||||
|
||||
class TextureEditButton
|
||||
: public BrowseButton
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(TextureEditButton, AZ::SystemAllocator, 0);
|
||||
TextureEditButton(QWidget* pParent = nullptr)
|
||||
: BrowseButton(ePropertyTexture, pParent)
|
||||
{
|
||||
setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/open-in-internal-app.svg")));
|
||||
setToolTip(tr("Launch default editor"));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnClicked() override
|
||||
{
|
||||
CFileUtil::EditTextureFile(m_path.toUtf8().data(), true);
|
||||
}
|
||||
};
|
||||
|
||||
FileResourceSelectorWidget::FileResourceSelectorWidget(QWidget* pParent /*= nullptr*/)
|
||||
: QWidget(pParent)
|
||||
, m_propertyType(ePropertyInvalid)
|
||||
, m_tooltip(nullptr)
|
||||
{
|
||||
m_pathEdit = new QLineEdit;
|
||||
m_mainLayout = new QHBoxLayout(this);
|
||||
m_mainLayout->addWidget(m_pathEdit, 1);
|
||||
|
||||
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// KDAB just ported the MFC texture preview tooltip, but looks like Amazon added their own. Not sure which to use.
|
||||
// To switch to Amazon QToolTipWidget, remove FileResourceSelectorWidget::event and m_previewTooltip
|
||||
#ifdef USE_QTOOLTIPWIDGET
|
||||
m_tooltip = new QToolTipWidget(this);
|
||||
|
||||
installEventFilter(this);
|
||||
#endif
|
||||
connect(m_pathEdit, &QLineEdit::editingFinished, this, [this]() { OnPathChanged(m_pathEdit->text()); });
|
||||
}
|
||||
|
||||
bool FileResourceSelectorWidget::eventFilter([[maybe_unused]] QObject* obj, QEvent* event)
|
||||
{
|
||||
if (m_propertyType == ePropertyTexture)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip)
|
||||
{
|
||||
QHelpEvent* e = (QHelpEvent*)event;
|
||||
|
||||
m_tooltip->AddSpecialContent("TEXTURE", m_path);
|
||||
m_tooltip->TryDisplay(e->globalPos(), m_pathEdit, QToolTipWidget::ArrowDirection::ARROW_RIGHT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::Leave)
|
||||
{
|
||||
m_tooltip->hide();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidget::SetPropertyType(PropertyType type)
|
||||
{
|
||||
if (m_propertyType == type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//if the property type changed for some reason, delete all the existing widgets
|
||||
if (!m_buttons.isEmpty())
|
||||
{
|
||||
qDeleteAll(m_buttons.begin(), m_buttons.end());
|
||||
m_buttons.clear();
|
||||
}
|
||||
|
||||
m_previewToolTip.reset();
|
||||
m_propertyType = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ePropertyTexture:
|
||||
AddButton(new FileBrowseButton(type));
|
||||
AddButton(new TextureEditButton);
|
||||
m_previewToolTip.reset(new CBitmapToolTip);
|
||||
break;
|
||||
case ePropertyModel:
|
||||
case ePropertyGeomCache:
|
||||
case ePropertyAudioTrigger:
|
||||
case ePropertyAudioSwitch:
|
||||
case ePropertyAudioSwitchState:
|
||||
case ePropertyAudioRTPC:
|
||||
case ePropertyAudioEnvironment:
|
||||
case ePropertyAudioPreloadRequest:
|
||||
AddButton(new ResourceSelectorButton(type));
|
||||
break;
|
||||
case ePropertyFile:
|
||||
AddButton(new FileBrowseButton(type));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_mainLayout->invalidate();
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidget::AddButton(BrowseButton* button)
|
||||
{
|
||||
m_mainLayout->addWidget(button);
|
||||
m_buttons.push_back(button);
|
||||
connect(button, &BrowseButton::PathChanged, this, &FileResourceSelectorWidget::OnPathChanged);
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidget::OnPathChanged(const QString& path)
|
||||
{
|
||||
bool changed = SetPath(path);
|
||||
if (changed)
|
||||
{
|
||||
emit PathChanged(m_path);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileResourceSelectorWidget::SetPath(const QString& path)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
const QString newPath = path.toLower();
|
||||
if (m_path != newPath)
|
||||
{
|
||||
m_path = newPath;
|
||||
UpdateWidgets();
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
void FileResourceSelectorWidget::UpdateWidgets()
|
||||
{
|
||||
m_pathEdit->setText(m_path);
|
||||
|
||||
foreach(BrowseButton * button, m_buttons)
|
||||
{
|
||||
button->SetPath(m_path);
|
||||
}
|
||||
|
||||
if (m_previewToolTip)
|
||||
{
|
||||
m_previewToolTip->SetTool(this, rect());
|
||||
}
|
||||
}
|
||||
|
||||
QString FileResourceSelectorWidget::GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QWidget* FileResourceSelectorWidget::GetLastInTabOrder()
|
||||
{
|
||||
return m_buttons.empty() ? nullptr : m_buttons.last();
|
||||
}
|
||||
|
||||
QWidget* FileResourceSelectorWidget::GetFirstInTabOrder()
|
||||
{
|
||||
return m_buttons.empty() ? nullptr : m_buttons.first();
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidget::UpdateTabOrder()
|
||||
{
|
||||
if (m_buttons.count() >= 2)
|
||||
{
|
||||
for (int i = 0; i < m_buttons.count() - 1; ++i)
|
||||
{
|
||||
setTabOrder(m_buttons[i], m_buttons[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileResourceSelectorWidget::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip && m_previewToolTip && !m_previewToolTip->isVisible())
|
||||
{
|
||||
if (!m_path.isEmpty())
|
||||
{
|
||||
m_previewToolTip->LoadImage(m_path);
|
||||
m_previewToolTip->setVisible(true);
|
||||
}
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::Resize && m_previewToolTip)
|
||||
{
|
||||
m_previewToolTip->SetTool(this, rect());
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
QWidget* FileResourceSelectorWidgetHandler::CreateGUI(QWidget* pParent)
|
||||
{
|
||||
FileResourceSelectorWidget* newCtrl = aznew FileResourceSelectorWidget(pParent);
|
||||
connect(newCtrl, &FileResourceSelectorWidget::PathChanged, newCtrl, [newCtrl]()
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
|
||||
});
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidgetHandler::ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
Q_UNUSED(GUI);
|
||||
Q_UNUSED(attrib);
|
||||
Q_UNUSED(attrValue);
|
||||
Q_UNUSED(debugName);
|
||||
}
|
||||
|
||||
void FileResourceSelectorWidgetHandler::WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarResource val = instance;
|
||||
val.m_propertyType = GUI->GetPropertyType();
|
||||
val.m_path = GUI->GetPath().toUtf8().data();
|
||||
instance = static_cast<property_t>(val);
|
||||
}
|
||||
|
||||
bool FileResourceSelectorWidgetHandler::ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
Q_UNUSED(node);
|
||||
CReflectedVarResource val = instance;
|
||||
GUI->SetPropertyType(val.m_propertyType);
|
||||
GUI->SetPath(val.m_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <Controls/ReflectedPropertyControl/moc_PropertyResourceCtrl.cpp>
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include "ReflectedVar.h"
|
||||
#include "Util/VariablePropertyType.h"
|
||||
#include <QWidget>
|
||||
#include <QtWidgets/QToolButton>
|
||||
#include <QtCore/QVector>
|
||||
#endif
|
||||
|
||||
class QLineEdit;
|
||||
class QHBoxLayout;
|
||||
class CBitmapToolTip;
|
||||
class QToolTipWidget;
|
||||
|
||||
class BrowseButton
|
||||
: public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(BrowseButton, AZ::SystemAllocator, 0);
|
||||
|
||||
BrowseButton(PropertyType type, QWidget* parent = nullptr);
|
||||
|
||||
void SetPath(const QString& path) { m_path = path; }
|
||||
QString GetPath() const { return m_path; }
|
||||
|
||||
PropertyType GetPropertyType() const {return m_propertyType; }
|
||||
|
||||
signals:
|
||||
void PathChanged(const QString& path);
|
||||
|
||||
protected:
|
||||
void SetPathAndEmit(const QString& path);
|
||||
virtual void OnClicked() = 0;
|
||||
|
||||
PropertyType m_propertyType;
|
||||
QString m_path;
|
||||
};
|
||||
|
||||
class FileResourceSelectorWidget
|
||||
: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FileResourceSelectorWidget, AZ::SystemAllocator, 0);
|
||||
FileResourceSelectorWidget(QWidget* pParent = nullptr);
|
||||
|
||||
bool SetPath(const QString& path);
|
||||
QString GetPath() const;
|
||||
void SetPropertyType(PropertyType type);
|
||||
PropertyType GetPropertyType() const { return m_propertyType; }
|
||||
|
||||
QWidget* GetFirstInTabOrder();
|
||||
QWidget* GetLastInTabOrder();
|
||||
void UpdateTabOrder();
|
||||
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
|
||||
signals:
|
||||
void PathChanged(const QString& path);
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void OnAssignClicked();
|
||||
void OnMaterialClicked();
|
||||
|
||||
void UpdateWidgets();
|
||||
void AddButton(BrowseButton* button);
|
||||
void OnPathChanged(const QString& path);
|
||||
|
||||
private:
|
||||
QLineEdit* m_pathEdit;
|
||||
PropertyType m_propertyType;
|
||||
QString m_path;
|
||||
|
||||
QHBoxLayout* m_mainLayout;
|
||||
QVector<BrowseButton*> m_buttons;
|
||||
QScopedPointer<CBitmapToolTip> m_previewToolTip;
|
||||
QToolTipWidget* m_tooltip;
|
||||
};
|
||||
|
||||
class FileResourceSelectorWidgetHandler
|
||||
: QObject
|
||||
, public AzToolsFramework::PropertyHandler < CReflectedVarResource, FileResourceSelectorWidget >
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(FileResourceSelectorWidgetHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Resource", 0xbc91f416); }
|
||||
virtual bool IsDefaultHandler() const override { return true; }
|
||||
virtual QWidget* GetFirstInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetFirstInTabOrder(); }
|
||||
virtual QWidget* GetLastInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetLastInTabOrder(); }
|
||||
virtual void UpdateWidgetInternalTabbing(FileResourceSelectorWidget* widget) override { widget->UpdateTabOrder(); }
|
||||
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override;
|
||||
virtual void ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
virtual bool ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Description : implementation file
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ReflectedPropertiesPanel.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ReflectedPropertiesPanel dialog
|
||||
|
||||
|
||||
ReflectedPropertiesPanel::ReflectedPropertiesPanel(QWidget* pParent)
|
||||
: ReflectedPropertyControl(pParent)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ReflectedPropertiesPanel::DeleteVars()
|
||||
{
|
||||
ClearVarBlock();
|
||||
m_updateCallbacks.clear();
|
||||
m_varBlock = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ReflectedPropertiesPanel::SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
|
||||
{
|
||||
assert(vb);
|
||||
|
||||
m_varBlock = vb;
|
||||
|
||||
RemoveAllItems();
|
||||
m_varBlock = vb;
|
||||
AddVarBlock(m_varBlock, category);
|
||||
|
||||
SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
|
||||
|
||||
// When new object set all previous callbacks freed.
|
||||
m_updateCallbacks.clear();
|
||||
if (updCallback)
|
||||
{
|
||||
stl::push_back_unique(m_updateCallbacks, updCallback);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void ReflectedPropertiesPanel::AddVars(CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* updCallback, const char* category)
|
||||
{
|
||||
assert(vb);
|
||||
|
||||
bool bNewBlock = false;
|
||||
// Make a clone of properties.
|
||||
if (!m_varBlock)
|
||||
{
|
||||
RemoveAllItems();
|
||||
m_varBlock = vb->Clone(true);
|
||||
AddVarBlock(m_varBlock, category);
|
||||
bNewBlock = true;
|
||||
}
|
||||
m_varBlock->Wire(vb);
|
||||
|
||||
if (bNewBlock)
|
||||
{
|
||||
SetUpdateCallback(AZStd::bind(&ReflectedPropertiesPanel::OnPropertyChanged, this, AZStd::placeholders::_1));
|
||||
|
||||
// When new object set all previous callbacks freed.
|
||||
m_updateCallbacks.clear();
|
||||
}
|
||||
|
||||
if (updCallback)
|
||||
{
|
||||
stl::push_back_unique(m_updateCallbacks, updCallback);
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertiesPanel::OnPropertyChanged(IVariable* pVar)
|
||||
{
|
||||
std::list<ReflectedPropertyControl::UpdateVarCallback*>::iterator iter;
|
||||
for (iter = m_updateCallbacks.begin(); iter != m_updateCallbacks.end(); ++iter)
|
||||
{
|
||||
(*iter)->operator()(pVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
|
||||
#define CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h"
|
||||
#include "Util/Variable.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ReflectedPropertiesPanel dialog
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
//This class is a port of ReflectedPropertiesPanel to use the ReflectedPropertyControl
|
||||
class SANDBOX_API ReflectedPropertiesPanel
|
||||
: public ReflectedPropertyControl
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
public:
|
||||
ReflectedPropertiesPanel(QWidget* pParent = nullptr); // standard constructor
|
||||
|
||||
void DeleteVars();
|
||||
void AddVars(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
|
||||
|
||||
void SetVarBlock(class CVarBlock* vb, ReflectedPropertyControl::UpdateVarCallback* func = nullptr, const char* category = nullptr);
|
||||
|
||||
protected:
|
||||
void OnPropertyChanged(IVariable* pVar);
|
||||
|
||||
protected:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
TSmartPtr<CVarBlock> m_varBlock;
|
||||
|
||||
std::list<ReflectedPropertyControl::UpdateVarCallback*> m_updateCallbacks;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_REFLECTEDPROPERTIESPANEL_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYCTRL_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYCTRL_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include "Include/EditorCoreAPI.h"
|
||||
#include "ReflectedPropertyItem.h"
|
||||
#include "ReflectedVar.h"
|
||||
#include <QFrame>
|
||||
#endif
|
||||
|
||||
class QLineEdit;
|
||||
class QLabel;
|
||||
class QVBoxLayout;
|
||||
class PropertyCard;
|
||||
class QScrollArea;
|
||||
|
||||
namespace AzToolsFramework {
|
||||
class ReflectedPropertyEditor;
|
||||
class PropertyRowWidget;
|
||||
class ComponentEditorHeader;
|
||||
}
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
//ReflectedPropertyEditor-based implementation of the MFC CPropertyCtrl API
|
||||
class EDITOR_CORE_API ReflectedPropertyControl
|
||||
: public QWidget
|
||||
, public AzToolsFramework::IPropertyEditorNotify
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
Q_OBJECT
|
||||
public:
|
||||
//! For alternative undo.
|
||||
typedef AZStd::function<void(IVariable*)> UndoCallback;
|
||||
|
||||
explicit ReflectedPropertyControl(QWidget* parent = nullptr, Qt::WindowFlags windowFlags = Qt::WindowFlags());
|
||||
|
||||
void Setup(bool showScrollbars = true, int labelWidth = 150);
|
||||
|
||||
ReflectedPropertyItem* AddVarBlock(CVarBlock* varBlock, const char* szCategory = nullptr);
|
||||
|
||||
void CreateItems(XmlNodeRef node);
|
||||
void CreateItems(XmlNodeRef node, CVarBlockPtr& varBlock, IVariable::OnSetCallback* func, bool splitCamelCaseIntoWords = false);
|
||||
|
||||
// Replace category item contents with the specified var block.
|
||||
virtual void ReplaceVarBlock(IVariable* categoryItem, CVarBlock* varBlock);
|
||||
|
||||
//replace top-level var block. (used to port ctrl->ReplaceVarBlock(ctrl->GetRootItem(), varBlock);
|
||||
virtual void ReplaceRootVarBlock(CVarBlock* newVarBlock);
|
||||
|
||||
void RemoveAllItems();
|
||||
|
||||
bool FindVariable(IVariable* categoryItem) const;
|
||||
|
||||
//! When item change, this callback fired variable that changed.
|
||||
typedef AZStd::function<void(IVariable*)> UpdateVarCallback;
|
||||
//! When item change, update object.
|
||||
typedef AZStd::function<void(IVariable*)> UpdateObjectCallback;
|
||||
//! When selection changes, this callback fired variable that changed.
|
||||
typedef AZStd::function<void(IVariable*)> SelChangeCallback;
|
||||
|
||||
/** Set update callback to be used for this property window.
|
||||
*/
|
||||
void SetUpdateCallback(const UpdateVarCallback& callback);
|
||||
void ClearUpdateCallback() { m_updateVarFunc = nullptr; }
|
||||
|
||||
void SetUpdateObjectCallback(UpdateObjectCallback callback) { m_updateObjectFunc = callback; }
|
||||
void ClearUpdateObjectCallback() { m_updateObjectFunc = nullptr; }
|
||||
|
||||
/** Set selchange callback to be used for this property window.
|
||||
*/
|
||||
void SetSelChangeCallback(SelChangeCallback callback);
|
||||
|
||||
//set a key that can be used to save/restore expanded state.
|
||||
void SetSavedStateKey(AZ::u32 key);
|
||||
|
||||
void ExpandAll();
|
||||
void CollapseAll();
|
||||
|
||||
virtual void Expand(ReflectedPropertyItem* item, bool expand);
|
||||
void ExpandAllChildren(ReflectedPropertyItem* item, bool recursive);
|
||||
|
||||
//IPropertyEditorNotify Interface
|
||||
void BeforePropertyModified([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void AfterPropertyModified(AzToolsFramework::InstanceDataNode* pNode) override;
|
||||
void SetPropertyEditingActive([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SetPropertyEditingComplete([[maybe_unused]] AzToolsFramework::InstanceDataNode* pNode) override {}
|
||||
void SealUndoStack() override {}
|
||||
void RequestPropertyContextMenu(AzToolsFramework::InstanceDataNode*, const QPoint&) override;
|
||||
void PropertySelectionChanged(AzToolsFramework::InstanceDataNode *pNode, bool selected) override;
|
||||
|
||||
void SetStoreUndoByItems(bool bStoreUndoByItems) { m_bStoreUndoByItems = bStoreUndoByItems; }
|
||||
bool IsStoreUndoByItems() const { return m_bStoreUndoByItems; }
|
||||
|
||||
void ClearSelection();
|
||||
ReflectedPropertyItem* GetSelectedItem();
|
||||
virtual void SelectItem(ReflectedPropertyItem* item);
|
||||
|
||||
QVector<ReflectedPropertyItem*> GetSelectedItems();
|
||||
|
||||
/** Set alternative undo callback.
|
||||
*/
|
||||
void SetUndoCallback(UndoCallback& callback);
|
||||
void ClearUndoCallback();
|
||||
|
||||
/** Enable of disable calling update callback when some values change.
|
||||
*/
|
||||
void EnableUpdateCallback(bool bEnable);
|
||||
void SetDeferredUpdateCallback(bool deferred);
|
||||
|
||||
// Control is grayed, but is not readonly.
|
||||
void SetGrayed(bool grayed);
|
||||
|
||||
// Sets control to be read only, User cannot modify content of properties.
|
||||
void SetReadOnly(bool readonly);
|
||||
|
||||
void SetMultiSelect(bool multiSelect);
|
||||
|
||||
void EnableNotifyWithoutValueChange(bool bFlag);
|
||||
|
||||
void CopyItem(XmlNodeRef rootNode, ReflectedPropertyItem* pItem, bool bRecursively);
|
||||
|
||||
// set to false if you don't want to receive callbacks when the item is not modified (when items are expanded etc)
|
||||
void SetCallbackOnNonModified(bool bEnable) { m_bSendCallbackOnNonModified = bEnable; }
|
||||
|
||||
void ReloadValues();
|
||||
|
||||
//whether to group child properties alphabetically under expanding elements
|
||||
void SetGroupProperties(bool group);
|
||||
|
||||
//whether to sort child properties alphabetically
|
||||
void SetSortProperties(bool sort);
|
||||
|
||||
//whether to show line edit for filtering properties
|
||||
void SetShowFilterWidget(bool showFilter);
|
||||
|
||||
// It doesn't add any property item, but instead it updates all property items with
|
||||
// a new variable block (sets display value, flags and user data).
|
||||
virtual void UpdateVarBlock(CVarBlock* pVarBlock);
|
||||
|
||||
//! Find item that reference specified property.
|
||||
ReflectedPropertyItem* FindItemByVar(IVariable* pVar);
|
||||
|
||||
ReflectedPropertyItem* GetRootItem();
|
||||
|
||||
int GetContentHeight() const;
|
||||
int GetVisibleHeight() const {return GetContentHeight();}
|
||||
|
||||
//whether this control is a section of a TwoColumnPropertyCtrl (so we can show correct copy/paste options)
|
||||
void SetIsTwoColumnCtrlSection(bool isSection);
|
||||
|
||||
struct SCustomPopupItem
|
||||
{
|
||||
typedef AZStd::function<void()> Callback;
|
||||
|
||||
QString m_text;
|
||||
Callback m_callback;
|
||||
|
||||
SCustomPopupItem(const QString& text, const Callback& callback)
|
||||
: m_text(text)
|
||||
, m_callback(callback) {}
|
||||
};
|
||||
|
||||
struct SCustomPopupMenu
|
||||
{
|
||||
typedef AZStd::function<void(int)> Callback;
|
||||
|
||||
QString m_text;
|
||||
Callback m_callback;
|
||||
QStringList m_subMenuText;
|
||||
|
||||
SCustomPopupMenu(const QString& text, const Callback& callback, const QStringList& subMenuText)
|
||||
: m_text(text)
|
||||
, m_callback(callback)
|
||||
, m_subMenuText(subMenuText) {}
|
||||
};
|
||||
|
||||
void AddCustomPopupMenuPopup(const QString& text, const AZStd::function<void(int)>& handler, const QStringList& items);
|
||||
void RemoveCustomPopupMenuPopup(const QString& text);
|
||||
|
||||
void AddCustomPopupMenuItem(const QString& text, const SCustomPopupItem::Callback handler);
|
||||
void RemoveCustomPopupMenuItem(const QString& text);
|
||||
|
||||
AzToolsFramework::PropertyRowWidget* FindPropertyRowWidget(ReflectedPropertyItem* item);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
AzToolsFramework::ReflectedPropertyEditor* GetEditor() { return m_editor; }
|
||||
|
||||
void SetValuesFromNode(XmlNodeRef rootNode);
|
||||
|
||||
public slots:
|
||||
//invalidates attributes and values
|
||||
void InvalidateCtrl(bool queued = true);
|
||||
void RebuildCtrl(bool queued = true);
|
||||
|
||||
void SetTitle(const QString &title);
|
||||
|
||||
void OnCopy(QVector<ReflectedPropertyItem*> items, bool bRecursively);
|
||||
void OnCopyAll();
|
||||
void OnCopyAll(XmlNodeRef node);
|
||||
void OnPaste();
|
||||
|
||||
Q_SIGNALS:
|
||||
void CopyAllSections();
|
||||
void PasteAllSections();
|
||||
|
||||
protected:
|
||||
friend class ReflectedPropertyItem;
|
||||
|
||||
virtual void OnItemChange(ReflectedPropertyItem* item, bool deferCallbacks = true);
|
||||
CReflectedVar* GetReflectedVarFromCallbackInstance(AzToolsFramework::InstanceDataNode* pNode);
|
||||
void RecreateAllItems();
|
||||
|
||||
// only shows items containing the string in their name. All items shown if string is empty.
|
||||
void RestrictToItemsContaining(const QString& searchName);
|
||||
|
||||
bool CallUndoFunc(ReflectedPropertyItem* item);
|
||||
|
||||
virtual void UpdateVarBlock(ReflectedPropertyItem* pPropertyItem, IVariableContainer* pSourceContainer, IVariableContainer* pTargetContainer);
|
||||
|
||||
void ClearVarBlock();
|
||||
|
||||
private slots:
|
||||
void DoUpdateCallback(IVariable *var);
|
||||
void DoUpdateObjectCallback(IVariable *var);
|
||||
|
||||
private:
|
||||
AzToolsFramework::ReflectedPropertyEditor* m_editor;
|
||||
QLineEdit* m_filterLineEdit;
|
||||
QWidget* m_filterWidget;
|
||||
QLabel* m_titleLabel;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
_smart_ptr<CVarBlock> m_pVarBlock;
|
||||
_smart_ptr<ReflectedPropertyItem> m_root;
|
||||
AZStd::unique_ptr<CPropertyContainer> m_rootContainer;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
AZ::SerializeContext* m_serializeContext;
|
||||
|
||||
bool m_bEnableCallback;
|
||||
QString m_filterString;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
UpdateVarCallback m_updateVarFunc;
|
||||
UpdateObjectCallback m_updateObjectFunc;
|
||||
SelChangeCallback m_selChangeFunc;
|
||||
UndoCallback m_undoFunc;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
bool m_bStoreUndoByItems;
|
||||
bool m_bForceModified;
|
||||
|
||||
bool m_groupProperties;
|
||||
bool m_sortProperties;
|
||||
bool m_bSendCallbackOnNonModified;
|
||||
bool m_initialized;
|
||||
|
||||
bool m_isTwoColumnSection;
|
||||
|
||||
//custom popup menu
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::vector<SCustomPopupItem> m_customPopupMenuItems;
|
||||
std::vector<SCustomPopupMenu> m_customPopupMenuPopups;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
template<typename T>
|
||||
void RemoveCustomPopup(const QString& text, T& customPopup);
|
||||
};
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
class EDITOR_CORE_API TwoColumnPropertyControl
|
||||
: public QWidget
|
||||
{
|
||||
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
Q_OBJECT
|
||||
public:
|
||||
TwoColumnPropertyControl(QWidget* parent = nullptr);
|
||||
void Setup(bool showScrollbars = true, int labelWidth = 150);
|
||||
|
||||
void AddVarBlock(CVarBlock* varBlock, const char* szCategory = nullptr);
|
||||
|
||||
// Replace category item contents with the specified var block.
|
||||
virtual void ReplaceVarBlock(IVariable* categoryItem, CVarBlock* varBlock);
|
||||
|
||||
void RemoveAllItems();
|
||||
|
||||
bool FindVariable(IVariable* categoryItem) const;
|
||||
|
||||
void InvalidateCtrl();
|
||||
void RebuildCtrl();
|
||||
|
||||
void SetStoreUndoByItems(bool bStoreUndoByItems);
|
||||
|
||||
/** Set alternative undo callback.
|
||||
*/
|
||||
void SetUndoCallback(ReflectedPropertyControl::UndoCallback callback);
|
||||
void ClearUndoCallback();
|
||||
|
||||
/** Enable of disable calling update callback when some values change.
|
||||
*/
|
||||
void EnableUpdateCallback(bool bEnable);
|
||||
void SetUpdateCallback(ReflectedPropertyControl::UpdateVarCallback callback);
|
||||
|
||||
// Control is grayed, but is not readonly.
|
||||
void SetGrayed(bool grayed);
|
||||
|
||||
//set a key that can be used to save/restore expanded state.
|
||||
void SetSavedStateKey(const QString& key);
|
||||
|
||||
void ExpandAllChildren(ReflectedPropertyItem* item, bool recursive);
|
||||
void ExpandAllChildren(bool recursive);
|
||||
|
||||
void ReloadItems();
|
||||
|
||||
void OnCopyAll();
|
||||
void OnPaste();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private:
|
||||
void ToggleTwoColumnLayout();
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QVector<PropertyCard*> m_controlList;
|
||||
QVector<_smart_ptr<CVarBlock>> m_varBlockList;
|
||||
_smart_ptr<CVarBlock> m_pVarBlock;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
QWidget *m_leftContainer;
|
||||
QWidget *m_rightContainer;
|
||||
QScrollArea *m_leftScrollArea;
|
||||
QScrollArea *m_rightScrollArea;
|
||||
|
||||
bool m_twoColumns;
|
||||
|
||||
static const int minimumColumnWidth = 320;
|
||||
static const int minimumTwoColumnWidth = 660;
|
||||
};
|
||||
|
||||
|
||||
class PropertyCard
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropertyCard(QWidget* parent = nullptr);
|
||||
|
||||
void AddVarBlock(CVarBlock *varBlock);
|
||||
|
||||
ReflectedPropertyControl* GetControl();
|
||||
|
||||
void SetExpanded(bool expanded);
|
||||
bool IsExpanded() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void OnExpansionContractionDone();
|
||||
|
||||
private:
|
||||
void OnExpanderChanged(bool expanded);
|
||||
|
||||
AzToolsFramework::ComponentEditorHeader* m_header = nullptr;
|
||||
ReflectedPropertyControl* m_propertyEditor = nullptr;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYCTRL_H
|
||||
@@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/reflectedPropertyCtrl/img">
|
||||
<file alias="apply.png">resources/apply.png</file>
|
||||
<file alias="file_browse.png">resources/file_browse.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ReflectedPropertyItem.h"
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyRowWidget.hxx>
|
||||
|
||||
// Editor
|
||||
#include "ReflectedVarWrapper.h"
|
||||
#include "ReflectedPropertyCtrl.h"
|
||||
#include "Undo/UndoVariableChange.h"
|
||||
|
||||
// default number of increments to cover the range of a property - determined experimentally by feel
|
||||
const float ReflectedPropertyItem::s_DefaultNumStepIncrements = 500.0f;
|
||||
|
||||
|
||||
//A ReflectedVarAdapter for holding IVariableContainers
|
||||
|
||||
//The extra ReflectedVarAdapter is the extra case of a container (has children) but also has a value itself.
|
||||
//An example is an IVariable array whose type is forced to IVariable::DT_TEXTURE. The base Ivariable has a texture,
|
||||
//but it also has children that are parameters of the texture. The ReflectedPropertyEditor does not support this case
|
||||
//so we work around by adding the base property to the list of children and showing the value of the base property
|
||||
//in the container value space instead of "X Elements"
|
||||
|
||||
static ColorF StringToColor(const QString &value)
|
||||
{
|
||||
ColorF color;
|
||||
float r, g, b, a;
|
||||
int res = azsscanf(value.toUtf8().data(), "%f,%f,%f,%f", &r, &g, &b, &a);
|
||||
if (res == 4)
|
||||
{
|
||||
color.Set(r, g, b, a);
|
||||
}
|
||||
else if (res == 3)
|
||||
{
|
||||
color.Set(r, g, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned abgr;
|
||||
azsscanf(value.toUtf8().data(), "%u", &abgr);
|
||||
color = ColorF(abgr);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
class ReflectedVarContainerAdapter : public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
ReflectedVarContainerAdapter(ReflectedPropertyItem *item, ReflectedPropertyControl *control, ReflectedVarAdapter *variableAdapter = nullptr)
|
||||
: m_extraVariableAdapter(variableAdapter)
|
||||
, m_item(item)
|
||||
, m_propertyCtrl(control)
|
||||
, m_containerVar(new CPropertyContainer(AZStd::string()))
|
||||
{
|
||||
m_containerVar->SetAutoExpand(false);
|
||||
}
|
||||
|
||||
void SetVariable(IVariable *pVariable) override
|
||||
{
|
||||
if (m_extraVariableAdapter)
|
||||
m_extraVariableAdapter->SetVariable(pVariable);
|
||||
|
||||
//Check whether the parent container has autoExpand flag set, and if so, the autoexpand flag for this item
|
||||
//We need to do this because the default IVariable flags has the item expanded, so most items are expanded,
|
||||
//but the ReflectedPropertyEditor expands all ancestors if any item is expanded.
|
||||
//This is not what we want -- the old property editor did not expand ancestors. In case of Material editor,
|
||||
//this expansion can be really expensive!
|
||||
const bool parentIsAutoExpand = m_item->GetParent() == nullptr || m_item->GetParent()->GetContainer() == nullptr || m_item->GetParent()->GetContainer()->m_containerVar->AutoExpand();
|
||||
const bool bDefaultExpand = (pVariable->GetFlags() & IVariable::UI_COLLAPSED) == 0 || (pVariable->GetFlags() & IVariable::UI_AUTO_EXPAND);
|
||||
m_containerVar->SetAutoExpand(parentIsAutoExpand && bDefaultExpand);
|
||||
|
||||
UpdateCommon(pVariable, pVariable);
|
||||
}
|
||||
|
||||
//helps implement ReflectedPropertyControl::ReplaceVarBlock
|
||||
void ReplaceVarBlock(CVarBlock *varBlock)
|
||||
{
|
||||
m_containerVar->Clear();
|
||||
UpdateCommon(m_item->GetVariable(), varBlock);
|
||||
}
|
||||
|
||||
void SyncReflectedVarToIVar(IVariable *pVariable) override
|
||||
{
|
||||
if (m_extraVariableAdapter)
|
||||
{
|
||||
m_extraVariableAdapter->SyncReflectedVarToIVar(pVariable);
|
||||
//update text on parent container. Do not have control update attributes since this will happen anyway as part of updating ReflectedVar
|
||||
updateContainerText(pVariable, false);
|
||||
}
|
||||
};
|
||||
|
||||
void SyncIVarToReflectedVar(IVariable *pVariable) override
|
||||
{
|
||||
if (m_extraVariableAdapter)
|
||||
{
|
||||
m_extraVariableAdapter->SyncIVarToReflectedVar(pVariable);
|
||||
//update text on parent container. Force control to update attributes since this doesn't normally happen when updating an IVar from ReflectedVar
|
||||
updateContainerText(pVariable, true);
|
||||
}
|
||||
};
|
||||
|
||||
CReflectedVar *GetReflectedVar() override { return m_containerVar.data(); }
|
||||
|
||||
bool Contains(CReflectedVar *var) override { return var == m_containerVar.data() || (m_extraVariableAdapter && m_extraVariableAdapter->GetReflectedVar() == var); }
|
||||
|
||||
private:
|
||||
|
||||
void UpdateCommon(IVariable *nameVariable, IVariableContainer *childContainer)
|
||||
{
|
||||
m_containerVar->m_varName = nameVariable->GetHumanName().toUtf8().data();
|
||||
m_containerVar->m_description = nameVariable->GetDescription().toUtf8().data();
|
||||
if (m_extraVariableAdapter)
|
||||
{
|
||||
m_containerVar->AddProperty(m_extraVariableAdapter->GetReflectedVar());
|
||||
}
|
||||
//Handle adding empty varblock
|
||||
if (!childContainer)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < childContainer->GetNumVariables(); i++)
|
||||
{
|
||||
AddChild(childContainer->GetVariable(i));
|
||||
}
|
||||
}
|
||||
|
||||
void AddChild(IVariable *var)
|
||||
{
|
||||
if (var->GetFlags() & IVariable::UI_INVISIBLE)
|
||||
return;
|
||||
ReflectedPropertyItemPtr item = new ReflectedPropertyItem(m_propertyCtrl, m_item);
|
||||
item->SetVariable(var);
|
||||
m_containerVar->AddProperty(item->GetReflectedVar());
|
||||
}
|
||||
|
||||
void updateContainerText(IVariable *pVariable, bool updateAttributes)
|
||||
{
|
||||
//set text of the container to the value of the main variable. If it's empty, use space, otherwise ReflectedPropertyEditor doesn't update it!
|
||||
m_containerVar->SetValueText(pVariable->GetDisplayValue().isEmpty() ? AZStd::string(" ") : AZStd::string(pVariable->GetDisplayValue().toUtf8().data()));
|
||||
if (updateAttributes)
|
||||
m_propertyCtrl->InvalidateCtrl();
|
||||
}
|
||||
|
||||
private:
|
||||
//optional adapter for case where this item contains a variable in addition to a container of variables.
|
||||
ReflectedVarAdapter *m_extraVariableAdapter;
|
||||
QScopedPointer<CPropertyContainer> m_containerVar;
|
||||
ReflectedPropertyItem *m_item;
|
||||
ReflectedPropertyControl *m_propertyCtrl;
|
||||
};
|
||||
|
||||
ReflectedPropertyItem::ReflectedPropertyItem(ReflectedPropertyControl *control, ReflectedPropertyItem *parent)
|
||||
: m_pVariable(nullptr)
|
||||
, m_reflectedVarAdapter(nullptr)
|
||||
, m_reflectedVarContainerAdapter(nullptr)
|
||||
, m_parent(parent)
|
||||
, m_propertyCtrl(control)
|
||||
, m_syncingIVar(false)
|
||||
, m_strNoScriptDefault("<<undefined>>")
|
||||
, m_strScriptDefault(m_strNoScriptDefault)
|
||||
{
|
||||
m_type = ePropertyInvalid;
|
||||
m_modified = false;
|
||||
if (parent)
|
||||
parent->AddChild(this);
|
||||
|
||||
m_onSetCallback = AZStd::bind(&ReflectedPropertyItem::OnVariableChange, this, AZStd::placeholders::_1);
|
||||
m_onSetEnumCallback = AZStd::bind(&ReflectedPropertyItem::OnVariableEnumChange, this, AZStd::placeholders::_1);
|
||||
}
|
||||
|
||||
ReflectedPropertyItem::~ReflectedPropertyItem()
|
||||
{
|
||||
// just to make sure we dont double (or infinitely recurse...) delete
|
||||
AddRef();
|
||||
|
||||
if (m_pVariable)
|
||||
ReleaseVariable();
|
||||
|
||||
RemoveAllChildren();
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::SetVariable(IVariable *var)
|
||||
{
|
||||
if (var == m_pVariable)
|
||||
{
|
||||
// Early exit optimization if setting the same var as the current var.
|
||||
// A common use case, in Track View for example, is to re-use the save var for a property when switching to a new
|
||||
// instance of the same variable. The visible display of the value is often handled by invalidating the property,
|
||||
// but the non-visible attributes, i.e. the range values, are usually set using this method. Thus we reset the ranges
|
||||
// explicitly here when the Ivariable var is the same
|
||||
|
||||
if (m_reflectedVarAdapter)
|
||||
m_reflectedVarAdapter->UpdateRangeLimits(var);
|
||||
return;
|
||||
}
|
||||
_smart_ptr<IVariable> pInputVar = var;
|
||||
// Release previous variable.
|
||||
if (m_pVariable)
|
||||
ReleaseVariable();
|
||||
|
||||
m_pVariable = pInputVar;
|
||||
assert(m_pVariable != NULL);
|
||||
|
||||
m_pVariable->AddOnSetCallback(&m_onSetCallback);
|
||||
m_pVariable->AddOnSetEnumCallback(&m_onSetEnumCallback);
|
||||
|
||||
// Fetch base parameter description
|
||||
Prop::Description desc(m_pVariable);
|
||||
m_type = desc.m_type;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case ePropertyVector2:
|
||||
m_reflectedVarAdapter = new ReflectedVarVector2Adapter;
|
||||
break;
|
||||
case ePropertyVector:
|
||||
m_reflectedVarAdapter = new ReflectedVarVector3Adapter;
|
||||
break;
|
||||
case ePropertyVector4:
|
||||
m_reflectedVarAdapter = new ReflectedVarVector4Adapter;
|
||||
break;
|
||||
case ePropertyFloat:
|
||||
case ePropertyAngle:
|
||||
//if the Description has a valid global enumDB lookup, edit as an enum, otherwise use normal float editor
|
||||
if (desc.m_pEnumDBItem)
|
||||
m_reflectedVarAdapter = new ReflectedVarDBEnumAdapter;
|
||||
else
|
||||
m_reflectedVarAdapter = new ReflectedVarFloatAdapter;
|
||||
break;
|
||||
case ePropertyInt:
|
||||
//if the Description has a valid global enumDB lookup, edit as an enum, otherwise use normal int editor
|
||||
if (desc.m_pEnumDBItem)
|
||||
m_reflectedVarAdapter = new ReflectedVarDBEnumAdapter;
|
||||
else
|
||||
m_reflectedVarAdapter = new ReflectedVarIntAdapter;
|
||||
break;
|
||||
case ePropertyBool:
|
||||
m_reflectedVarAdapter = new ReflectedVarBoolAdapter;
|
||||
break;
|
||||
case ePropertyString:
|
||||
//if the Description has a valid global enumDB lookup, edit as an enum, otherwise use normal string editor
|
||||
if (desc.m_pEnumDBItem)
|
||||
m_reflectedVarAdapter = new ReflectedVarDBEnumAdapter;
|
||||
else
|
||||
m_reflectedVarAdapter = new ReflectedVarStringAdapter;
|
||||
break;
|
||||
case ePropertySelection:
|
||||
m_reflectedVarAdapter = new ReflectedVarEnumAdapter;
|
||||
break;
|
||||
case ePropertyAnimation:
|
||||
m_reflectedVarAdapter = new ReflectedVarAnimationAdapter;
|
||||
break;
|
||||
case ePropertyColor:
|
||||
m_reflectedVarAdapter = new ReflectedVarColorAdapter;
|
||||
break;
|
||||
case ePropertyUser:
|
||||
m_reflectedVarAdapter = new ReflectedVarUserAdapter;
|
||||
break;
|
||||
case ePropertyEquip:
|
||||
case ePropertyReverbPreset:
|
||||
case ePropertyGameToken:
|
||||
case ePropertyMissionObj:
|
||||
case ePropertySequence:
|
||||
case ePropertySequenceId:
|
||||
case ePropertyLocalString:
|
||||
case ePropertyLightAnimation:
|
||||
case ePropertyParticleName:
|
||||
m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type);
|
||||
break;
|
||||
case ePropertyTexture:
|
||||
case ePropertyModel:
|
||||
case ePropertyGeomCache:
|
||||
case ePropertyAudioTrigger:
|
||||
case ePropertyAudioSwitch:
|
||||
case ePropertyAudioSwitchState:
|
||||
case ePropertyAudioRTPC:
|
||||
case ePropertyAudioEnvironment:
|
||||
case ePropertyAudioPreloadRequest:
|
||||
case ePropertyFile:
|
||||
m_reflectedVarAdapter = new ReflectedVarResourceAdapter;
|
||||
break;
|
||||
case ePropertyFloatCurve:
|
||||
case ePropertyColorCurve:
|
||||
m_reflectedVarAdapter = new ReflectedVarSplineAdapter(this, m_type);
|
||||
break;
|
||||
case ePropertyMotion:
|
||||
m_reflectedVarAdapter = new ReflectedVarMotionAdapter;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const bool hasChildren = (m_pVariable->GetNumVariables() > 0 || desc.m_type == ePropertyTable || m_pVariable->GetType() == IVariable::ARRAY);
|
||||
//const bool isNotContainerType = (m_pVariable->GetType() != IVariable::ARRAY && desc.m_type != ePropertyTable && desc.m_type != ePropertyInvalid);
|
||||
if (hasChildren )
|
||||
{
|
||||
m_reflectedVarContainerAdapter = new ReflectedVarContainerAdapter(this, m_propertyCtrl, m_reflectedVarAdapter);
|
||||
m_reflectedVarAdapter = m_reflectedVarContainerAdapter;
|
||||
}
|
||||
|
||||
if (m_reflectedVarAdapter)
|
||||
{
|
||||
m_reflectedVarAdapter->SetVariable(m_pVariable);
|
||||
m_reflectedVarAdapter->SyncReflectedVarToIVar(m_pVariable);
|
||||
}
|
||||
|
||||
m_modified = false;
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::ReplaceVarBlock(CVarBlock *varBlock)
|
||||
{
|
||||
RemoveAllChildren();
|
||||
if (m_reflectedVarAdapter)
|
||||
m_reflectedVarAdapter->ReplaceVarBlock(varBlock);
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::AddChild(ReflectedPropertyItem *item)
|
||||
{
|
||||
assert(item);
|
||||
m_childs.push_back(item);
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::RemoveAllChildren()
|
||||
{
|
||||
for (int i = 0; i < m_childs.size(); i++)
|
||||
{
|
||||
m_childs[i]->m_parent = 0;
|
||||
}
|
||||
|
||||
m_childs.clear();
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::RemoveChild(ReflectedPropertyItem* item)
|
||||
{
|
||||
for (int i = 0; i < m_childs.size(); i++)
|
||||
{
|
||||
if (m_childs[i] == item)
|
||||
{
|
||||
item->m_parent = nullptr;
|
||||
m_childs.erase(m_childs.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CReflectedVar * ReflectedPropertyItem::GetReflectedVar() const
|
||||
{
|
||||
return m_reflectedVarAdapter ? m_reflectedVarAdapter->GetReflectedVar() : nullptr;
|
||||
}
|
||||
|
||||
ReflectedPropertyItem * ReflectedPropertyItem::findItem(CReflectedVar *var)
|
||||
{
|
||||
if (m_reflectedVarAdapter && m_reflectedVarAdapter->Contains(var) )
|
||||
return this;
|
||||
for (auto child : m_childs)
|
||||
{
|
||||
ReflectedPropertyItem *result = child->findItem(var);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
ReflectedPropertyItem * ReflectedPropertyItem::findItem(IVariable *var)
|
||||
{
|
||||
if (m_pVariable == var)
|
||||
return this;
|
||||
for (auto child : m_childs)
|
||||
{
|
||||
ReflectedPropertyItem *result = child->findItem(var);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReflectedPropertyItem* ReflectedPropertyItem::findItem(const QString &name)
|
||||
{
|
||||
if (m_pVariable && m_pVariable->GetHumanName() == name)
|
||||
return this;
|
||||
for (auto child : m_childs)
|
||||
{
|
||||
ReflectedPropertyItem *result = child->findItem(name);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
ReflectedPropertyItem * ReflectedPropertyItem::FindItemByFullName(const QString& fullName)
|
||||
{
|
||||
if (GetFullName() == fullName)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
for (int i = 0; i < m_childs.size(); ++i)
|
||||
{
|
||||
auto pFound = m_childs[i]->FindItemByFullName(fullName);
|
||||
if (pFound)
|
||||
{
|
||||
return pFound;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString ReflectedPropertyItem::GetName() const
|
||||
{
|
||||
return m_pVariable ? m_pVariable->GetHumanName() : QString();
|
||||
}
|
||||
|
||||
QString ReflectedPropertyItem::GetFullName() const
|
||||
{
|
||||
if (m_parent && m_pVariable)
|
||||
{
|
||||
return m_parent->GetFullName() + "::" + m_pVariable->GetName();
|
||||
}
|
||||
else if (m_pVariable)
|
||||
{
|
||||
return m_pVariable->GetName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::OnReflectedVarChanged()
|
||||
{
|
||||
m_syncingIVar = true;
|
||||
if (m_reflectedVarAdapter)
|
||||
{
|
||||
std::unique_ptr<CUndo> undo;
|
||||
if (!CUndo::IsRecording())
|
||||
{
|
||||
if (!m_propertyCtrl->CallUndoFunc(this))
|
||||
undo.reset(new CUndo((m_pVariable->GetHumanName() + " Modified").toUtf8().data()));
|
||||
}
|
||||
|
||||
m_reflectedVarAdapter->SyncIVarToReflectedVar(m_pVariable);
|
||||
|
||||
if (m_propertyCtrl->IsStoreUndoByItems() && CUndo::IsRecording())
|
||||
CUndo::Record(new CUndoVariableChange(m_pVariable, "PropertyChange"));
|
||||
|
||||
m_modified = true;
|
||||
}
|
||||
m_syncingIVar = false;
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::SyncReflectedVarToIVar()
|
||||
{
|
||||
if (m_reflectedVarAdapter)
|
||||
{
|
||||
m_reflectedVarAdapter->SyncReflectedVarToIVar(m_pVariable);
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::ReleaseVariable()
|
||||
{
|
||||
if (m_pVariable)
|
||||
{
|
||||
// Unwire all from variable.
|
||||
m_pVariable->RemoveOnSetCallback(&m_onSetCallback);
|
||||
m_pVariable->RemoveOnSetEnumCallback(&m_onSetEnumCallback);
|
||||
}
|
||||
m_pVariable = 0;
|
||||
delete m_reflectedVarAdapter;
|
||||
m_reflectedVarAdapter = nullptr;
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::OnVariableChange(IVariable* pVar)
|
||||
{
|
||||
assert(pVar != 0 && pVar == m_pVariable);
|
||||
|
||||
if (m_syncingIVar)
|
||||
return;
|
||||
|
||||
// When variable changes, invalidate UI.
|
||||
m_modified = true;
|
||||
|
||||
if (m_reflectedVarAdapter)
|
||||
{
|
||||
m_reflectedVarAdapter->OnVariableChange(pVar);
|
||||
}
|
||||
SyncReflectedVarToIVar();
|
||||
|
||||
m_propertyCtrl->InvalidateCtrl();
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::OnVariableEnumChange([[maybe_unused]] IVariable* pVar)
|
||||
{
|
||||
|
||||
if (m_reflectedVarAdapter && m_reflectedVarAdapter->UpdateReflectedVarEnums())
|
||||
{
|
||||
m_propertyCtrl->InvalidateCtrl(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::ReloadValues()
|
||||
{
|
||||
m_modified = false;
|
||||
|
||||
if (m_pVariable)
|
||||
SetVariable(m_pVariable);
|
||||
|
||||
for (int i = 0; i < GetChildCount(); i++)
|
||||
{
|
||||
GetChild(i)->ReloadValues();
|
||||
}
|
||||
SyncReflectedVarToIVar();
|
||||
}
|
||||
|
||||
|
||||
/** Changes value of item.
|
||||
*/
|
||||
void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bool bForceModified)
|
||||
{
|
||||
if (!m_pVariable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_smart_ptr<ReflectedPropertyItem> holder = this; // Make sure we are not released during this function.
|
||||
|
||||
QString value = sValue;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case ePropertyBool:
|
||||
if (QString::compare(value, "true", Qt::CaseInsensitive) == 0 || value.toInt() != 0)
|
||||
{
|
||||
value = "1";
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "0";
|
||||
}
|
||||
break;
|
||||
|
||||
case ePropertyVector2:
|
||||
if (!value.contains(','))
|
||||
{
|
||||
value = value + ", " + value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ePropertyVector4:
|
||||
if (!value.contains(','))
|
||||
{
|
||||
value = value + ", " + value + ", " + value + ", " + value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ePropertyVector:
|
||||
if (!value.contains(','))
|
||||
{
|
||||
value = value + ", " + value + ", " + value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ePropertyTexture:
|
||||
case ePropertyModel:
|
||||
value.replace('\\', '/');
|
||||
break;
|
||||
}
|
||||
|
||||
// correct the length of value
|
||||
switch (m_type)
|
||||
{
|
||||
case ePropertyTexture:
|
||||
case ePropertyModel:
|
||||
case ePropertyFile:
|
||||
if (value.length() >= MAX_PATH)
|
||||
{
|
||||
value = value.left(MAX_PATH);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
bool bModified = bForceModified || m_pVariable->GetDisplayValue() != value;
|
||||
bool bStoreUndo = (m_pVariable->GetDisplayValue() != value || bForceModified) && bRecordUndo;
|
||||
|
||||
std::unique_ptr<CUndo> undo;
|
||||
if (bStoreUndo && !CUndo::IsRecording())
|
||||
{
|
||||
if (!m_propertyCtrl->CallUndoFunc(this))
|
||||
{
|
||||
undo.reset(new CUndo((GetName() + " Modified").toUtf8().data()));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pVariable)
|
||||
{
|
||||
if (bModified)
|
||||
{
|
||||
if (m_propertyCtrl->IsStoreUndoByItems() && bStoreUndo && CUndo::IsRecording())
|
||||
{
|
||||
CUndo::Record(new CUndoVariableChange(m_pVariable, "PropertyChange"));
|
||||
}
|
||||
|
||||
if (bForceModified)
|
||||
{
|
||||
m_pVariable->SetForceModified(true);
|
||||
}
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case ePropertyColor:
|
||||
{
|
||||
ColorF color = StringToColor(value);
|
||||
if (m_pVariable->GetType() == IVariable::VECTOR)
|
||||
{
|
||||
m_pVariable->Set(color.toVec3());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pVariable->Set(static_cast<int>(color.pack_abgr8888()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ePropertyInvalid:
|
||||
break;
|
||||
default:
|
||||
m_pVariable->SetDisplayValue(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bModified)
|
||||
{
|
||||
m_modified = true;
|
||||
// If Value changed mark document modified.
|
||||
// Notify parent that this Item have been modified.
|
||||
m_propertyCtrl->OnItemChange(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::SendOnItemChange()
|
||||
{
|
||||
m_propertyCtrl->OnItemChange(this);
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::ExpandAllChildren(bool recursive)
|
||||
{
|
||||
Expand(true);
|
||||
for (auto child : m_childs)
|
||||
{
|
||||
if (recursive)
|
||||
{
|
||||
child->ExpandAllChildren(recursive);
|
||||
}
|
||||
else
|
||||
{
|
||||
child->Expand(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedPropertyItem::Expand(bool expand)
|
||||
{
|
||||
AzToolsFramework::PropertyRowWidget *widget = m_propertyCtrl->FindPropertyRowWidget(this);
|
||||
if (widget)
|
||||
{
|
||||
widget->SetExpanded(expand);
|
||||
}
|
||||
}
|
||||
|
||||
QString ReflectedPropertyItem::GetPropertyName() const
|
||||
{
|
||||
return m_pVariable ? m_pVariable->GetHumanName() : QString();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYITEM_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYITEM_H
|
||||
#pragma once
|
||||
|
||||
#include "Util/Variable.h"
|
||||
#include <Util/VariablePropertyType.h>
|
||||
|
||||
namespace AzToolsFramework {
|
||||
class ReflectedPropertyEditor;
|
||||
}
|
||||
|
||||
class CReflectedVar;
|
||||
class CPropertyContainer;
|
||||
class ReflectedPropertyControl;
|
||||
class ReflectedVarAdapter;
|
||||
class ReflectedVarContainerAdapter;
|
||||
|
||||
// Class representing a property inside a ReflectedPropertyCtrl.
|
||||
// It contains the IVariable and corresponding CReflectedVar for that property
|
||||
// and any children properties if the IVariable is a container.
|
||||
|
||||
// This class is loosely based on the MFC-based CPropertyItem to make porting easier.
|
||||
// The CPropertyItem created editor widgets for each property type, but this class
|
||||
// just holds a CReflectedVar and updates it's values. The editing is done by the
|
||||
// reflection system and registered property handlers for each CReflectedVar.
|
||||
class EDITOR_CORE_API ReflectedPropertyItem
|
||||
: public CRefCountBase
|
||||
{
|
||||
public:
|
||||
ReflectedPropertyItem(ReflectedPropertyControl* control, ReflectedPropertyItem* parent);
|
||||
~ReflectedPropertyItem();
|
||||
|
||||
void SetVariable(IVariable* var);
|
||||
IVariable* GetVariable() const { return m_pVariable; }
|
||||
|
||||
void ReplaceVarBlock(CVarBlock* varBlock);
|
||||
|
||||
CReflectedVar* GetReflectedVar() const;
|
||||
|
||||
ReflectedPropertyItem* findItem(CReflectedVar* var);
|
||||
ReflectedPropertyItem* findItem(IVariable* var);
|
||||
ReflectedPropertyItem* findItem(const QString &name);
|
||||
ReflectedPropertyItem* FindItemByFullName(const QString& fullName);
|
||||
|
||||
//update the internal IVariable as result of ReflectedVar changing
|
||||
void OnReflectedVarChanged();
|
||||
|
||||
//update the ReflectedVar to current value of IVar
|
||||
void SyncReflectedVarToIVar();
|
||||
|
||||
//! Return true if this property item is modified.
|
||||
bool IsModified() const { return m_modified; }
|
||||
|
||||
void ReloadValues();
|
||||
|
||||
ReflectedVarContainerAdapter* GetContainer() { return m_reflectedVarContainerAdapter; }
|
||||
ReflectedPropertyItem* GetParent() { return m_parent; }
|
||||
|
||||
/** Get script default value of property item.
|
||||
*/
|
||||
virtual bool HasScriptDefault() const { return m_strScriptDefault != m_strNoScriptDefault; };
|
||||
|
||||
/** Get script default value of property item.
|
||||
*/
|
||||
virtual QString GetScriptDefault() const { return m_strScriptDefault; };
|
||||
|
||||
/** Set script default value of property item.
|
||||
*/
|
||||
virtual void SetScriptDefault(const QString& sScriptDefault) { m_strScriptDefault = sScriptDefault; };
|
||||
|
||||
/** Set script default value of property item.
|
||||
*/
|
||||
virtual void ClearScriptDefault() { m_strScriptDefault = m_strNoScriptDefault; };
|
||||
|
||||
|
||||
/** Changes value of item.
|
||||
*/
|
||||
virtual void SetValue(const QString& sValue, bool bRecordUndo = true, bool bForceModified = false);
|
||||
|
||||
//hack for calling ReflectedPropertyControl::OnItemChange from a wrapper class
|
||||
//this is used because changes to Splines should not actually change anything in the IVariable,
|
||||
//but we need OnItemChanged as if the IVariable did change.
|
||||
void SendOnItemChange();
|
||||
|
||||
void ExpandAllChildren(bool recursive);
|
||||
void Expand(bool expand);
|
||||
|
||||
QString GetPropertyName() const;
|
||||
|
||||
void AddChild(ReflectedPropertyItem* item);
|
||||
void RemoveAllChildren();
|
||||
void RemoveChild(ReflectedPropertyItem* item);
|
||||
|
||||
// default number of increments to cover the range of a property
|
||||
static const float s_DefaultNumStepIncrements;
|
||||
|
||||
// for a consistent Feel, compute the step size for a numerical slider for the specified min/max, rounded to precision
|
||||
inline static float ComputeSliderStep(float sliderMin, float sliderMax, const float precision = .01f)
|
||||
{
|
||||
float step;
|
||||
step = int_round(((sliderMax - sliderMin) / ReflectedPropertyItem::s_DefaultNumStepIncrements) / precision) * precision;
|
||||
// prevent rounding down to zero
|
||||
return (step > precision) ? step : precision;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class ReflectedPropertyControl;
|
||||
|
||||
//! Release used variable.
|
||||
void ReleaseVariable();
|
||||
//! Callback called when variable change.
|
||||
void OnVariableChange(IVariable* var);
|
||||
void OnVariableEnumChange(IVariable* var);
|
||||
|
||||
public:
|
||||
//! Get number of child nodes.
|
||||
int GetChildCount() const { return m_childs.size(); };
|
||||
//! Get Child by id.
|
||||
ReflectedPropertyItem* GetChild(int index) const { return m_childs[index]; }
|
||||
PropertyType GetType() const { return m_type; }
|
||||
|
||||
/** Get name of property item.
|
||||
*/
|
||||
virtual QString GetName() const;
|
||||
|
||||
QString GetFullName() const;
|
||||
|
||||
protected:
|
||||
PropertyType m_type;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
//The variable being edited.
|
||||
_smart_ptr<IVariable> m_pVariable;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
//holds the CReflectedVar and syncs its value with IVariable when either changes
|
||||
ReflectedVarAdapter* m_reflectedVarAdapter;
|
||||
ReflectedVarContainerAdapter* m_reflectedVarContainerAdapter;
|
||||
|
||||
ReflectedPropertyItem* m_parent;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
std::vector<_smart_ptr<ReflectedPropertyItem> > m_childs;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
ReflectedPropertyControl* m_propertyCtrl;
|
||||
|
||||
unsigned int m_modified : 1;
|
||||
|
||||
bool m_syncingIVar;
|
||||
|
||||
QString m_strNoScriptDefault;
|
||||
QString m_strScriptDefault;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
IVariable::OnSetCallback m_onSetCallback;
|
||||
IVariable::OnSetEnumCallback m_onSetEnumCallback;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
typedef _smart_ptr<ReflectedPropertyItem> ReflectedPropertyItemPtr;
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_REFLECTEDPROPERTYITEM_H
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ReflectedVar.h"
|
||||
|
||||
// AzCore
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
|
||||
bool ReflectedVarInit::s_reflectionDone = false;
|
||||
|
||||
void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
if (!serializeContext)
|
||||
return;
|
||||
|
||||
if (s_reflectionDone)
|
||||
return;
|
||||
|
||||
s_reflectionDone = true;
|
||||
|
||||
serializeContext->Class< CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("description", &CReflectedVar::m_description)
|
||||
->Field("varName", &CReflectedVar::m_varName);
|
||||
|
||||
serializeContext->Class <CReflectedVarAnimation, CReflectedVar >()
|
||||
->Version(1)
|
||||
->Field("animation", &CReflectedVarAnimation::m_animation)
|
||||
->Field("entityID", &CReflectedVarAnimation::m_entityID)
|
||||
;
|
||||
|
||||
serializeContext->Class <CReflectedVarResource, CReflectedVar >()
|
||||
->Version(1)
|
||||
->Field("path", &CReflectedVarResource::m_path)
|
||||
->Field("propertyType", &CReflectedVarResource::m_propertyType)
|
||||
;
|
||||
|
||||
serializeContext->Class< CReflectedVarColor, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("color", &CReflectedVarColor::m_color);
|
||||
|
||||
serializeContext->Class< CReflectedVarUser, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("value", &CReflectedVarUser::m_value)
|
||||
->Field("enableEdit", &CReflectedVarUser::m_enableEdit)
|
||||
->Field("title", &CReflectedVarUser::m_dialogTitle)
|
||||
->Field("useTree", &CReflectedVarUser::m_useTree)
|
||||
->Field("treeSeparator", &CReflectedVarUser::m_treeSeparator)
|
||||
->Field("itemNames", &CReflectedVarUser::m_itemNames)
|
||||
->Field("itemDescriptions", &CReflectedVarUser::m_itemDescriptions);
|
||||
|
||||
serializeContext->Class <CReflectedVarSpline, CReflectedVar >()
|
||||
->Version(1)
|
||||
->Field("spline", &CReflectedVarSpline::m_spline)
|
||||
->Field("propertyType", &CReflectedVarSpline::m_propertyType)
|
||||
;
|
||||
|
||||
serializeContext->Class< CPropertyContainer, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("properties", &CPropertyContainer::m_properties);
|
||||
|
||||
serializeContext->Class <CReflectedVarMotion, CReflectedVar >()
|
||||
->Version(1)
|
||||
->Field("motion", &CReflectedVarMotion::m_motion)
|
||||
->Field("assetId", &CReflectedVarMotion::m_assetId)
|
||||
;
|
||||
|
||||
AZ::EditContext* ec = serializeContext->GetEditContext();
|
||||
if (ec)
|
||||
{
|
||||
ec->Class< CReflectedVarAnimation >("VarAnimation", "Animation")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAnimation::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAnimation::description)
|
||||
;
|
||||
|
||||
ec->Class< CReflectedVarResource >("VarResource", "Resource")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarResource::description)
|
||||
;
|
||||
|
||||
ec->Class< CReflectedVarUser >("VarUser", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarUser::varName)
|
||||
->Attribute(AZ::Edit::Attributes::Handler, AZ_CRC("ePropertyUser", 0x65b972c0))
|
||||
;
|
||||
|
||||
ec->Class< CReflectedVarColor >("VarColor", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &CReflectedVarColor::m_color, "Color", "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarColor::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarColor::description)
|
||||
;
|
||||
|
||||
ec->Class< CReflectedVarSpline >("VarSpline", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarSpline::varName)
|
||||
->Attribute(AZ::Edit::Attributes::Handler, &CReflectedVarSpline::handler)
|
||||
;
|
||||
|
||||
ec->Class< CPropertyContainer >("PropertyContainer", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CPropertyContainer::m_properties, "Properties", "")
|
||||
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CPropertyContainer::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CPropertyContainer::description)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &CPropertyContainer::GetVisibility)
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, &CPropertyContainer::m_autoExpand)
|
||||
->Attribute(AZ::Edit::Attributes::ValueText, &CPropertyContainer::m_valueText) //will be ignored if blank
|
||||
;
|
||||
|
||||
ec->Class< CReflectedVarMotion >("VarMotion", "Motion")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarMotion::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarMotion::description)
|
||||
;
|
||||
}
|
||||
CReflectedVarString::reflect(serializeContext);
|
||||
CReflectedVarBool::reflect(serializeContext);
|
||||
CReflectedVarFloat::reflect(serializeContext);
|
||||
CReflectedVarInt::reflect(serializeContext);
|
||||
CReflectedVarVector2::reflect(serializeContext);
|
||||
CReflectedVarVector3::reflect(serializeContext);
|
||||
CReflectedVarVector4::reflect(serializeContext);
|
||||
CReflectedVarAny<AZStd::vector<AZStd::string>>::reflect(serializeContext);
|
||||
CReflectedVarEnum<int>::reflect(serializeContext);
|
||||
CReflectedVarEnum<AZStd::string>::reflect(serializeContext);
|
||||
CReflectedVarGenericProperty::reflect(serializeContext);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void CReflectedVarAny<T>::reflect(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
static bool reflected = false;
|
||||
if (reflected)
|
||||
return;
|
||||
reflected = true;
|
||||
|
||||
serializeContext->Class< CReflectedVarAny<T>, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("value", &CReflectedVarAny<T>::m_value);
|
||||
|
||||
AZ::EditContext* ec = serializeContext->GetEditContext();
|
||||
if (ec)
|
||||
{
|
||||
ec->Class< CReflectedVarAny<T> >("VarAny", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CReflectedVarAny<T>::m_value, "Value", "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarAny<T>::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarAny<T>::description)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, class R>
|
||||
void CReflectedVarRanged<T, R>::reflect(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
static bool reflected = false;
|
||||
if (reflected)
|
||||
return;
|
||||
reflected = true;
|
||||
|
||||
serializeContext->Class< CReflectedVarRanged<T, R>, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("value", &CReflectedVarRanged<T, R>::m_value)
|
||||
->Field("min", &CReflectedVarRanged<T, R>::m_minVal)
|
||||
->Field("max", &CReflectedVarRanged<T, R>::m_maxVal)
|
||||
->Field("step", &CReflectedVarRanged<T, R>::m_stepSize)
|
||||
->Field("softMin", &CReflectedVarRanged<T, R>::m_softMinVal)
|
||||
->Field("softMax", &CReflectedVarRanged<T, R>::m_softMaxVal)
|
||||
;
|
||||
|
||||
AZ::EditContext* ec = serializeContext->GetEditContext();
|
||||
if (ec)
|
||||
{
|
||||
ec->Class< CReflectedVarRanged<T, R> >("VarAny", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::Slider, &CReflectedVarRanged<T, R>::m_value, "Value", "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarRanged<T, R>::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarRanged<T, R>::description)
|
||||
->Attribute(AZ::Edit::Attributes::Min, &CReflectedVarRanged<T, R>::minValue)
|
||||
->Attribute(AZ::Edit::Attributes::Max, &CReflectedVarRanged<T, R>::maxValue)
|
||||
->Attribute(AZ::Edit::Attributes::Step, &CReflectedVarRanged<T, R>::stepSize)
|
||||
->Attribute(AZ::Edit::Attributes::SoftMin, &CReflectedVarRanged<T, R>::softMinVal)
|
||||
->Attribute(AZ::Edit::Attributes::SoftMax, &CReflectedVarRanged<T, R>::softMaxVal)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void CReflectedVarEnum<T>::reflect(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
static bool reflected = false;
|
||||
if (reflected)
|
||||
return;
|
||||
reflected = true;
|
||||
|
||||
serializeContext->Class< CReflectedVarEnum<T>, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("value", &CReflectedVarEnum<T>::m_value)
|
||||
->Field("selectedName", &CReflectedVarEnum<T>::m_selectedEnumName)
|
||||
->Field("availableValues", &CReflectedVarEnum<T>::m_enums)
|
||||
;
|
||||
|
||||
AZ::EditContext* ec = serializeContext->GetEditContext();
|
||||
if (ec)
|
||||
{
|
||||
ec->Class< CReflectedVarEnum<T> >("Enum Variable", "")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &CReflectedVarEnum<T>::m_selectedEnumName, "Value", "")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &CReflectedVarEnum<T>::GetEnums)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &CReflectedVarEnum<T>::OnEnumChanged)
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarEnum<T>::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarEnum<T>::description)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CReflectedVarGenericProperty::reflect(AZ::SerializeContext* serializeContext)
|
||||
{
|
||||
static bool reflected = false;
|
||||
if (reflected)
|
||||
return;
|
||||
reflected = true;
|
||||
|
||||
serializeContext->Class< CReflectedVarGenericProperty, CReflectedVar>()
|
||||
->Version(1)
|
||||
->Field("value", &CReflectedVarGenericProperty::m_value)
|
||||
->Field("propertyType", &CReflectedVarGenericProperty::m_propertyType)
|
||||
;
|
||||
|
||||
AZ::EditContext* ec = serializeContext->GetEditContext();
|
||||
if (ec)
|
||||
{
|
||||
ec->Class< CReflectedVarGenericProperty >("GenericProperty", "GenericProperty")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarGenericProperty::varName)
|
||||
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarGenericProperty::description)
|
||||
->Attribute(AZ::Edit::Attributes::Handler, &CReflectedVarGenericProperty::handler)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AZ::u32 CReflectedVarSpline::handler()
|
||||
{
|
||||
switch (m_propertyType)
|
||||
{
|
||||
case ePropertyFloatCurve:
|
||||
return AZ_CRC("ePropertyFloatCurve", 0x7440ccce);
|
||||
case ePropertyColorCurve:
|
||||
return AZ_CRC("ePropertyColorCurve", 0xa30da4ec);
|
||||
default:
|
||||
AZ_Assert(false, "CReflectedVarSpline property type must be ePropertyFloatCurve or ePropertyColorCurve");
|
||||
return AZ::Edit::UIHandlers::Default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AZ::u32 CReflectedVarGenericProperty::handler()
|
||||
{
|
||||
switch (m_propertyType)
|
||||
{
|
||||
case ePropertyShader:
|
||||
return AZ_CRC("ePropertyShader", 0xc40932f1);
|
||||
case ePropertyEquip:
|
||||
return AZ_CRC("ePropertyEquip", 0x66ffd290);
|
||||
case ePropertyReverbPreset:
|
||||
return AZ_CRC("ePropertyReverbPreset", 0x51469f38);
|
||||
case ePropertyDeprecated0:
|
||||
return AZ_CRC("ePropertyCustomAction", 0x4ffa5ba5);
|
||||
case ePropertyGameToken:
|
||||
return AZ_CRC("ePropertyGameToken", 0x34855b6f);
|
||||
case ePropertyMissionObj:
|
||||
return AZ_CRC("ePropertyMissionObj", 0x4a2d0dc8);
|
||||
case ePropertySequence:
|
||||
return AZ_CRC("ePropertySequence", 0xdd1c7d44);
|
||||
case ePropertySequenceId:
|
||||
return AZ_CRC("ePropertySequenceId", 0x05983dcc);
|
||||
case ePropertyLocalString:
|
||||
return AZ_CRC("ePropertyLocalString", 0x0cd9609a);
|
||||
case ePropertyLightAnimation:
|
||||
return AZ_CRC("ePropertyLightAnimation", 0x277097da);
|
||||
case ePropertyParticleName:
|
||||
return AZ_CRC("ePropertyParticleName", 0xf44c7133);
|
||||
default:
|
||||
AZ_Assert(false, "No property handlers defined for the property type");
|
||||
return AZ_CRC("Default", 0xe35e00df);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPropertyContainer::AddProperty(CReflectedVar *property)
|
||||
{
|
||||
if (property)
|
||||
m_properties.push_back(property);
|
||||
}
|
||||
|
||||
void CPropertyContainer::Clear()
|
||||
{
|
||||
m_properties.clear();
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_REFLECTEDVAR_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_REFLECTEDVAR_H
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include "Util/VariablePropertyType.h"
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Vector4.h>
|
||||
|
||||
|
||||
//Base class for generic reflected variables
|
||||
class CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVar, "{9CF461B5-4093-4F7E-9A28-75531F0D046C}")
|
||||
|
||||
CReflectedVar() = default;
|
||||
CReflectedVar(const AZStd::string& name)
|
||||
: m_varName(name){}
|
||||
virtual ~CReflectedVar(){}
|
||||
|
||||
AZStd::string m_varName;
|
||||
AZStd::string m_description;
|
||||
};
|
||||
|
||||
|
||||
// Reflected container of reflected values. Also holds ePropertyTable data
|
||||
class CPropertyContainer
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CPropertyContainer, "{99500790-241A-4274-BAD8-C4510E869FC6}", CReflectedVar)
|
||||
CPropertyContainer(const AZStd::string& name)
|
||||
: CReflectedVar(name) {}
|
||||
CPropertyContainer() = default;
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
void AddProperty(CReflectedVar* property);
|
||||
|
||||
void Clear();
|
||||
|
||||
//If we're an unnamed container, just show our children in flat list. Otherwise show the container name with children underneath
|
||||
AZ::u32 GetVisibility() const
|
||||
{
|
||||
return m_varName.empty() ? AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20) : AZ_CRC("PropertyVisibility_Show", 0xa43c82dd);
|
||||
}
|
||||
|
||||
void SetAutoExpand(bool autoExpand) { m_autoExpand = autoExpand; }
|
||||
bool AutoExpand() const { return m_autoExpand; }
|
||||
|
||||
AZStd::vector<CReflectedVar*> GetProperties() const { return m_properties; }
|
||||
|
||||
void SetValueText(const AZStd::string& valueText) { m_valueText = valueText; }
|
||||
|
||||
friend class ReflectedVarInit;
|
||||
|
||||
private:
|
||||
AZStd::vector<CReflectedVar*> m_properties;
|
||||
bool m_autoExpand = false;
|
||||
AZStd::string m_valueText;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
class CReflectedVarAny
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI((CReflectedVarAny<T>, "{EE8293C3-9B1E-470B-9922-2CBB8DA13D78}", T), CReflectedVar)
|
||||
|
||||
CReflectedVarAny(const AZStd::string& name, const T& val = T())
|
||||
: CReflectedVar(name)
|
||||
, m_value(val) {}
|
||||
CReflectedVarAny() = default;
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
static void reflect(AZ::SerializeContext* serializeContext);
|
||||
|
||||
T m_value;
|
||||
};
|
||||
|
||||
// Class to hold values that have min/max
|
||||
// T = data type held in this variable
|
||||
// R = data type of the range
|
||||
template<class T, class R>
|
||||
class CReflectedVarRanged
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI((CReflectedVarRanged, "{6AB4EC29-E17B-4B3B-A153-BFDAA48B8CF8}", T, R), CReflectedVar)
|
||||
|
||||
CReflectedVarRanged(const AZStd::string& name, const T& val = T())
|
||||
: CReflectedVar(name)
|
||||
, m_value(val)
|
||||
, m_minVal(std::numeric_limits<R>::lowest())
|
||||
, m_maxVal(std::numeric_limits<R>::max())
|
||||
, m_stepSize(1)
|
||||
, m_softMinVal(std::numeric_limits<R>::lowest())
|
||||
, m_softMaxVal(std::numeric_limits<R>::max())
|
||||
{}
|
||||
CReflectedVarRanged()
|
||||
: CReflectedVarRanged(AZStd::string(), T()){}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
R minValue() const { return m_minVal; }
|
||||
R maxValue() const { return m_maxVal; }
|
||||
R stepSize() const { return m_stepSize; }
|
||||
R softMinVal() const { return m_softMinVal; }
|
||||
R softMaxVal() const { return m_softMaxVal; }
|
||||
|
||||
static void reflect(AZ::SerializeContext* serializeContext);
|
||||
|
||||
T m_value;
|
||||
R m_minVal;
|
||||
R m_maxVal;
|
||||
R m_stepSize;
|
||||
R m_softMinVal;
|
||||
R m_softMaxVal;
|
||||
};
|
||||
|
||||
//name some commonly-used variable types
|
||||
template <class T>
|
||||
using CReflectedVarNumeric = CReflectedVarRanged<T, T>;
|
||||
|
||||
//ePropertyFloat
|
||||
using CReflectedVarFloat = CReflectedVarNumeric<float>;
|
||||
|
||||
//ePropertyInt
|
||||
using CReflectedVarInt = CReflectedVarNumeric<int>;
|
||||
|
||||
//ePropertyString
|
||||
using CReflectedVarString = CReflectedVarAny<AZStd::string>;
|
||||
|
||||
//ePropertyBool
|
||||
using CReflectedVarBool = CReflectedVarAny<bool>;
|
||||
|
||||
//ePropertyVector2
|
||||
using CReflectedVarVector2 = CReflectedVarRanged<AZ::Vector2, float>;
|
||||
|
||||
//ePropertyVector
|
||||
using CReflectedVarVector3 = CReflectedVarRanged<AZ::Vector3, float>;
|
||||
|
||||
//ePropertyVector4
|
||||
using CReflectedVarVector4 = CReflectedVarRanged<AZ::Vector4, float>;
|
||||
|
||||
// Class for holding enumerated values, ePropertySelection
|
||||
// Keeps a key-value pair values (int, string, float, etc) and names corresponding to each value
|
||||
// The names are displayed to user when editing, the values are used by underlying code.
|
||||
|
||||
template<class T>
|
||||
class CReflectedVarEnum
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI((CReflectedVarEnum<T>, "{40AE7D74-7E3A-41A9-8F71-2BBC3067118B}", T), CReflectedVar)
|
||||
|
||||
CReflectedVarEnum(const AZStd::string& name)
|
||||
: CReflectedVar(name) {}
|
||||
CReflectedVarEnum() = default;
|
||||
|
||||
void setEnums(const AZStd::vector<AZStd::pair<T, AZStd::string> >& enums)
|
||||
{
|
||||
m_enums = enums;
|
||||
if (m_enums.size() > 0)
|
||||
{
|
||||
m_value = m_enums.at(0).first;
|
||||
m_selectedEnumName = m_enums.at(0).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value = T();
|
||||
m_selectedEnumName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void addEnum(const T& value, const AZStd::string& name)
|
||||
{
|
||||
m_enums.push_back(AZStd::pair<T, AZStd::string>(value, name));
|
||||
if (m_enums.size() == 1)
|
||||
{
|
||||
m_selectedEnumName = name;
|
||||
m_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
void setEnumValue(const T& value)
|
||||
{
|
||||
auto it = std::find_if(m_enums.cbegin(), m_enums.cend(), [value](const AZStd::pair<T, AZStd::string>& item) -> bool { return item.first == value; });
|
||||
if (it != m_enums.end())
|
||||
{
|
||||
m_value = it->first;
|
||||
m_selectedEnumName = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void setEnumByName(const AZStd::string& name)
|
||||
{
|
||||
auto it = std::find_if(m_enums.cbegin(), m_enums.cend(), [name](const AZStd::pair<T, AZStd::string>& item) -> bool { return item.second == name; });
|
||||
if (it != m_enums.end())
|
||||
{
|
||||
m_value = it->first;
|
||||
m_selectedEnumName = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void OnEnumChanged()
|
||||
{
|
||||
setEnumByName(m_selectedEnumName);
|
||||
}
|
||||
|
||||
AZStd::vector < AZStd::string> GetEnums() const
|
||||
{
|
||||
AZStd::vector < AZStd::string> returnVal;
|
||||
for (const auto& i : m_enums)
|
||||
{
|
||||
returnVal.push_back(i.second);
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
static void reflect(AZ::SerializeContext* serializeContext);
|
||||
|
||||
T m_value;
|
||||
AZStd::string m_selectedEnumName;
|
||||
AZStd::vector<AZStd::pair<T, AZStd::string> > m_enums;
|
||||
};
|
||||
|
||||
//Class to hold ePropertyColor (IVariable::DT_COLOR)
|
||||
class CReflectedVarColor
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarColor, "{CC69E773-B4FA-4B6D-8A46-0B580097B6D2}", CReflectedVar)
|
||||
|
||||
CReflectedVarColor(const AZStd::string& name, AZ::Vector3 color = AZ::Vector3())
|
||||
: CReflectedVar(name)
|
||||
, m_color(color) {}
|
||||
CReflectedVarColor() {}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
AZ::Vector3 m_color;
|
||||
};
|
||||
|
||||
//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
|
||||
class CReflectedVarAnimation
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarAnimation, "{635D982E-23EC-463F-8F33-4FC2C19D5673}", CReflectedVar)
|
||||
|
||||
CReflectedVarAnimation(const AZStd::string& name)
|
||||
: CReflectedVar(name)
|
||||
, m_entityID(0)
|
||||
{}
|
||||
CReflectedVarAnimation()
|
||||
: m_entityID(0){}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
AZStd::string m_animation;
|
||||
AZ::EntityId m_entityID;
|
||||
};
|
||||
|
||||
//Class to hold:
|
||||
// ePropertyTexture (IVariable::DT_TEXTURE)
|
||||
// ePropertyMaterial (IVariable::DT_MATERIAL)
|
||||
// ePropertyModel (IVariable::DT_OBJECT)
|
||||
// ePropertyGeomCache (IVariable::DT_GEOM_CACHE)
|
||||
// ePropertyAudioTrigger (IVariable::DT_AUDIO_TRIGGER)
|
||||
// ePropertyAudioSwitch (IVariable::DT_AUDIO_SWITCH )
|
||||
// ePropertyAudioSwitchState (IVariable::DT_AUDIO_SWITCH_STATE)
|
||||
// ePropertyAudioRTPC (IVariable::DT_AUDIO_RTPC)
|
||||
// ePropertyAudioEnvironment (IVariable::DT_AUDIO_ENVIRONMENT)
|
||||
// ePropertyAudioPreloadRequest (IVariable::DT_AUDIO_PRELOAD_REQUEST)
|
||||
|
||||
class CReflectedVarResource
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarResource, "{162864C2-0C3E-4B6A-84D3-BBAD975B4FD2}", CReflectedVar)
|
||||
|
||||
CReflectedVarResource(const AZStd::string& name)
|
||||
: CReflectedVar(name)
|
||||
, m_propertyType(ePropertyInvalid)
|
||||
{}
|
||||
CReflectedVarResource()
|
||||
: m_propertyType(ePropertyInvalid){}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
AZStd::string m_path;
|
||||
PropertyType m_propertyType;
|
||||
};
|
||||
|
||||
//Class to hold ePropertyUser (IVariable::DT_USERITEMCB)
|
||||
class CReflectedVarUser
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarUser, "{A901DA91-3893-4848-9AE8-62C0ED074970}", CReflectedVar)
|
||||
|
||||
CReflectedVarUser(const AZStd::string &name)
|
||||
: CReflectedVar(name)
|
||||
, m_enableEdit(false)
|
||||
, m_useTree(false)
|
||||
{}
|
||||
CReflectedVarUser() : m_enableEdit(false), m_useTree(false) {}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
|
||||
AZStd::string m_value;
|
||||
|
||||
bool m_enableEdit;
|
||||
bool m_useTree;
|
||||
AZStd::string m_dialogTitle;
|
||||
AZStd::string m_treeSeparator;
|
||||
AZStd::vector<AZStd::string> m_itemNames;
|
||||
AZStd::vector<AZStd::string> m_itemDescriptions;
|
||||
};
|
||||
|
||||
//Class to hold ePropertyAnimation (IVariable::DT_ANIMATION )
|
||||
class CReflectedVarSpline
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarSpline, "{9A928683-7C84-48BF-8A2E-F7BEC423EE4E}", CReflectedVar)
|
||||
|
||||
CReflectedVarSpline(PropertyType propertyType, const AZStd::string &name)
|
||||
: CReflectedVar(name)
|
||||
, m_spline(0)
|
||||
, m_propertyType(propertyType)
|
||||
{}
|
||||
|
||||
CReflectedVarSpline()
|
||||
: m_spline(0)
|
||||
, m_propertyType(ePropertyInvalid)
|
||||
{}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZ::u32 handler();
|
||||
|
||||
uint64_t m_spline;
|
||||
PropertyType m_propertyType;
|
||||
};
|
||||
|
||||
//Class to wrap all the many properties that can be represented by a string and edited via a popup
|
||||
class CReflectedVarGenericProperty
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarGenericProperty, "{C4A34C95-3D71-40CE-86D2-DDE314B33CC5}", CReflectedVar)
|
||||
|
||||
CReflectedVarGenericProperty(PropertyType pType, const AZStd::string& name = AZStd::string(), const AZStd::string& val = AZStd::string())
|
||||
: CReflectedVar(name)
|
||||
, m_propertyType(pType)
|
||||
, m_value(val) {}
|
||||
CReflectedVarGenericProperty()
|
||||
: CReflectedVar()
|
||||
, m_propertyType(ePropertyInvalid){}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
PropertyType propertyType() const { return m_propertyType; }
|
||||
|
||||
AZ::u32 handler();
|
||||
|
||||
static void reflect(AZ::SerializeContext* serializeContext);
|
||||
|
||||
PropertyType m_propertyType;
|
||||
AZStd::string m_value;
|
||||
};
|
||||
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarInit
|
||||
{
|
||||
public:
|
||||
static void setupReflection(AZ::SerializeContext* serializeContext);
|
||||
private:
|
||||
static bool s_reflectionDone;
|
||||
};
|
||||
|
||||
//Class to hold ePropertyMotion (IVariable::DT_MOTION )
|
||||
class CReflectedVarMotion
|
||||
: public CReflectedVar
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CReflectedVarMotion, "{66397EFB-620A-40B8-8C66-D6AECF690DF5}", CReflectedVar)
|
||||
|
||||
CReflectedVarMotion(const AZStd::string& name)
|
||||
: CReflectedVar(name)
|
||||
, m_assetId(0) {}
|
||||
|
||||
CReflectedVarMotion()
|
||||
: m_assetId(0) {}
|
||||
|
||||
AZStd::string varName() const { return m_varName; }
|
||||
AZStd::string description() const { return m_description; }
|
||||
|
||||
AZStd::string m_motion;
|
||||
AZ::Data::AssetId m_assetId;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_REFLECTEDVAR_H
|
||||
@@ -0,0 +1,579 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EditorDefs.h"
|
||||
|
||||
#include "ReflectedVarWrapper.h"
|
||||
|
||||
// AzCore
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
|
||||
// Editor
|
||||
#include "ReflectedPropertyCtrl.h"
|
||||
#include "UIEnumsDatabase.h"
|
||||
|
||||
namespace {
|
||||
|
||||
//setting the IVariable to itself in property items was trigger to update limits for that variable.
|
||||
//limits were obtained using IVariable::GetLimits instead of from the Prop::Description
|
||||
template <class T, class R>
|
||||
void setRangeParams(CReflectedVarRanged<T, R> *reflectedVar, IVariable *pVariable, bool updatingExistingVariable = false)
|
||||
{
|
||||
float min, max, step;
|
||||
bool hardMin, hardMax;
|
||||
if (updatingExistingVariable)
|
||||
{
|
||||
pVariable->GetLimits(min, max, step, hardMin, hardMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
Prop::Description desc(pVariable);
|
||||
min = desc.m_rangeMin;
|
||||
max = desc.m_rangeMax;
|
||||
step = desc.m_step;
|
||||
hardMin = desc.m_bHardMin;
|
||||
hardMax = desc.m_bHardMax;
|
||||
}
|
||||
reflectedVar->m_softMinVal = min;
|
||||
reflectedVar->m_softMaxVal = max;
|
||||
|
||||
if (hardMin)
|
||||
{
|
||||
reflectedVar->m_minVal = min;
|
||||
}
|
||||
else
|
||||
{
|
||||
reflectedVar->m_minVal = std::numeric_limits<int>::lowest();
|
||||
}
|
||||
if (hardMax)
|
||||
{
|
||||
reflectedVar->m_maxVal = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is an issue with assigning std::numeric_limits<int>::max() to a float
|
||||
// A float can't actually represent the value of 2147483647 and clang
|
||||
// compilers actually warn on this fact.
|
||||
// A static_cast is used here to indicate explicit acceptance of the value change here
|
||||
/* The clang compiler warning is below
|
||||
../Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp:59:38: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Werror,-Wimplicit-int-float-conversion]
|
||||
reflectedVar->m_maxVal = std::numeric_limits<int>::max();
|
||||
*/
|
||||
reflectedVar->m_maxVal = static_cast<float>(std::numeric_limits<int>::max());
|
||||
}
|
||||
reflectedVar->m_stepSize = step;
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedVarIntAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarInt(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateRangeLimits(pVariable);
|
||||
Prop::Description desc(pVariable);
|
||||
m_valueMultiplier = desc.m_valueMultiplier;
|
||||
}
|
||||
|
||||
void ReflectedVarIntAdapter::UpdateRangeLimits(IVariable *pVariable)
|
||||
{
|
||||
setRangeParams<int>(m_reflectedVar.data(), pVariable);
|
||||
}
|
||||
|
||||
void ReflectedVarIntAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
float value;
|
||||
if (pVariable->GetType() == IVariable::FLOAT)
|
||||
{
|
||||
pVariable->Get(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int intValue;
|
||||
pVariable->Get(intValue);
|
||||
value = intValue;
|
||||
}
|
||||
m_reflectedVar->m_value = std::round(value * m_valueMultiplier);
|
||||
}
|
||||
|
||||
void ReflectedVarIntAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
//don't round here. Often the IVariable is actually a float under-the hood
|
||||
//for example: DT_PERCENT is stored in float (0 to 1) but has ePropertyType::Integer because editor should be an integer editor ranging from 0 to 100.
|
||||
pVariable->Set(m_reflectedVar->m_value / m_valueMultiplier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ReflectedVarFloatAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarFloat(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateRangeLimits(pVariable);
|
||||
Prop::Description desc(pVariable);
|
||||
m_valueMultiplier = desc.m_valueMultiplier;
|
||||
}
|
||||
|
||||
void ReflectedVarFloatAdapter::UpdateRangeLimits(IVariable *pVariable)
|
||||
{
|
||||
setRangeParams<float>(m_reflectedVar.data(), pVariable);
|
||||
}
|
||||
|
||||
void ReflectedVarFloatAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
float value;
|
||||
pVariable->Get(value);
|
||||
m_reflectedVar->m_value = value * m_valueMultiplier;
|
||||
}
|
||||
|
||||
void ReflectedVarFloatAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(m_reflectedVar->m_value/m_valueMultiplier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ReflectedVarStringAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarString(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarStringAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
QString value;
|
||||
pVariable->Get(value);
|
||||
m_reflectedVar->m_value = value.toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarStringAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(m_reflectedVar->m_value.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ReflectedVarBoolAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarBool(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarBoolAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
bool value;
|
||||
pVariable->Get(value);
|
||||
m_reflectedVar->m_value = value;
|
||||
}
|
||||
|
||||
void ReflectedVarBoolAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(m_reflectedVar->m_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ReflectedVarEnumAdapter::ReflectedVarEnumAdapter()
|
||||
: m_updatingEnums(false)
|
||||
, m_pVariable(nullptr)
|
||||
{}
|
||||
|
||||
void ReflectedVarEnumAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_pVariable = pVariable;
|
||||
Prop::Description desc(pVariable);
|
||||
m_enumList = desc.m_enumList;
|
||||
m_reflectedVar.reset(new CReflectedVarEnum<AZStd::string>(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateReflectedVarEnums();
|
||||
}
|
||||
|
||||
bool ReflectedVarEnumAdapter::UpdateReflectedVarEnums()
|
||||
{
|
||||
if (!m_pVariable || m_updatingEnums)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_updatingEnums = true;
|
||||
//Allow derived classes to populate the IVariable's enumList
|
||||
updateIVariableEnumList(m_pVariable);
|
||||
m_enumList = m_pVariable->GetEnumList();
|
||||
m_updatingEnums = false;
|
||||
|
||||
bool changed = false;
|
||||
//Copy the updated enums to the ReflecteVar
|
||||
if (m_enumList)
|
||||
{
|
||||
const AZStd::vector<AZStd::string> oldEnums = m_reflectedVar->GetEnums();
|
||||
|
||||
AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>> enums;
|
||||
for (uint i = 0; !m_enumList->GetItemName(i).isNull(); i++)
|
||||
{
|
||||
QString sEnumName = m_enumList->GetItemName(i);
|
||||
enums.push_back(AZStd::pair<AZStd::string, AZStd::string>(sEnumName.toUtf8().data(), sEnumName.toUtf8().data()));
|
||||
|
||||
}
|
||||
m_reflectedVar->setEnums(enums);
|
||||
|
||||
changed = m_reflectedVar->GetEnums() != oldEnums;
|
||||
if (changed)
|
||||
{
|
||||
// set the current enum value from the IVariable
|
||||
SyncReflectedVarToIVar(m_pVariable);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ReflectedVarEnumAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
const AZStd::string value = pVariable->GetDisplayValue().toUtf8().data();
|
||||
m_reflectedVar->setEnumByName(value);
|
||||
}
|
||||
|
||||
void ReflectedVarEnumAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
QString iVarVal = m_reflectedVar->m_selectedEnumName.c_str();
|
||||
pVariable->SetDisplayValue(iVarVal);
|
||||
}
|
||||
|
||||
void ReflectedVarEnumAdapter::OnVariableChange([[maybe_unused]] IVariable* pVariable)
|
||||
{
|
||||
//setting the enums on the pVariable will cause the variable to change getting us back here
|
||||
//The original property editor did need to update things immediately because it did so when creating the in-place editing control
|
||||
if (!m_updatingEnums)
|
||||
{
|
||||
UpdateReflectedVarEnums();
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedVarDBEnumAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
Prop::Description desc(pVariable);
|
||||
m_pEnumDBItem = desc.m_pEnumDBItem;
|
||||
m_reflectedVar.reset(new CReflectedVarEnum<AZStd::string>(pVariable->GetHumanName().toUtf8().data()));
|
||||
if (m_pEnumDBItem)
|
||||
{
|
||||
for (int i = 0; i < m_pEnumDBItem->strings.size(); i++)
|
||||
{
|
||||
QString name = m_pEnumDBItem->strings[i];
|
||||
m_reflectedVar->addEnum( m_pEnumDBItem->NameToValue(name).toUtf8().data(), name.toUtf8().data() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedVarDBEnumAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
const AZStd::string valueStr = pVariable->GetDisplayValue().toUtf8().data();
|
||||
const AZStd::string value = m_pEnumDBItem ? AZStd::string(m_pEnumDBItem->ValueToName(valueStr.c_str()).toUtf8().data()) : valueStr;
|
||||
m_reflectedVar->setEnumByName(value);
|
||||
|
||||
}
|
||||
|
||||
void ReflectedVarDBEnumAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
QString iVarVal = m_reflectedVar->m_selectedEnumName.c_str();
|
||||
if (m_pEnumDBItem)
|
||||
{
|
||||
iVarVal = m_pEnumDBItem->NameToValue(iVarVal);
|
||||
}
|
||||
pVariable->SetDisplayValue(iVarVal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ReflectedVarVector2Adapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarVector2(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateRangeLimits(pVariable);
|
||||
}
|
||||
|
||||
void ReflectedVarVector2Adapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
Vec2 vec;
|
||||
pVariable->Get(vec);
|
||||
m_reflectedVar->m_value = AZ::Vector2(vec.x, vec.y);
|
||||
}
|
||||
|
||||
void ReflectedVarVector2Adapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(Vec2(m_reflectedVar->m_value.GetX(), m_reflectedVar->m_value.GetY()));
|
||||
}
|
||||
|
||||
|
||||
void ReflectedVarVector3Adapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarVector3(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateRangeLimits(pVariable);
|
||||
}
|
||||
|
||||
void ReflectedVarVector3Adapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
Vec3 vec;
|
||||
pVariable->Get(vec);
|
||||
m_reflectedVar->m_value = AZ::Vector3(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
void ReflectedVarVector3Adapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(Vec3(m_reflectedVar->m_value.GetX(), m_reflectedVar->m_value.GetY(), m_reflectedVar->m_value.GetZ()));
|
||||
}
|
||||
|
||||
|
||||
void ReflectedVarVector4Adapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarVector4(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
UpdateRangeLimits(pVariable);
|
||||
}
|
||||
|
||||
void ReflectedVarVector4Adapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
Vec4 vec;
|
||||
pVariable->Get(vec);
|
||||
m_reflectedVar->m_value = AZ::Vector4(vec.x, vec.y, vec.z, vec.w);
|
||||
}
|
||||
|
||||
void ReflectedVarVector4Adapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(Vec4(m_reflectedVar->m_value.GetX(), m_reflectedVar->m_value.GetY(), m_reflectedVar->m_value.GetZ(), m_reflectedVar->m_value.GetW()));
|
||||
}
|
||||
|
||||
|
||||
void ReflectedVarColorAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarColor(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarColorAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
if (pVariable->GetType() == IVariable::VECTOR)
|
||||
{
|
||||
Vec3 v(0, 0, 0);
|
||||
pVariable->Get(v);
|
||||
const QColor col = ColorLinearToGamma(ColorF(v.x, v.y, v.z));
|
||||
m_reflectedVar->m_color.Set(col.redF(), col.greenF(), col.blueF());
|
||||
}
|
||||
else
|
||||
{
|
||||
int col(0);
|
||||
pVariable->Get(col);
|
||||
const QColor qcolor = ColorToQColor((uint32)col);
|
||||
m_reflectedVar->m_color.Set(qcolor.redF(), qcolor.greenF(), qcolor.blueF());
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedVarColorAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
if (pVariable->GetType() == IVariable::VECTOR)
|
||||
{
|
||||
ColorF colLin = ColorGammaToLinear(QColor::fromRgbF(m_reflectedVar->m_color.GetX(), m_reflectedVar->m_color.GetY(), m_reflectedVar->m_color.GetZ()));
|
||||
pVariable->Set(Vec3(colLin.r, colLin.g, colLin.b));
|
||||
}
|
||||
else
|
||||
{
|
||||
int ir = m_reflectedVar->m_color.GetX() * 255.0f;
|
||||
int ig = m_reflectedVar->m_color.GetY() * 255.0f;
|
||||
int ib = m_reflectedVar->m_color.GetZ() * 255.0f;
|
||||
|
||||
pVariable->Set(static_cast<int>(RGB(ir, ig, ib)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ReflectedVarAnimationAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarAnimation(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarAnimationAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar->m_entityID = static_cast<AZ::EntityId>(pVariable->GetUserData().value<AZ::u64>());
|
||||
m_reflectedVar->m_animation = pVariable->GetDisplayValue().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarAnimationAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->SetUserData(static_cast<AZ::u64>(m_reflectedVar->m_entityID));
|
||||
pVariable->SetDisplayValue(m_reflectedVar->m_animation.c_str());
|
||||
|
||||
}
|
||||
|
||||
void ReflectedVarResourceAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarResource(pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarResourceAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
QString path;
|
||||
pVariable->Get(path);
|
||||
m_reflectedVar->m_path = path.toUtf8().data();
|
||||
Prop::Description desc(pVariable);
|
||||
m_reflectedVar->m_propertyType = desc.m_type;
|
||||
|
||||
}
|
||||
|
||||
void ReflectedVarResourceAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
const bool bForceModified = (m_reflectedVar->m_propertyType == ePropertyGeomCache);
|
||||
pVariable->SetForceModified(bForceModified);
|
||||
pVariable->SetDisplayValue(m_reflectedVar->m_path.c_str());
|
||||
|
||||
//shouldn't be able to change the type, so ignore m_reflecatedVar->m_properyType
|
||||
}
|
||||
|
||||
|
||||
ReflectedVarGenericPropertyAdapter::ReflectedVarGenericPropertyAdapter(PropertyType propertyType)
|
||||
:m_propertyType(propertyType)
|
||||
{}
|
||||
|
||||
void ReflectedVarGenericPropertyAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarGenericProperty(m_propertyType, pVariable->GetHumanName().toUtf8().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarGenericPropertyAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
QString value;
|
||||
pVariable->Get(value);
|
||||
|
||||
m_reflectedVar->m_value = value.toUtf8().data();
|
||||
}
|
||||
|
||||
void ReflectedVarGenericPropertyAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(m_reflectedVar->m_value.c_str());
|
||||
}
|
||||
|
||||
void ReflectedVarUserAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarUser( pVariable->GetHumanName().toUtf8().data()));
|
||||
}
|
||||
|
||||
void ReflectedVarUserAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
QString value;
|
||||
pVariable->Get(value);
|
||||
m_reflectedVar->m_value = value.toUtf8().data();
|
||||
|
||||
//extract the list of custom items from the IVariable user data
|
||||
IVariable::IGetCustomItems* pGetCustomItems = static_cast<IVariable::IGetCustomItems*> (pVariable->GetUserData().value<void *>());
|
||||
if (pGetCustomItems != 0)
|
||||
{
|
||||
std::vector<IVariable::IGetCustomItems::SItem> items;
|
||||
QString dlgTitle;
|
||||
// call the user supplied callback to fill-in items and get dialog title
|
||||
bool bShowIt = pGetCustomItems->GetItems(pVariable, items, dlgTitle);
|
||||
if (bShowIt) // if func didn't veto, show the dialog
|
||||
{
|
||||
m_reflectedVar->m_enableEdit = true;
|
||||
m_reflectedVar->m_useTree = pGetCustomItems->UseTree();
|
||||
m_reflectedVar->m_treeSeparator = pGetCustomItems->GetTreeSeparator();
|
||||
m_reflectedVar->m_dialogTitle = dlgTitle.toUtf8().data();
|
||||
m_reflectedVar->m_itemNames.resize(items.size());
|
||||
m_reflectedVar->m_itemDescriptions.resize(items.size());
|
||||
|
||||
QByteArray ba;
|
||||
int i = -1;
|
||||
std::generate(m_reflectedVar->m_itemNames.begin(), m_reflectedVar->m_itemNames.end(), [&items, &i, &ba]() { ++i; ba = items[i].name.toUtf8(); return ba.data(); });
|
||||
i = -1;
|
||||
std::generate(m_reflectedVar->m_itemDescriptions.begin(), m_reflectedVar->m_itemDescriptions.end(), [&items, &i, &ba]() { ++i; ba = items[i].desc.toUtf8(); return ba.data(); });
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reflectedVar->m_enableEdit = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ReflectedVarUserAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->Set(m_reflectedVar->m_value.c_str());
|
||||
}
|
||||
|
||||
|
||||
ReflectedVarSplineAdapter::ReflectedVarSplineAdapter(ReflectedPropertyItem *parentItem, PropertyType propertyType)
|
||||
: m_propertyType(propertyType)
|
||||
, m_bDontSendToControl(false)
|
||||
, m_parentItem(parentItem)
|
||||
{
|
||||
}
|
||||
|
||||
void ReflectedVarSplineAdapter::SetVariable(IVariable* pVariable)
|
||||
{
|
||||
m_reflectedVar.reset(new CReflectedVarSpline(m_propertyType, pVariable->GetHumanName().toUtf8().data()));
|
||||
|
||||
}
|
||||
|
||||
void ReflectedVarSplineAdapter::SyncReflectedVarToIVar(IVariable* pVariable)
|
||||
{
|
||||
if (!m_bDontSendToControl)
|
||||
{
|
||||
m_reflectedVar->m_spline = reinterpret_cast<uint64_t>(pVariable->GetSpline());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReflectedVarSplineAdapter::SyncIVarToReflectedVar(IVariable* pVariable)
|
||||
{
|
||||
// Splines update variables directly so don't call OnVariableChange or SetValue here or values will be overwritten.
|
||||
|
||||
// Call OnSetValue to force this field to notify this variable that its model has changed without going through the
|
||||
// full OnVariableChange pass
|
||||
//
|
||||
// Set m_bDontSendToControl to prevent the control's data from being overwritten (as the variable's data won't
|
||||
// necessarily be up to date vs the controls at the point this happens).
|
||||
m_bDontSendToControl = true;
|
||||
pVariable->OnSetValue(false);
|
||||
m_bDontSendToControl = false;
|
||||
|
||||
m_parentItem->SendOnItemChange();
|
||||
}
|
||||
|
||||
void ReflectedVarMotionAdapter::SetVariable(IVariable *pVariable)
|
||||
{
|
||||
// Create new reflected var
|
||||
m_reflectedVar.reset(new CReflectedVarMotion(pVariable->GetHumanName().toLatin1().data()));
|
||||
m_reflectedVar->m_description = pVariable->GetDescription().toLatin1().data();
|
||||
|
||||
// Set the asset id
|
||||
AZStd::string stringGuid = pVariable->GetDisplayValue().toLatin1().data();
|
||||
AZ::Uuid guid(stringGuid.c_str(), stringGuid.length());
|
||||
AZ::u32 subId = pVariable->GetUserData().value<AZ::u32>();
|
||||
m_reflectedVar->m_assetId = AZ::Data::AssetId(guid, subId);
|
||||
|
||||
// Lookup Filename by assetId and get the filename part of the description
|
||||
EBUS_EVENT_RESULT(m_reflectedVar->m_motion, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, m_reflectedVar->m_assetId);
|
||||
}
|
||||
|
||||
void ReflectedVarMotionAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
|
||||
{
|
||||
AZStd::string stringGuid = pVariable->GetDisplayValue().toLatin1().data();
|
||||
AZ::Uuid guid(stringGuid.c_str(), stringGuid.length());
|
||||
AZ::u32 subId = pVariable->GetUserData().value<AZ::u32>();
|
||||
m_reflectedVar->m_assetId = AZ::Data::AssetId(guid, subId);
|
||||
|
||||
// Lookup Filename by assetId and get the filename part of the description
|
||||
EBUS_EVENT_RESULT(m_reflectedVar->m_motion, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, m_reflectedVar->m_assetId);
|
||||
}
|
||||
|
||||
void ReflectedVarMotionAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
|
||||
{
|
||||
pVariable->SetUserData(m_reflectedVar->m_assetId.m_subId);
|
||||
pVariable->SetDisplayValue(m_reflectedVar->m_assetId.m_guid.ToString<AZStd::string>().c_str());
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CRYINCLUDE_EDITOR_UTILS_REFLECTEDVARWRAPPER_H
|
||||
#define CRYINCLUDE_EDITOR_UTILS_REFLECTEDVARWRAPPER_H
|
||||
#pragma once
|
||||
|
||||
#include "Util/Variable.h"
|
||||
#include <Util/VariablePropertyType.h>
|
||||
#include "ReflectedVar.h"
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
struct CUIEnumsDatabase_SEnum;
|
||||
class ReflectedPropertyItem;
|
||||
|
||||
// Class to wrap the CReflectedVars and sync them with corresponding IVariable.
|
||||
// Most of this code is ported from CPropertyItem functions that marshal data between
|
||||
// IVariable and editor widgets.
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
virtual ~ReflectedVarAdapter(){};
|
||||
|
||||
// update the range limits in CReflectedVar to range specified in IVariable
|
||||
virtual void UpdateRangeLimits([[maybe_unused]] IVariable* pVariable) {};
|
||||
|
||||
//set IVariable for this property and create a CReflectedVar to represent it
|
||||
virtual void SetVariable(IVariable* pVariable) = 0;
|
||||
|
||||
//update the ReflectedVar to current value of IVar
|
||||
virtual void SyncReflectedVarToIVar(IVariable* pVariable) = 0;
|
||||
|
||||
//update the internal IVariable as result of ReflectedVar changing
|
||||
virtual void SyncIVarToReflectedVar(IVariable* pVariable) = 0;
|
||||
|
||||
// Callback called when variable change. SyncReflectedVarToIVar will be called after
|
||||
virtual void OnVariableChange([[maybe_unused]] IVariable* var) {};
|
||||
|
||||
virtual bool UpdateReflectedVarEnums() { return false; }
|
||||
|
||||
virtual CReflectedVar* GetReflectedVar() = 0;
|
||||
|
||||
//needed for containers that can have new values filled in
|
||||
virtual void ReplaceVarBlock([[maybe_unused]] CVarBlock* varBlock) {};
|
||||
|
||||
virtual bool Contains(CReflectedVar* var) { return GetReflectedVar() == var; }
|
||||
};
|
||||
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarIntAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void UpdateRangeLimits(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarInt > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
float m_valueMultiplier = 1.0f;
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarFloatAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void UpdateRangeLimits(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarFloat > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
float m_valueMultiplier = 1.0f;
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarStringAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarString > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarBoolAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarBool > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarEnumAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
ReflectedVarEnumAdapter();
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
virtual void OnVariableChange(IVariable* var);
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
|
||||
protected:
|
||||
//update the ReflectedVar with the allowable enum options
|
||||
bool UpdateReflectedVarEnums() override;
|
||||
|
||||
//virtual function to allow derived classes to update the enum list before syncing with ReflectedVar.
|
||||
virtual void updateIVariableEnumList([[maybe_unused]] IVariable* pVariable) {};
|
||||
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarEnum<AZStd::string> > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
IVariable* m_pVariable;
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
IVarEnumListPtr m_enumList;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
bool m_updatingEnums;
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarDBEnumAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarEnum<AZStd::string> > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
CUIEnumsDatabase_SEnum* m_pEnumDBItem;
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarVector2Adapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarVector2 > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarVector3Adapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarVector3 > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarVector4Adapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarVector4 > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarColorAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarColor > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarAnimationAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarAnimation > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarResourceAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarResource> m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarUserAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable *pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable *pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable *pVariable) override;
|
||||
CReflectedVar *GetReflectedVar() override {
|
||||
return m_reflectedVar.data();
|
||||
}
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarUser> m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarSplineAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
ReflectedVarSplineAdapter(ReflectedPropertyItem *parentItem, PropertyType propertyType);
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override {
|
||||
return m_reflectedVar.data();
|
||||
}
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarSpline > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
bool m_bDontSendToControl;
|
||||
PropertyType m_propertyType;
|
||||
ReflectedPropertyItem *m_parentItem;
|
||||
};
|
||||
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarGenericPropertyAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
ReflectedVarGenericPropertyAdapter(PropertyType propertyType);
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarGenericProperty > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
PropertyType m_propertyType;
|
||||
};
|
||||
|
||||
class EDITOR_CORE_API ReflectedVarMotionAdapter
|
||||
: public ReflectedVarAdapter
|
||||
{
|
||||
public:
|
||||
void SetVariable(IVariable* pVariable) override;
|
||||
void SyncReflectedVarToIVar(IVariable* pVariable) override;
|
||||
void SyncIVarToReflectedVar(IVariable* pVariable) override;
|
||||
CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); }
|
||||
private:
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
QScopedPointer<CReflectedVarMotion > m_reflectedVar;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_EDITOR_UTILS_REFLECTEDVARWRAPPER_H
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1e7fb0db541a13f6f6b6f494f133f72e05c847508bdf69e1bc63dcf8eb4aa752
|
||||
size 311
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:124de9138d3af8e14a49944245d7245df4065c49ad1e5ec1d8377600933558c5
|
||||
size 370
|
||||
Reference in New Issue
Block a user