Files
o3de/Code/Editor/Util/Variable.h
T
amzn-phist d6b268e84e Remove ResourceSelectorHost and clean up/refactor related bits (#3050)
* Sever dependency on legacy resource selector host

Audio resource selectors (browse dialogs) no longer need to be
registered with the legacy IResourceSelectorHost system.  Set up a new
EBus specifically to handle browse button presses and directly invokes
the dialog.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Hook up legacy audio control selector to new EBus

Remaining use of legacy audio selectors (trackview) need to be able to
bypass ResourceSelectorHost now.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Removes ResourceSelectorHost and legacy selectors

This removes various Variable types that were tied to resource
selectors, such as GeomCache, Model, Animation, File.  Removes the
ResourceSelectorHost completely.  The two things that still appeared to
have selectors in TrackView are Audio Controls and Texture.  Fixed the
audio control selector to work via EBus and the Texture selector didn't
seem to work at all, but left it in as it was.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Make the default audio selector return old value

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Fix some signed/unsigned comparison warnings

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Remove deleted function from Editor Mock

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>

* Change audio selector api to use string_view

Per feedback.

Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com>
2021-08-16 12:41:24 -05:00

1890 lines
65 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef CRYINCLUDE_EDITOR_UTIL_VARIABLE_H
#define CRYINCLUDE_EDITOR_UTIL_VARIABLE_H
#pragma once
#include "RefCountBase.h"
#include "Include/EditorCoreAPI.h"
#include <QObject>
AZ_PUSH_DISABLE_WARNING(4458, "-Wunknown-warning-option")
#include <QtUtilWin.h>
AZ_POP_DISABLE_WARNING
#include <QVariant>
#include <StlUtils.h>
inline const char* to_c_str(const char* str) { return str; }
#define MAX_VAR_STRING_LENGTH 4096
struct IVarEnumList;
struct ISplineInterpolator;
class CUsedResources;
struct IVariable;
namespace
{
template<typename T>
T nextNiceNumberBelow(T number);
template<typename T>
T nextNiceNumberAbove(T number)
{
if (number == 0)
{
return 0;
}
if (number < 0)
{
return -nextNiceNumberBelow(-number);
}
// number = 8000
auto l = log10(number); // 3.90
AZ::s64 i = aznumeric_cast<AZ::s64>(l); // 3
int f = aznumeric_cast<int>(pow(10, l - i)); // 10^0.9 = 8
f = f < 2 ? 2 : f < 5 ? 5 : 10; // f -> 10
return aznumeric_cast<T>(pow(10, i) * f);
}
template<typename T>
T nextNiceNumberBelow(T number)
{
if (number == 0)
{
return 0;
}
if (number < 0)
{
return -nextNiceNumberAbove(-number);
}
// number = 8000
auto l = log10(number); // 3.90
AZ::s64 i = aznumeric_cast<AZ::s64>(l); // 3
int f = aznumeric_cast<int>(pow(10, l - i)); // 10^0.9 = 8
f = f > 5 ? 5 : f > 2 ? 2 : 1; // f -> 5
return aznumeric_cast<T>(pow(10, i) * f);
}
}
/** IVariableContainer
* Interface for all classes that hold child variables
*/
struct IVariableContainer
: public CRefCountBase
{
//! Add child variable
virtual void AddVariable(IVariable* var) = 0;
//! Delete specific variable
virtual bool DeleteVariable(IVariable* var, bool recursive = false) = 0;
//! Delete all variables
virtual void DeleteAllVariables() = 0;
//! Gets number of variables
virtual int GetNumVariables() const = 0;
//! Get variable at index
virtual IVariable* GetVariable(int index) const = 0;
//! Returns true if var block contains specified variable.
virtual bool IsContainsVariable(IVariable* pVar, bool bRecursive = false) const = 0;
//! Find variable by name.
virtual IVariable* FindVariable(const char* name, bool bRecursive = false, bool bHumanName = false) const = 0;
//! Return true if variable block is empty (Does not have any vars).
virtual bool IsEmpty() const = 0;
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/** IVariable is the variant variable interface.
*/
struct IVariable
: public IVariableContainer
{
/** Type of data stored in variable.
*/
enum EType
{
UNKNOWN, //!< Unknown parameter type.
INT, //!< Integer property.
BOOL, //!< Boolean property.
FLOAT, //!< Float property.
VECTOR2, //!< Vector property.
VECTOR, //!< Vector property.
VECTOR4, //!< Vector property.
QUAT, //!< Quaternion property.
STRING, //!< String property.
ARRAY, //!< Array of parameters.
FLOW_CUSTOM_DATA, //!< FLow graph custom data
DOUBLE //!< Double property.
};
//! Type of data hold by variable.
enum EDataType
{
DT_SIMPLE = 0, //!< Standard param type.
DT_BOOLEAN,
DT_PERCENT, //!< Percent data type, (Same as simple but value is from 0-1 and UI will be from 0-100).
DT_COLOR,
DT_ANGLE,
DT_TEXTURE,
DT_SHADER,
DT_LOCAL_STRING,
DT_EQUIP,
DT_MATERIALLOOKUP,
DT_EXTARRAY, // Extendable Array
DT_SEQUENCE, // Movie Sequence (DEPRECATED, use DT_SEQUENCE_ID, instead.)
DT_MISSIONOBJ, // Mission Objective
DT_USERITEMCB, // Use a callback GetItemsCallback in user data of variable
DT_UIENUM, // Edit as enum, uses CUIEnumsDatabase to lookup the enum to value pairs and combobox in GUI.
DT_SEQUENCE_ID, // Movie Sequence
DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set
DT_PARTICLE_EFFECT,
DT_DEPRECATED, // formerly DT_FLARE
DT_AUDIO_TRIGGER,
DT_AUDIO_SWITCH,
DT_AUDIO_SWITCH_STATE,
DT_AUDIO_RTPC,
DT_AUDIO_ENVIRONMENT,
DT_AUDIO_PRELOAD_REQUEST,
DT_UI_ELEMENT,
DT_COLORA, // DT_COLOR with alpha channel
DT_MOTION, // Motion animation asset
DT_CURVE = BIT(7), // Combined with other types
};
// Flags that can used with variables.
enum EFlags
{
// User interface related flags.
UI_DISABLED = BIT(0), //!< This variable will be disabled in UI.
UI_BOLD = BIT(1), //!< Variable name in properties will be bold.
UI_SHOW_CHILDREN = BIT(2), //!< Display children in parent field.
UI_USE_GLOBAL_ENUMS = BIT(3), //!< Use CUIEnumsDatabase to fetch enums for this variable name.
UI_INVISIBLE = BIT(4), //!< This variable will not be displayed in the UI
UI_ROLLUP2 = BIT(5), //!< Prefer right roll-up bar for extended property control.
UI_COLLAPSED = BIT(6), //!< Category collapsed by default.
UI_UNSORTED = BIT(7), //!< Do not sort list-box alphabetically.
UI_EXPLICIT_STEP = BIT(8), //!< Use the step size set in the variable for the UI directly.
UI_NOT_DISPLAY_VALUE = BIT(9), //!< The UI will display an empty string where it would normally draw the variable value.
UI_HIGHLIGHT_EDITED = BIT(10), //!< Edited (non-default value) properties show highlight color.
UI_AUTO_EXPAND = BIT(11), //!< Category expanded by default. to auto-expand child in ReflectedPropertyCtrl.
UI_CREATE_SPLINE = BIT(12), //!< To indicate the spline need to be re-created. This is usually because the data was changed directly through the data address
};
typedef AZStd::function<void(IVariable*)> OnSetCallback;
using OnSetEnumCallback = OnSetCallback;
// Store IGetCustomItems into IVariable's UserData and set datatype to
// DT_USERITEMCB
// RefCounting is NOT handled by IVariable!
struct IGetCustomItems
: public CRefCountBase
{
struct SItem
{
SItem() {}
SItem(const QString& name, const QString& desc = QString())
: name(name)
, desc(desc) {}
SItem(const char* name, const char* desc = "")
: name(name)
, desc(desc) {}
QString name;
QString desc;
};
virtual bool GetItems (IVariable* /* pVar */, std::vector<SItem>& /* items */, QString& /* outDialogTitle */) = 0;
virtual bool UseTree() = 0;
virtual const char* GetTreeSeparator() = 0;
};
//! Get name of parameter.
virtual QString GetName() const = 0;
//! Set name of parameter.
virtual void SetName(const QString& name) = 0;
//! Get human readable name of parameter (Normally same as name).
virtual QString GetHumanName() const = 0;
//! Set human readable name of parameter (name without prefix).
virtual void SetHumanName(const QString& name) = 0;
//! Get variable description.
virtual QString GetDescription() const = 0;
//! Set variable description.
virtual void SetDescription(const char* desc) = 0;
//! Set variable description.
virtual void SetDescription(const QString& desc) = 0;
//! Get parameter type.
virtual EType GetType() const = 0;
//! Get size of parameter.
virtual int GetSize() const = 0;
//! Type of data stored in this variable.
virtual unsigned char GetDataType() const = 0;
virtual void SetDataType(unsigned char dataType) = 0;
virtual void SetUserData(const QVariant &data) = 0;
virtual QVariant GetUserData() const = 0;
//////////////////////////////////////////////////////////////////////////
// Flags
//////////////////////////////////////////////////////////////////////////
//! Set variable flags, (Limited to 16 flags).
virtual void SetFlags(int flags) = 0;
virtual int GetFlags() const = 0;
virtual void SetFlagRecursive(EFlags flag) = 0;
/////////////////////////////////////////////////////////////////////////////
// Set methods.
/////////////////////////////////////////////////////////////////////////////
virtual void Set(int value) = 0;
virtual void Set(bool value) = 0;
virtual void Set(float value) = 0;
virtual void Set(double value) = 0;
virtual void Set(const Vec2& value) = 0;
virtual void Set(const Vec3& value) = 0;
virtual void Set(const Vec4& value) = 0;
virtual void Set(const Ang3& value) = 0;
virtual void Set(const Quat& value) = 0;
virtual void Set(const QString& value) = 0;
virtual void Set(const char* value) = 0;
virtual void SetDisplayValue(const QString& value) = 0;
// Called when value updated by any means (including internally).
virtual void OnSetValue(bool bRecursive) = 0;
/////////////////////////////////////////////////////////////////////////////
// Get methods.
/////////////////////////////////////////////////////////////////////////////
virtual void Get(int& value) const = 0;
virtual void Get(bool& value) const = 0;
virtual void Get(float& value) const = 0;
virtual void Get(double& value) const = 0;
virtual void Get(Vec2& value) const = 0;
virtual void Get(Vec3& value) const = 0;
virtual void Get(Vec4& value) const = 0;
virtual void Get(Ang3& value) const = 0;
virtual void Get(Quat& value) const = 0;
virtual void Get(QString& value) const = 0;
virtual QString GetDisplayValue() const = 0;
virtual bool HasDefaultValue() const = 0;
//! reset value to default value
virtual void ResetToDefault() = 0;
//! Return cloned value of variable.
virtual IVariable* Clone(bool bRecursive) const = 0;
//! Copy variable value from specified variable.
//! This method executed always recursively on all sub hierarchy of variables,
//! In Array vars, will never create new variables, only copy values of corresponding childs.
//! @param fromVar Source variable to copy value from.
virtual void CopyValue(IVariable* fromVar) = 0;
//////////////////////////////////////////////////////////////////////////
// Value Limits.
//////////////////////////////////////////////////////////////////////////
//! Set value limits.
virtual void SetLimits([[maybe_unused]] float fMin, [[maybe_unused]] float fMax, [[maybe_unused]] float fStep = 0.f, [[maybe_unused]] bool bHardMin = true, [[maybe_unused]] bool bHardMax = true) {}
//! Get value limits.
virtual void GetLimits([[maybe_unused]] float& fMin, [[maybe_unused]] float& fMax, [[maybe_unused]] float& fStep, [[maybe_unused]] bool& bHardMin, [[maybe_unused]] bool& bHardMax) {}
void GetLimits(float& fMin, float& fMax)
{
float f;
bool b;
GetLimits(fMin, fMax, f, b, b);
}
virtual bool HasCustomLimits() { return false; }
virtual void EnableNotifyWithoutValueChange([[maybe_unused]] bool bFlag){}
//////////////////////////////////////////////////////////////////////////
// Wire/Unwire variables.
//////////////////////////////////////////////////////////////////////////
//! Wire variable, wired variable will be changed when this var changes.
virtual void Wire(IVariable* targetVar) = 0;
//! Unwire variable.
virtual void Unwire(IVariable* targetVar) = 0;
//////////////////////////////////////////////////////////////////////////
// Assign on set callback.
//////////////////////////////////////////////////////////////////////////
virtual void AddOnSetCallback(OnSetCallback* func) = 0;
virtual void RemoveOnSetCallback(OnSetCallback* func) = 0;
virtual void ClearOnSetCallbacks() {}
//////////////////////////////////////////////////////////////////////////
// Assign callback triggered when enums change.
//////////////////////////////////////////////////////////////////////////
virtual void AddOnSetEnumCallback(OnSetEnumCallback* func) = 0;
virtual void RemoveOnSetEnumCallback(OnSetCallback* func) = 0;
virtual void ClearOnSetEnumCallbacks() {}
//////////////////////////////////////////////////////////////////////////
//! Retrieve pointer to selection list used by variable.
virtual IVarEnumList* GetEnumList() const { return 0; }
virtual ISplineInterpolator* GetSpline() { return 0; }
//////////////////////////////////////////////////////////////////////////
//! Serialize variable to XML.
//////////////////////////////////////////////////////////////////////////
virtual void Serialize(XmlNodeRef node, bool load) = 0;
// From CObject, (not implemented)
virtual void Serialize([[maybe_unused]] CArchive& ar) {}
//////////////////////////////////////////////////////////////////////////
// Disables the update callbacks for certain operations in order to avoid
// too many function calls when not needed.
//////////////////////////////////////////////////////////////////////////
virtual void EnableUpdateCallbacks(bool boEnable) = 0;
// Setup to true to force save Undo in case the value the same.
virtual void SetForceModified([[maybe_unused]] bool bForceModified) {}
};
// Smart pointer to this parameter.
typedef _smart_ptr<IVariable> IVariablePtr;
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
/**
**************************************************************************************
* CVariableBase implements IVariable interface and provide default implementation
* for basic IVariable functionality (Name, Flags, etc...)
* CVariableBase cannot be instantiated directly and should be used as the base class for
* actual Variant implementation classes.
***************************************************************************************
*/
class EDITOR_CORE_API CVariableBase
: public IVariable
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
virtual ~CVariableBase() {}
void SetName(const QString& name) { m_name = name; };
//! Get name of parameter.
QString GetName() const { return m_name; };
QString GetHumanName() const
{
if (!m_humanName.isEmpty())
{
return m_humanName;
}
return m_name;
}
void SetHumanName(const QString& name) { m_humanName = name; }
void SetDescription(const char* desc) { m_description = desc; };
void SetDescription(const QString& desc) { m_description = desc; };
//! Get name of parameter.
QString GetDescription() const { return m_description; };
EType GetType() const { return IVariable::UNKNOWN; };
int GetSize() const { return sizeof(*this); };
unsigned char GetDataType() const { return m_dataType; };
void SetDataType(unsigned char dataType) { m_dataType = dataType; }
void SetFlags(int flags) { m_flags = flags; }
int GetFlags() const { return m_flags; }
void SetFlagRecursive(EFlags flag) { m_flags |= flag; }
void SetUserData(const QVariant &data){ m_userData = data; };
QVariant GetUserData() const { return m_userData; }
//////////////////////////////////////////////////////////////////////////
// Set methods.
//////////////////////////////////////////////////////////////////////////
void Set([[maybe_unused]] int value) { assert(0); }
void Set([[maybe_unused]] bool value) { assert(0); }
void Set([[maybe_unused]] float value) { assert(0); }
void Set([[maybe_unused]] double value) { assert(0); }
void Set([[maybe_unused]] const Vec2& value) { assert(0); }
void Set([[maybe_unused]] const Vec3& value) { assert(0); }
void Set([[maybe_unused]] const Vec4& value) { assert(0); }
void Set([[maybe_unused]] const Ang3& value) { assert(0); }
void Set([[maybe_unused]] const Quat& value) { assert(0); }
void Set([[maybe_unused]] const QString& value) { assert(0); }
void Set([[maybe_unused]] const char* value) { assert(0); }
void SetDisplayValue(const QString& value) { Set(value); }
//////////////////////////////////////////////////////////////////////////
// Get methods.
//////////////////////////////////////////////////////////////////////////
void Get([[maybe_unused]] int& value) const { assert(0); }
void Get([[maybe_unused]] bool& value) const { assert(0); }
void Get([[maybe_unused]] float& value) const { assert(0); }
void Get([[maybe_unused]] double& value) const { assert(0); }
void Get([[maybe_unused]] Vec2& value) const { assert(0); }
void Get([[maybe_unused]] Vec3& value) const { assert(0); }
void Get([[maybe_unused]] Vec4& value) const { assert(0); }
void Get([[maybe_unused]] Ang3& value) const { assert(0); }
void Get([[maybe_unused]] Quat& value) const { assert(0); }
void Get([[maybe_unused]] QString& value) const { assert(0); }
QString GetDisplayValue() const { QString val; Get(val); return val; }
//////////////////////////////////////////////////////////////////////////
// IVariableContainer functions
//////////////////////////////////////////////////////////////////////////
virtual void AddVariable([[maybe_unused]] IVariable* var) { assert(0); }
virtual bool DeleteVariable([[maybe_unused]] IVariable* var, [[maybe_unused]] bool recursive = false) { return false; }
virtual void DeleteAllVariables() {}
virtual int GetNumVariables() const { return 0; }
virtual IVariable* GetVariable([[maybe_unused]] int index) const { return nullptr; }
virtual bool IsContainsVariable([[maybe_unused]] IVariable* pVar, [[maybe_unused]] bool bRecursive = false) const { return false; }
virtual IVariable* FindVariable([[maybe_unused]] const char* name, [[maybe_unused]] bool bRecursive = false, [[maybe_unused]] bool bHumanName = false) const { return nullptr; }
virtual bool IsEmpty() const { return true; }
//////////////////////////////////////////////////////////////////////////
void Wire(IVariable* var)
{
m_wiredVars.push_back(var);
}
//////////////////////////////////////////////////////////////////////////
void Unwire(IVariable* var)
{
if (!var)
{
// Unwire all.
m_wiredVars.clear();
}
else
{
stl::find_and_erase(m_wiredVars, var);
}
}
//////////////////////////////////////////////////////////////////////////
void AddOnSetCallback(OnSetCallback* func)
{
if (!stl::find(m_onSetFuncs, func))
{
m_onSetFuncs.push_back(func);
}
}
//////////////////////////////////////////////////////////////////////////
void RemoveOnSetCallback(OnSetCallback* func)
{
stl::find_and_erase(m_onSetFuncs, func);
}
//////////////////////////////////////////////////////////////////////////
void ClearOnSetCallbacks()
{
m_onSetFuncs.clear();
}
void AddOnSetEnumCallback(OnSetEnumCallback* func) override
{
if (!stl::find(m_onSetEnumFuncs, func))
{
m_onSetEnumFuncs.push_back(func);
}
}
//////////////////////////////////////////////////////////////////////////
void RemoveOnSetEnumCallback(OnSetCallback* func)
{
stl::find_and_erase(m_onSetEnumFuncs, func);
}
void ClearOnSetEnumCallbacks() override
{
m_onSetEnumFuncs.clear();
}
virtual void OnSetValue([[maybe_unused]] bool bRecursive)
{
// If have wired variables or OnSet callback, process them.
// Send value to wired variable.
for (CVariableBase::WiredList::iterator it = m_wiredVars.begin(); it != m_wiredVars.end(); ++it)
{
if (m_bForceModified)
{
(*it)->SetForceModified(true);
}
// Copy value to wired vars.
(*it)->CopyValue(this);
}
if (!m_boUpdateCallbacksEnabled)
{
return;
}
// Call on set callback.
for (auto it = m_onSetFuncs.begin(); it != m_onSetFuncs.end(); ++it)
{
// Call on set callback.
(*it)->operator()(this);
}
}
//////////////////////////////////////////////////////////////////////////
void Serialize(XmlNodeRef node, bool load)
{
if (load)
{
if (node->haveAttr(m_name.toUtf8().data()))
{
Set(node->getAttr(m_name.toUtf8().data()));
}
}
else
{
// Saving.
QString str;
Get(str);
node->setAttr(m_name.toUtf8().data(), str.toUtf8().data());
}
}
virtual void EnableUpdateCallbacks(bool boEnable){m_boUpdateCallbacksEnabled = boEnable; };
virtual void SetForceModified(bool bForceModified) { m_bForceModified = bForceModified; }
protected:
// Constructor.
CVariableBase()
: m_dataType(DT_SIMPLE)
, m_flags(0)
, m_boUpdateCallbacksEnabled(true)
, m_bForceModified(false)
{
}
// Copy constructor.
CVariableBase(const CVariableBase& var)
{
m_name = var.m_name;
m_humanName = var.m_humanName;
m_description = var.m_description;
m_flags = var.m_flags;
m_dataType = var.m_dataType;
m_userData = var.m_userData;
m_boUpdateCallbacksEnabled = true;
m_bForceModified = var.m_bForceModified;
// Never copy callback function or wired variables they are private to specific variable,
}
// Not allow.
CVariableBase& operator=([[maybe_unused]] const CVariableBase& var)
{
return *this;
}
//////////////////////////////////////////////////////////////////////////
// Variables.
//////////////////////////////////////////////////////////////////////////
typedef std::vector<OnSetCallback*> OnSetCallbackList;
typedef std::vector<IVariablePtr> WiredList;
using OnSetEnumCallbackList = std::vector<OnSetEnumCallback*>;
QString m_name;
QString m_humanName;
QString m_description;
//! Optional userdata pointer
QVariant m_userData;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
//! Extended data (Extended data is never copied, it's always private to this variable).
WiredList m_wiredVars;
OnSetCallbackList m_onSetFuncs;
OnSetEnumCallbackList m_onSetEnumFuncs;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
uint16 m_flags;
//! Limited to 8 flags.
unsigned char m_dataType;
bool m_boUpdateCallbacksEnabled;
bool m_bForceModified;
};
/**
**************************************************************************************
* CVariableArray implements variable of type array of IVariables.
***************************************************************************************
*/
class EDITOR_CORE_API CVariableArray
: public CVariableBase
{
public:
CVariableArray(){}
//! Get name of parameter.
virtual EType GetType() const { return IVariable::ARRAY; };
virtual int GetSize() const { return sizeof(CVariableArray); };
//////////////////////////////////////////////////////////////////////////
// Set methods.
//////////////////////////////////////////////////////////////////////////
virtual void Set(const QString& value)
{
if (m_strValue != value)
{
m_strValue = value;
OnSetValue(false);
}
}
void OnSetValue(bool bRecursive)
{
CVariableBase::OnSetValue(bRecursive);
if (bRecursive)
{
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
(*it)->OnSetValue(true);
}
}
}
void SetFlagRecursive(EFlags flag)
{
CVariableBase::SetFlagRecursive(flag);
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
(*it)->SetFlagRecursive(flag);
}
}
//////////////////////////////////////////////////////////////////////////
// Get methods.
//////////////////////////////////////////////////////////////////////////
virtual void Get(QString& value) const { value = m_strValue; }
virtual bool HasDefaultValue() const
{
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
if (!(*it)->HasDefaultValue())
{
return false;
}
}
return true;
}
virtual void ResetToDefault()
{
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
(*it)->ResetToDefault();
}
}
//////////////////////////////////////////////////////////////////////////
IVariable* Clone(bool bRecursive) const
{
CVariableArray* var = new CVariableArray(*this);
// m_vars was shallow-duplicated, clone elements.
for (int i = 0; i < m_vars.size(); i++)
{
var->m_vars[i] = m_vars[i]->Clone(bRecursive);
}
return var;
}
//////////////////////////////////////////////////////////////////////////
void CopyValue(IVariable* fromVar)
{
assert(fromVar);
if (fromVar->GetType() != IVariable::ARRAY)
{
return;
}
int numSrc = fromVar->GetNumVariables();
int numTrg = static_cast<int>(m_vars.size());
for (int i = 0; i < numSrc && i < numTrg; i++)
{
// Copy Every child variable.
m_vars[i]->CopyValue(fromVar->GetVariable(i));
}
QString strValue;
fromVar->Get(strValue);
Set(strValue);
}
//////////////////////////////////////////////////////////////////////////
virtual int GetNumVariables() const { return static_cast<int>(m_vars.size()); }
virtual IVariable* GetVariable(int index) const
{
assert(index >= 0 && index < (int)m_vars.size());
return m_vars[index];
}
virtual void AddVariable(IVariable* var)
{
m_vars.push_back(var);
}
virtual bool DeleteVariable(IVariable* var, bool recursive /*=false*/)
{
bool found = stl::find_and_erase(m_vars, var);
if (!found && recursive)
{
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
if ((*it)->DeleteVariable(var, recursive))
{
return true;
}
}
}
return found;
}
virtual void DeleteAllVariables()
{
m_vars.clear();
}
virtual bool IsContainsVariable(IVariable* pVar, bool bRecursive) const
{
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
if (*it == pVar)
{
return true;
}
}
// If not found search childs.
if (bRecursive)
{
// Search all top level variables.
for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
if ((*it)->IsContainsVariable(pVar))
{
return true;
}
}
}
return false;
}
virtual IVariable* FindVariable(const char* name, bool bRecursive, bool bHumanName) const;
virtual bool IsEmpty() const
{
return m_vars.empty();
}
void Serialize(XmlNodeRef node, bool load)
{
if (load)
{
// Loading.
QString name;
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
IVariable* var = *it;
if (var->GetNumVariables())
{
XmlNodeRef child = node->findChild(var->GetName().toUtf8().data());
if (child)
{
var->Serialize(child, load);
}
}
else
{
var->Serialize(node, load);
}
}
}
else
{
// Saving.
for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
IVariable* var = *it;
if (var->GetNumVariables())
{
XmlNodeRef child = node->newChild(var->GetName().toUtf8().data());
var->Serialize(child, load);
}
else
{
var->Serialize(node, load);
}
}
}
}
protected:
typedef std::vector<IVariablePtr> Variables;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
Variables m_vars;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
//! Any string value displayed in properties.
QString m_strValue;
};
/** var_type namespace includes type definitions needed for CVariable implementaton.
*/
namespace var_type
{
//////////////////////////////////////////////////////////////////////////
template <int TypeID, bool IsStandart, bool IsInteger, bool IsSigned, bool SupportsRange>
struct type_traits_base
{
static int type() { return TypeID; };
//! Return true if standard C++ type.
static bool is_standart() { return IsStandart; };
static bool is_integer() { return IsInteger; };
static bool is_signed() { return IsSigned; };
static bool supports_range() { return SupportsRange; };
};
template <class Type>
struct type_traits
: public type_traits_base<IVariable::UNKNOWN, false, false, false, false> {};
// Types specialization.
template<>
struct type_traits<int>
: public type_traits_base<IVariable::INT, true, true, true, true> {};
template<>
struct type_traits<bool>
: public type_traits_base<IVariable::BOOL, true, true, false, true> {};
template<>
struct type_traits<float>
: public type_traits_base<IVariable::FLOAT, true, false, false, true> {};
template<>
struct type_traits<double>
: public type_traits_base<IVariable::DOUBLE, true, false, false, true>{};
template<>
struct type_traits<Vec2>
: public type_traits_base<IVariable::VECTOR2, false, false, false, false> {};
template<>
struct type_traits<Vec3>
: public type_traits_base<IVariable::VECTOR, false, false, false, false> {};
template<>
struct type_traits<Vec4>
: public type_traits_base<IVariable::VECTOR4, false, false, false, false> {};
template<>
struct type_traits<Quat>
: public type_traits_base<IVariable::QUAT, false, false, false, false> {};
template<>
struct type_traits<QString>
: public type_traits_base<IVariable::STRING, false, false, false, false> {};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// General one type to another type convertor class.
//////////////////////////////////////////////////////////////////////////
struct type_convertor
{
template <class From, class To>
void operator()([[maybe_unused]] const From& from, [[maybe_unused]] To& to) const { assert(0); }
void operator()(const int& from, int& to) const { to = from; }
void operator()(const int& from, bool& to) const { to = from != 0; }
void operator()(const int& from, float& to) const { to = (float)from; }
//////////////////////////////////////////////////////////////////////////
void operator()(const bool& from, int& to) const { to = from; }
void operator()(const bool& from, bool& to) const { to = from; }
void operator()(const bool& from, float& to) const { to = from; }
//////////////////////////////////////////////////////////////////////////
void operator()(const float& from, int& to) const { to = (int)from; }
void operator()(const float& from, bool& to) const { to = from != 0; }
void operator()(const float& from, float& to) const { to = from; }
void operator()(const double& from, int& to) const { to = (int)from; }
void operator()(const double& from, bool& to) const { to = from != 0; }
void operator()(const double& from, float& to) const { to = aznumeric_cast<float>(from); }
void operator()(const Vec2& from, Vec2& to) const { to = from; }
void operator()(const Vec3& from, Vec3& to) const { to = from; }
void operator()(const Vec4& from, Vec4& to) const { to = from; }
void operator()(const Quat& from, Quat& to) const { to = from; }
void operator()(const QString& from, QString& to) const { to = from; }
void operator()(bool value, QString& to) const { to = QString::number((value) ? (int)1 : (int)0); }
void operator()(int value, QString& to) const { to = QString::number(value); }
void operator()(float value, QString& to) const { to = QString::number(value); };
void operator()(double value, QString& to) const { to = QString::number(value); };
void operator()(const Vec2& value, QString& to) const { to = QString::fromLatin1("%1,%2").arg(value.x).arg(value.y); }
void operator()(const Vec3& value, QString& to) const { to = QString::fromLatin1("%1,%2,%3").arg(value.x).arg(value.y).arg(value.z); }
void operator()(const Vec4& value, QString& to) const { to = QString::fromLatin1("%1,%2,%3,%4").arg(value.x).arg(value.y).arg(value.z).arg(value.w); }
void operator()(const Ang3& value, QString& to) const { to = QString::fromLatin1("%1,%2,%3").arg(value.x).arg(value.y).arg(value.z); }
void operator()(const Quat& value, QString& to) const { to = QString::fromLatin1("%1,%2,%3,%4").arg(value.w).arg(value.v.x).arg(value.v.y).arg(value.v.z); }
void operator()(const QString& from, int& value) const { value = from.toInt(); }
void operator()(const QString& from, bool& value) const { value = from.toInt() != 0; }
void operator()(const QString& from, float& value) const { value = from.toFloat(); }
void operator()(const QString& from, Vec2& value) const
{
QStringList parts = from.split(QStringLiteral(","));
while (parts.size() < 2)
{
parts.push_back(QString());
}
value.x = parts[0].toFloat();
value.y = parts[1].toFloat();
};
void operator()(const QString& from, Vec3& value) const
{
QStringList parts = from.split(QStringLiteral(","));
while (parts.size() < 3)
{
parts.push_back(QString());
}
value.x = parts[0].toFloat();
value.y = parts[1].toFloat();
value.z = parts[2].toFloat();
};
void operator()(const QString& from, Vec4& value) const
{
QStringList parts = from.split(QStringLiteral(","));
while (parts.size() < 4)
{
parts.push_back(QString());
}
value.x = parts[0].toFloat();
value.y = parts[1].toFloat();
value.z = parts[2].toFloat();
value.w = parts[3].toFloat();
};
void operator()(const QString& from, Ang3& value) const
{
QStringList parts = from.split(QStringLiteral(","));
while (parts.size() < 3)
{
parts.push_back(QString());
}
value.x = parts[0].toFloat();
value.y = parts[1].toFloat();
value.z = parts[2].toFloat();
};
void operator()(const QString& from, Quat& value) const
{
QStringList parts = from.split(QStringLiteral(","));
while (parts.size() < 4)
{
parts.push_back(QString());
}
value.w = parts[0].toFloat();
value.v.x = parts[1].toFloat();
value.v.y = parts[2].toFloat();
value.v.z = parts[3].toFloat();
};
};
//////////////////////////////////////////////////////////////////////////
// Custom comparison functions for different variable type's values,.
//////////////////////////////////////////////////////////////////////////
template <class Type>
inline bool compare(const Type& arg1, const Type& arg2)
{
return arg1 == arg2;
};
inline bool compare(const Vec2& v1, const Vec2& v2)
{
return v1.x == v2.x && v1.y == v2.y;
}
inline bool compare(const Vec3& v1, const Vec3& v2)
{
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
}
inline bool compare(const Vec4& v1, const Vec4& v2)
{
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w;
}
inline bool compare(const Ang3& v1, const Ang3& v2)
{
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
}
inline bool compare(const Quat& q1, const Quat& q2)
{
return q1.v.x == q2.v.x && q1.v.y == q2.v.y && q1.v.z == q2.v.z && q1.w == q2.w;
}
inline bool compare(const char* s1, const char* s2)
{
return strcmp(s1, s2) == 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Custom Initialization functions for different variable type's values,.
//////////////////////////////////////////////////////////////////////////
template <class Type>
inline void init(Type& val)
{
val = 0;
};
inline void init(Vec2& val) { val.x = 0; val.y = 0; };
inline void init(Vec3& val) { val.x = 0; val.y = 0; val.z = 0; };
inline void init(Vec4& val) { val.x = 0; val.y = 0; val.z = 0; val.w = 0; };
inline void init(Ang3& val) { val.x = 0; val.y = 0; val.z = 0; };
inline void init(Quat& val)
{
val.v.x = 0;
val.v.y = 0;
val.v.z = 0;
val.w = 0;
};
inline void init(const char*& val)
{
val = "";
};
inline void init([[maybe_unused]] QString& val)
{
// self initializing.
}
//////////////////////////////////////////////////////////////////////////
};
//////////////////////////////////////////////////////////////////////////
// Void variable does not contain any value.
//////////////////////////////////////////////////////////////////////////
class CVariableVoid
: public CVariableBase
{
public:
CVariableVoid(){};
virtual EType GetType() const { return IVariable::UNKNOWN; };
virtual IVariable* Clone([[maybe_unused]] bool bRecursive) const { return new CVariableVoid(*this); }
virtual void CopyValue([[maybe_unused]] IVariable* fromVar) {};
virtual bool HasDefaultValue() const { return true; }
virtual void ResetToDefault() {};
protected:
CVariableVoid(const CVariableVoid& v)
: CVariableBase(v) {};
};
//////////////////////////////////////////////////////////////////////////
template <class T>
class CVariable
: public CVariableBase
{
typedef CVariable<T> Self;
public:
// Constructor.
CVariable()
: m_valueMin(0.0f)
, m_valueMax(100.0f)
, m_valueStep(0.0f)
, m_bHardMin(false)
, m_bHardMax(false)
, m_customLimits(false)
{
// Initialize value to zero or empty string.
var_type::init(m_valueDef);
}
explicit CVariable(const T& set)
: CVariable()
{
var_type::init(m_valueDef); // Update F32NAN values in Debud mode
SetValue(set);
}
//! Get name of parameter.
virtual EType GetType() const { return (EType)var_type::type_traits<T>::type(); };
virtual int GetSize() const { return sizeof(T); };
//////////////////////////////////////////////////////////////////////////
// Set methods.
//////////////////////////////////////////////////////////////////////////
virtual void Set(int value) { SetValue(value); }
virtual void Set(bool value) { SetValue(value); }
virtual void Set(float value) { SetValue(value); }
virtual void Set(double value) { SetValue(value); }
virtual void Set(const Vec2& value) { SetValue(value); }
virtual void Set(const Vec3& value) { SetValue(value); }
virtual void Set(const Vec4& value) { SetValue(value); }
virtual void Set(const Ang3& value) { SetValue(value); }
virtual void Set(const Quat& value) { SetValue(value); }
virtual void Set(const QString& value) { SetValue(value); }
virtual void Set(const char* value) { SetValue(QString(value)); }
//////////////////////////////////////////////////////////////////////////
// Get methods.
//////////////////////////////////////////////////////////////////////////
virtual void Get(int& value) const { GetValue(value); }
virtual void Get(bool& value) const { GetValue(value); }
virtual void Get(float& value) const { GetValue(value); }
virtual void Get(double& value) const { GetValue(value); }
virtual void Get(Vec2& value) const { GetValue(value); }
virtual void Get(Vec3& value) const { GetValue(value); }
virtual void Get(Vec4& value) const { GetValue(value); }
virtual void Get(Quat& value) const { GetValue(value); }
virtual void Get(QString& value) const { GetValue(value); }
virtual bool HasDefaultValue() const
{
T defval;
var_type::init(defval);
return m_valueDef == defval;
}
virtual void ResetToDefault()
{
T defval;
var_type::init(defval);
SetValue(defval);
}
//////////////////////////////////////////////////////////////////////////
// Limits.
//////////////////////////////////////////////////////////////////////////
virtual void SetLimits(float fMin, float fMax, float fStep = 0.f, bool bHardMin = true, bool bHardMax = true)
{
m_valueMin = fMin;
m_valueMax = fMax;
m_valueStep = fStep;
m_bHardMin = bHardMin;
m_bHardMax = bHardMax;
// Flag to determine when this variable has custom limits set
m_customLimits = true;
}
virtual void GetLimits(float& fMin, float& fMax, float& fStep, bool& bHardMin, bool& bHardMax)
{
if (!m_customLimits && var_type::type_traits<T>::supports_range())
{
float value;
GetValue(value);
if (value > m_valueMax && !m_bHardMax)
{
SetLimits(m_valueMin, nextNiceNumberAbove(value), 0.0, false, false);
}
if (value < m_valueMin && !m_bHardMin)
{
SetLimits(nextNiceNumberBelow(value), m_valueMax, 0.0, false, false);
}
}
fMin = m_valueMin;
fMax = m_valueMax;
fStep = m_valueStep;
bHardMin = m_bHardMin;
bHardMax = m_bHardMax;
}
void ClearLimits()
{
SetLimits(0.0f, 0.0f, 0.0f, false, false);
m_customLimits = false;
}
virtual bool HasCustomLimits()
{
return m_customLimits;
}
//////////////////////////////////////////////////////////////////////////
// Access operators.
//////////////////////////////////////////////////////////////////////////
//! Cast to held type.
operator T const& () const {
return m_valueDef;
}
//! Assign operator for variable.
void operator=(const T& value) { SetValue(value); }
//////////////////////////////////////////////////////////////////////////
IVariable* Clone([[maybe_unused]] bool bRecursive) const
{
Self* var = new Self(*this);
return var;
}
//////////////////////////////////////////////////////////////////////////
void CopyValue(IVariable* fromVar)
{
assert(fromVar);
T val;
fromVar->Get(val);
SetValue(val);
}
protected:
//////////////////////////////////////////////////////////////////////////
template <class P>
void SetValue(const P& value)
{
T newValue = T();
//var_type::type_convertor<P,T> convertor;
var_type::type_convertor convertor;
convertor(value, newValue);
// compare old and new values.
if (m_bForceModified || !var_type::compare(m_valueDef, newValue))
{
m_valueDef = newValue;
m_bForceModified = false;
OnSetValue(false);
}
}
//////////////////////////////////////////////////////////////////////////
template <class P>
void GetValue(P& value) const
{
var_type::type_convertor convertor;
convertor(m_valueDef, value);
}
protected:
T m_valueDef;
bool m_customLimits;
bool m_bResolving;
unsigned char m_bHardMin : 1;
unsigned char m_bHardMax : 1;
// Min/Max value.
float m_valueMin, m_valueMax, m_valueStep;
};
//////////////////////////////////////////////////////////////////////////
/**
**************************************************************************************
* CVariableArray implements variable of type array of IVariables.
***************************************************************************************
*/
template <class T>
class TVariableArray
: public CVariable<T>
{
typedef TVariableArray<T> Self;
public:
using CVariable<T>::GetType;
TVariableArray()
: CVariable<T>() {};
// Copy Constructor.
TVariableArray(const Self& var)
: CVariable<T>(var)
{}
//! Get name of parameter.
virtual int GetSize() const { return sizeof(Self); };
virtual bool HasDefaultValue() const
{
for (Vars::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
if (!(*it)->HasDefaultValue())
{
return false;
}
}
return true;
}
virtual void ResetToDefault()
{
for (Vars::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
(*it)->ResetToDefault();
}
}
//////////////////////////////////////////////////////////////////////////
IVariable* Clone(bool bRecursive) const
{
Self* var = new Self(*this);
for (Vars::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
var->m_vars.push_back((*it)->Clone(bRecursive));
}
return var;
}
//////////////////////////////////////////////////////////////////////////
void CopyValue(IVariable* fromVar)
{
assert(fromVar);
if (fromVar->GetType() != GetType())
{
return;
}
CVariable<T>::CopyValue(fromVar);
int numSrc = fromVar->GetNumVariables();
int numTrg = m_vars.size();
for (int i = 0; i < numSrc && i < numTrg; i++)
{
// Copy Every child variable.
m_vars[i]->CopyValue(fromVar->GetVariable(i));
}
}
//////////////////////////////////////////////////////////////////////////
int GetNumVariables() const { return m_vars.size(); }
IVariable* GetVariable(int index) const
{
assert(index >= 0 && index < (int)m_vars.size());
return m_vars[index];
}
void AddVariable(IVariable* var) { m_vars.push_back(var); }
void DeleteAllVariables() { m_vars.clear(); }
//////////////////////////////////////////////////////////////////////////
void Serialize(XmlNodeRef node, bool load)
{
CVariable<T>::Serialize(node, load);
if (load)
{
// Loading.
QString name;
for (Vars::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
IVariable* var = *it;
if (var->GetNumVariables())
{
XmlNodeRef child = node->findChild(var->GetName().toUtf8().data());
if (child)
{
var->Serialize(child, load);
}
}
else
{
var->Serialize(node, load);
}
}
}
else
{
// Saving.
for (Vars::iterator it = m_vars.begin(); it != m_vars.end(); ++it)
{
IVariable* var = *it;
if (var->GetNumVariables())
{
XmlNodeRef child = node->newChild(var->GetName().toUtf8().data());
var->Serialize(child, load);
}
else
{
var->Serialize(node, load);
}
}
}
}
protected:
typedef std::vector<IVariablePtr> Vars;
Vars m_vars;
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//! Selection list shown in combo box, for enumerated variable.
struct IVarEnumList
: public CRefCountBase
{
//! Get the name of specified value in enumeration, or empty string if out of range.
virtual QString GetItemName(uint index) = 0;
};
typedef _smart_ptr<IVarEnumList> IVarEnumListPtr;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING;
//! Selection list shown in combo box, for enumerated variable.
template <class T>
class CVarEnumListBase
: public IVarEnumList
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
CVarEnumListBase(){}
//////////////////////////////////////////////////////////////////////////
virtual T NameToValue(const QString& name) = 0;
//////////////////////////////////////////////////////////////////////////
virtual QString ValueToName(T const& value) = 0;
//! Add new item to the selection.
virtual void AddItem(const QString& name, const T& value) = 0;
template <class TVal>
static bool IsValueEqual(const TVal& v1, const TVal& v2)
{
return v1 == v2;
}
static bool IsValueEqual(const QString& v1, const QString& v2)
{
// Case insensitive compare.
return QString::compare(v1, v2, Qt::CaseInsensitive) == 0;
}
protected:
virtual ~CVarEnumListBase() {};
friend class _smart_ptr<CVarEnumListBase<T> >;
};
struct CUIEnumsDatabase_SEnum;
//////////////////////////////////////////////////////////////////////////
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class EDITOR_CORE_API CVarGlobalEnumList
: public CVarEnumListBase<QString>
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
CVarGlobalEnumList(CUIEnumsDatabase_SEnum* pEnum);
CVarGlobalEnumList(const QString& enumName);
//! Get the name of specified value in enumeration.
virtual QString GetItemName(uint index);
virtual QString NameToValue(const QString& name);
virtual QString ValueToName(const QString& value);
//! Don't add anything to a global enum database
virtual void AddItem([[maybe_unused]] const QString& name, [[maybe_unused]] const QString& value) {}
private:
CUIEnumsDatabase_SEnum* m_pEnum;
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//! Selection list shown in combo box, for enumerated variable.
template <class T>
class CVarEnumList
: public CVarEnumListBase<T>
{
public:
using CVarEnumListBase<T>::IsValueEqual;
CVarEnumList(){}
struct Item
{
QString name;
T value;
};
QString GetItemName(uint index)
{
if (index >= m_items.size())
{
return QString();
}
return m_items[index].name;
};
//////////////////////////////////////////////////////////////////////////
T NameToValue(const QString& name)
{
for (int i = 0; i < m_items.size(); i++)
{
if (name == m_items[i].name)
{
return m_items[i].value;
}
}
return T();
}
//////////////////////////////////////////////////////////////////////////
QString ValueToName(T const& value)
{
for (int i = 0; i < m_items.size(); i++)
{
if (CVarEnumListBase<T>::IsValueEqual(value, m_items[i].value))
{
return m_items[i].name;
}
}
return "";
}
//! Add new item to the selection.
void AddItem(const QString& name, const T& value)
{
Item item;
item.name = name;
item.value = value;
m_items.push_back(item);
};
protected:
~CVarEnumList() {};
private:
std::vector<Item> m_items;
};
//////////////////////////////////////////////////////////////////////////////////
// CVariableEnum is the same as CVariable but it display enumerated values in UI
//////////////////////////////////////////////////////////////////////////////////
template <class T>
class CVariableEnum
: public CVariable<T>
{
public:
using CVariable<T>::SetValue;
using CVariable<T>::GetFlags;
using CVariable<T>::OnSetValue;
using CVariable<T>::Set;
using CVariable<T>::m_valueDef;
using CVariable<T>::m_onSetEnumFuncs;
//////////////////////////////////////////////////////////////////////////
CVariableEnum(){}
//! Assign operator for variable.
void operator=(const T& value) { CVariable<T>::SetValue(value); }
//! Add new item to the enumeration.
void AddEnumItem(const char* name, const T& value)
{
AddEnumItem(QString(name), value);
};
//! Add new item to the enumeration.
void AddEnumItem(const QString& name, const T& value)
{
if (GetFlags() & IVariable::UI_USE_GLOBAL_ENUMS) // don't think adding makes sense
{
return;
}
if (!m_enum)
{
m_enum = new CVarEnumList<T>();
}
m_enum->AddItem(name, value);
OnEnumsChanged();
};
void SetEnumList(CVarEnumListBase<T>* enumList)
{
m_enum = enumList;
OnSetValue(false);
OnEnumsChanged();
}
IVarEnumList* GetEnumList() const
{
return m_enum;
}
//////////////////////////////////////////////////////////////////////////
IVariable* Clone([[maybe_unused]] bool bRecursive) const
{
CVariableEnum<T>* var = new CVariableEnum<T>(*this);
return var;
}
virtual QString GetDisplayValue() const
{
if (m_enum)
{
return m_enum->ValueToName(m_valueDef);
}
else
{
return CVariable<T>::GetDisplayValue();
}
}
virtual void SetDisplayValue(const QString& value)
{
if (m_enum)
{
Set(m_enum->NameToValue(value));
}
else
{
Set(value);
}
}
protected:
void OnEnumsChanged()
{
// Call on set callback.
for (auto it = m_onSetEnumFuncs.begin(); it != m_onSetEnumFuncs.end(); ++it)
{
// Call on set callback.
(*it)->operator()(this);
}
}
// Copy Constructor.
CVariableEnum(const CVariableEnum<T>& var)
: CVariable<T>(var)
{
m_enum = var.m_enum;
}
private:
_smart_ptr<CVarEnumListBase<T> > m_enum;
};
//////////////////////////////////////////////////////////////////////////
// Smart pointers to variables.
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
template <class T, class TVar>
struct CSmartVariableBase
{
typedef TVar VarType;
CSmartVariableBase() { pVar = new VarType(); }
operator T const& () const {
VarType* pV = pVar;
return *pV;
}
//void operator=( const T& value ) { VarType *pV = pVar; *pV = value; }
// Compare with pointer to variable.
bool operator==(IVariable* pV) { return pVar == pV; }
bool operator!=(IVariable* pV) { return pVar != pV; }
operator VarType&() {
VarType* pV = pVar;
return *pV;
} // Cast to CVariableBase&
VarType& operator*() const { return *pVar; }
VarType* operator->(void) const { return pVar; }
VarType* GetVar() const { return pVar; };
protected:
_smart_ptr<VarType> pVar;
};
//////////////////////////////////////////////////////////////////////////
template <class T>
struct CSmartVariable
: public CSmartVariableBase<T, CVariable<T> >
{
using CSmartVariableBase<T, CVariable<T> >::pVar;
void operator=(const T& value) { CVariable<T>* pV = pVar; *pV = value; }
};
//////////////////////////////////////////////////////////////////////////
template <class T>
struct CSmartVariableArrayT
: public CSmartVariableBase<T, TVariableArray<T> >
{
using CSmartVariableBase<T, TVariableArray<T> >::pVar;
void operator=(const T& value) { TVariableArray<T>* pV = pVar; *pV = value; }
};
//////////////////////////////////////////////////////////////////////////
template <class T>
struct CSmartVariableEnum
: public CSmartVariableBase<T, CVariableEnum<T> >
{
using CSmartVariableBase<T, CVariableEnum<T> >::pVar;
CSmartVariableEnum(){}
void operator=(const T& value) { CVariableEnum<T>* pV = pVar; *pV = value; }
void AddEnumItem(const QString& name, const T& value)
{
pVar->AddEnumItem(name, value);
};
void SetEnumList(CVarEnumListBase<T>* enumList)
{
pVar->EnableUpdateCallbacks(false);
pVar->SetEnumList(enumList);
pVar->EnableUpdateCallbacks(true);
}
};
//////////////////////////////////////////////////////////////////////////
struct CSmartVariableArray
{
typedef CVariableArray VarType;
CSmartVariableArray() { pVar = new VarType(); }
//////////////////////////////////////////////////////////////////////////
// Access operators.
//////////////////////////////////////////////////////////////////////////
operator VarType&() {
VarType* pV = pVar;
return *pV;
}
VarType& operator*() const { return *pVar; }
VarType* operator->(void) const { return pVar; }
VarType* GetVar() const { return pVar; };
private:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
_smart_ptr<VarType> pVar;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class EDITOR_CORE_API CVarBlock
: public IVariableContainer
{
AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
public:
// Dtor.
virtual ~CVarBlock() {}
//! Add variable to block.
virtual void AddVariable(IVariable* var);
//! Remove variable from block
virtual bool DeleteVariable(IVariable* var, bool bRecursive = false);
void AddVariable(IVariable* pVar, const char* varName, unsigned char dataType = IVariable::DT_SIMPLE);
// This used from smart variable pointer.
void AddVariable(CVariableBase& var, const char* varName, unsigned char dataType = IVariable::DT_SIMPLE);
//! Returns number of variables in block.
virtual int GetNumVariables() const { return static_cast<int>(m_vars.size()); }
//! Get pointer to stored variable by index.
virtual IVariable* GetVariable(int index) const
{
assert(index >= 0 && index < m_vars.size());
return m_vars[index];
}
// Clear all vars from VarBlock.
virtual void DeleteAllVariables() { m_vars.clear(); };
//! Return true if variable block is empty (Does not have any vars).
virtual bool IsEmpty() const { return m_vars.empty(); }
// Returns true if var block contains specified variable.
virtual bool IsContainsVariable(IVariable* pVar, bool bRecursive = true) const;
//! Find variable by name.
virtual IVariable* FindVariable(const char* name, bool bRecursive = true, bool bHumanName = false) const;
//////////////////////////////////////////////////////////////////////////
//! Clone var block.
CVarBlock* Clone(bool bRecursive) const;
//////////////////////////////////////////////////////////////////////////
//! Copy variable values from specified var block.
//! Do not create new variables, only copy values of existing ones.
//! Should only be used to copy identical var blocks (eg. not Array type var copied to String type var)
//! @param fromVarBlock Source variable block that contain copied values, must be identical to this var block.
void CopyValues(const CVarBlock* fromVarBlock);
//////////////////////////////////////////////////////////////////////////
//! Copy variable values from specified var block.
//! Do not create new variables, only copy values of existing ones.
//! Can be used to copy slightly different var blocks, matching performed by variable name.
//! @param fromVarBlock Source variable block that contain copied values.
void CopyValuesByName(CVarBlock* fromVarBlock);
void OnSetValues();
//////////////////////////////////////////////////////////////////////////
//! Set UI_CREATE_SPLINE flags for all the varialbes in this Var Block.
//! This is because when the data was changed for a spline variable, the spline need to be recreated to reflect the change.
//! Set the flag to notify the spline variable.
void SetRecreateSplines();
//////////////////////////////////////////////////////////////////////////
// Wire/Unwire other variable blocks.
//////////////////////////////////////////////////////////////////////////
//! Wire to other variable block.
//! Only equivalent VarBlocks can be wired (same number of variables with same type).
//! Recursive wiring of array variables is supported.
void Wire(CVarBlock* toVarBlock);
//! Unwire var block.
void Unwire(CVarBlock* varBlock);
//! Add this callback to every variable in block (recursively).
void AddOnSetCallback(IVariable::OnSetCallback* func);
//! Remove this callback from every variable in block (recursively).
void RemoveOnSetCallback(IVariable::OnSetCallback* func);
//////////////////////////////////////////////////////////////////////////
void Serialize(XmlNodeRef vbNode, bool load);
void ReserveNumVariables(int numVars);
//////////////////////////////////////////////////////////////////////////
//! Gather resources in this variable block.
virtual void GatherUsedResources(CUsedResources& resources);
void EnableUpdateCallbacks(bool boEnable);
IVariable* FindChildVar(const char* name, IVariable* pParentVar) const;
void Sort();
protected:
void SetCallbackToVar(IVariable::OnSetCallback* func, IVariable* pVar, bool bAdd);
void WireVar(IVariable* src, IVariable* trg, bool bWire);
void GatherUsedResourcesInVar(IVariable* pVar, CUsedResources& resources);
typedef std::vector<IVariablePtr> Variables;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
Variables m_vars;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
typedef _smart_ptr<CVarBlock> CVarBlockPtr;
//////////////////////////////////////////////////////////////////////////
class EDITOR_CORE_API CVarObject
: public QObject
, public CRefCountBase
{
public:
typedef IVariable::OnSetCallback VarOnSetCallback;
CVarObject();
~CVarObject();
void Serialize(XmlNodeRef node, bool load);
CVarBlock* GetVarBlock() const { return m_vars; };
void AddVariable(CVariableBase& var, const QString& varName, VarOnSetCallback* cb = nullptr, unsigned char dataType = IVariable::DT_SIMPLE);
void AddVariable(CVariableBase& var, const QString& varName, const QString& varHumanName, VarOnSetCallback* cb = nullptr, unsigned char dataType = IVariable::DT_SIMPLE);
void AddVariable(CVariableArray& table, CVariableBase& var, const QString& varName, const QString& varHumanName, VarOnSetCallback* cb = nullptr, unsigned char dataType = IVariable::DT_SIMPLE);
void ReserveNumVariables(int numVars);
void RemoveVariable(IVariable* var);
void EnableUpdateCallbacks(bool boEnable);
void OnSetValues();
protected:
//! Copy values of variables from other VarObject.
//! Source object must be of same type.
void CopyVariableValues(CVarObject* sourceObject);
private:
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
CVarBlockPtr m_vars;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
};
Q_DECLARE_METATYPE(IVariable *);
#endif // CRYINCLUDE_EDITOR_UTIL_VARIABLE_H