summaryrefslogtreecommitdiffstats
path: root/src/uipparser/Qt3DSUIPParserActionHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uipparser/Qt3DSUIPParserActionHelper.cpp')
-rw-r--r--src/uipparser/Qt3DSUIPParserActionHelper.cpp738
1 files changed, 738 insertions, 0 deletions
diff --git a/src/uipparser/Qt3DSUIPParserActionHelper.cpp b/src/uipparser/Qt3DSUIPParserActionHelper.cpp
new file mode 100644
index 0000000..ab6d751
--- /dev/null
+++ b/src/uipparser/Qt3DSUIPParserActionHelper.cpp
@@ -0,0 +1,738 @@
+/****************************************************************************
+**
+** Copyright (C) 1993-2009 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "RuntimePrefix.h"
+#ifdef EA_PLATFORM_WINDOWS
+#pragma warning(disable : 4396) // specializer warning nonsense
+#endif
+
+//==============================================================================
+// Includes
+//==============================================================================
+#include "Qt3DSUIPParserActionHelper.h"
+#include "Qt3DSUIPParserObjectRefHelper.h"
+#include "Qt3DSIPresentation.h"
+#include "Qt3DSCommandEventTypes.h"
+
+#include "Qt3DSDMPrefix.h"
+#include "Qt3DSDMXML.h"
+#include "Qt3DSDMWStrOpsImpl.h"
+#include "Qt3DSMetadata.h"
+#include "Qt3DSEulerAngles.h"
+#include "Qt3DSLogicSystem.h"
+#include "Qt3DSParametersSystem.h"
+
+using namespace qt3dsdm;
+
+//==============================================================================
+// Namespace
+//==============================================================================
+namespace Q3DStudio {
+
+//==============================================================================
+/**
+ * Constructor
+ */
+CUIPParserActionHelper::CUIPParserActionHelper(CUIPParserImpl *inUIPParser,
+ CUIPParserObjectRefHelper *inObjRefHelper,
+ IRuntimeMetaData &inMetaData)
+ : m_UIPParser(inUIPParser)
+ , m_ObjRefHelper(inObjRefHelper)
+ , m_MetaData(inMetaData)
+{
+}
+
+//==============================================================================
+/**
+ * Destructor
+ */
+CUIPParserActionHelper::~CUIPParserActionHelper()
+{
+}
+
+void CUIPParserActionHelper::CacheAction(qt3dsdm::IDOMReader &inReader,
+ const char8_t *inActionOwnerId)
+{
+ if (IsTrivial(inActionOwnerId))
+ return;
+
+ IDOMReader::Scope __childScope(inReader);
+
+ const char *theRef;
+ if (inReader.Att("ref", theRef)) {
+ // Ignore "ref" because we are only interested in new actions
+ return;
+ }
+
+ // Parse the action
+ SActionInfo theAction;
+ inReader.Att("id", theAction.m_Id);
+ theAction.m_Owner = inActionOwnerId;
+
+ const char *tempStr;
+ if (inReader.Att("triggerObject", tempStr))
+ theAction.m_TriggerObject = m_UIPParser->ParseObjectRefId(tempStr, inActionOwnerId);
+ inReader.Att("event", theAction.m_Event);
+ if (inReader.Att("targetObject", tempStr))
+ theAction.m_TargetObject = m_UIPParser->ParseObjectRefId(tempStr, inActionOwnerId);
+ if (inReader.Att("handler", tempStr)) {
+ theAction.m_Handler = tempStr;
+ CacheHandlerArguments(inReader, theAction);
+ }
+
+ // Only proceeds if we can find the elements
+ if (theAction.m_TargetObject.empty() || theAction.m_TriggerObject.empty()
+ || theAction.m_Owner.empty()) {
+ qCWarning(qt3ds::INVALID_OPERATION) << "Action invalid, id: " << theAction.m_Id.c_str();
+ return;
+ }
+
+ m_ActionMap[theAction.m_Id] = theAction;
+
+ // Build up logic tables to be processed by BuildAction later
+ // There are 2 tables involved:
+ // 1. The Listener-To-Events tables - multimap of each listener to all events it is listening to
+ // 2. The Listener-Event-To-Actions table - multimap of each listener-event pair to all actions
+ // it triggers
+ // note: The struct for Action is a pair of EventAction node and its owner
+ AddListenerEventPair(theAction.m_TriggerObject, theAction.m_Event);
+
+ SListenerEventNamePair theListenerEventPair(theAction.m_TriggerObject, theAction.m_Event);
+ TEventActionOwnerPair theLogicOwnerPair(theAction.m_Id, theAction.m_Owner);
+ m_ListenerEventActionsMap.insert(eastl::make_pair(theListenerEventPair, theLogicOwnerPair));
+}
+
+void CUIPParserActionHelper::AddListenerEventPair(eastl::string inListener,
+ const eastl::string &inEventName)
+{
+ // Check for dupes
+ TListenerEventsNameMap::iterator theStartItr = m_ListenerEventsNameMap.lower_bound(inListener);
+ TListenerEventsNameMap::iterator theEndItr = m_ListenerEventsNameMap.upper_bound(inListener);
+ for (; theStartItr != theEndItr; ++theStartItr) {
+ if (theStartItr->second == inEventName)
+ return;
+ }
+
+ m_ListenerEventsNameMap.insert(eastl::make_pair(inListener, inEventName));
+}
+
+void CUIPParserActionHelper::CacheHandlerArguments(qt3dsdm::IDOMReader &inReader,
+ SActionInfo &inAction)
+{
+ IDOMReader::Scope __handlerArgScope(inReader);
+ for (bool success = inReader.MoveToFirstChild(); success;
+ success = inReader.MoveToNextSibling()) {
+ SHandlerArgumentInfo theArg;
+ inReader.Att("name", theArg.m_Name);
+ inReader.Att("value", theArg.m_Value);
+ inAction.m_HandlerArgs.push_back(theArg);
+ }
+ if (inAction.m_Handler == "Set Property") {
+ SHandlerArgumentInfo theHandlerArg1 = inAction.m_HandlerArgs[0];
+ SElementData *targetData = m_UIPParser->GetElementData(inAction.m_TargetObject.c_str());
+ if (targetData && !theHandlerArg1.m_Value.empty()) {
+ m_UIPParser->m_ParseElementManager.MarkAttributeAsReferenced(
+ *targetData, theHandlerArg1.m_Value.c_str());
+ }
+ }
+}
+
+SElement *CUIPParserActionHelper::GetElement(const eastl::string &inElementName)
+{
+ return m_UIPParser->GetElement(inElementName.c_str());
+}
+
+void CUIPParserActionHelper::GetActionSectionCount(
+ CUIPParserImpl::SActionSectionCount &outActionCount)
+{
+ // There are 2 tables involved:
+ // 1. The Listener-To-Events tables - multimap of each listener to all events it is listening to
+ // 2. The Listener-Event-To-Actions table - multimap of each listener-event pair to all actions
+ // it triggers
+ // note: The struct for Action is a pair of EventAction node and its owner
+
+ // Get the count to reserve
+ // Iterate through each listener
+ for (TListenerEventsNameMap::iterator theListenerItr = m_ListenerEventsNameMap.begin();
+ theListenerItr != m_ListenerEventsNameMap.end();) {
+ ++outActionCount.m_TriggerElementCount;
+
+ INT32 theEventCount =
+ static_cast<INT32>(m_ListenerEventsNameMap.count(theListenerItr->first));
+ for (INT32 theEventCounter = 0; theEventCounter < theEventCount;
+ ++theEventCounter, ++theListenerItr) {
+ ++outActionCount.m_TriggerEventCount;
+
+ // iterate through each listener-event pair
+ SListenerEventNamePair thePair(theListenerItr->first, theListenerItr->second);
+ TListenerEventActionsMap::iterator theActionsItr =
+ m_ListenerEventActionsMap.lower_bound(thePair);
+ INT32 theActionCount = static_cast<INT32>(m_ListenerEventActionsMap.count(thePair));
+ for (INT32 theActionCounter = 0; theActionCounter < theActionCount;
+ ++theActionCounter) {
+ eastl::string theActionId = theActionsItr->second.first;
+ outActionCount.m_ActionCount +=
+ GetActionCount(theActionId, outActionCount.m_StringAttrCount,
+ outActionCount.m_CustomParamCount);
+ ++theActionsItr;
+ }
+ }
+ }
+}
+
+void CUIPParserActionHelper::BuildActions(IPresentation &inPresentation)
+{
+ // Now we start building
+ // Iterate through each listener
+ for (TListenerEventsNameMap::iterator theListenerItr = m_ListenerEventsNameMap.begin();
+ theListenerItr != m_ListenerEventsNameMap.end();) {
+ TElement *theElement = GetElement(theListenerItr->first);
+
+ INT32 theEventCount =
+ static_cast<INT32>(m_ListenerEventsNameMap.count(theListenerItr->first));
+ for (INT32 theEventCounter = 0; theEventCounter < theEventCount;
+ ++theEventCounter, ++theListenerItr) {
+ UINT32 theEventName =
+ CHash::HashEventCommand(theListenerItr->second.c_str()); // UINT32: HashedName
+
+ // iterate through each listener-event pair
+ SListenerEventNamePair thePair(theListenerItr->first, theListenerItr->second);
+ TListenerEventActionsMap::iterator theActionsItr =
+ m_ListenerEventActionsMap.lower_bound(thePair);
+ INT32 theActionCount = static_cast<INT32>(m_ListenerEventActionsMap.count(thePair));
+ for (INT32 theActionCounter = 0; theActionCounter < theActionCount;
+ ++theActionCounter) {
+ eastl::string theActionId = theActionsItr->second.first;
+ if (theElement)
+ BuildAction(*theElement, theEventName, inPresentation, theActionId);
+ ++theActionsItr;
+ }
+ }
+ }
+}
+
+union UTypeConverter {
+ SAttributeKey m_Key;
+ INT32 m_IntData;
+};
+
+struct SActionAdder
+{
+ ILogicSystem &m_LogicSystem;
+ TElement &m_EventElement;
+ UINT32 m_EventName;
+ TElement *m_Owner;
+ TElement *m_Target;
+
+ SActionAdder(ILogicSystem &inLogicSystem, TElement &inEventElement, UINT32 inEventName,
+ TElement *inOwner, TElement *inTarget)
+ : m_LogicSystem(inLogicSystem)
+ , m_EventElement(inEventElement)
+ , m_EventName(inEventName)
+ , m_Owner(inOwner)
+ , m_Target(inTarget)
+ {
+ }
+
+ INT32 AddAction(TEventCommandHash inCommand, UINT32 inArg1 = 0, UINT32 inArg2 = 0)
+ {
+ UVariant arg1Var;
+ UVariant arg2Var;
+ arg1Var.m_INT32 = (INT32)inArg1;
+ arg2Var.m_INT32 = (INT32)inArg2;
+ return m_LogicSystem.AddAction(m_EventElement, m_EventName, m_Target, m_Owner, inCommand,
+ arg1Var, arg2Var, true);
+ }
+};
+
+void CUIPParserActionHelper::BuildAction(TElement &inElement, UINT32 inEventName,
+ IPresentation &inPresentation,
+ const eastl::string &inActionId)
+{
+ ILogicSystem &theLogicBuilder = inPresentation.GetLogicSystem();
+ IParametersSystem &theParamSystem = inPresentation.GetParametersSystem();
+ TActionMap::iterator theIter = m_ActionMap.find(inActionId);
+ if (theIter == m_ActionMap.end()) {
+ Q3DStudio_ASSERT(false);
+ qCWarning(qt3ds::INVALID_OPERATION) << "Can't find action, id: " << inActionId.c_str();
+ return;
+ }
+
+ SActionInfo theAction = theIter->second;
+ INT32 theAddActionIndex = -1; // the index of newly added action. If there are more than 1
+ // actions, the index points to the firstly added action.
+ SActionAdder theAdder(theLogicBuilder, inElement, inEventName, GetElement(theAction.m_Owner),
+ GetElement(theAction.m_TargetObject));
+
+ // The list of applicable handler is loaded from metadata xml file (if it is non-custom handler)
+ bool theIsCustomHandler = IsCustomHandler(theAction);
+
+ if (theIsCustomHandler) {
+ // Argument 1 - param table start index
+ INT32 paramGroup = theParamSystem.CreateParameterGroup();
+
+ // First param is the handler name we want to invoke for the custom action.
+ ExportCustomActionParameters(inPresentation, theParamSystem, paramGroup,
+ theAction.m_Handler.c_str(), ERuntimeDataModelDataTypeString,
+ ERuntimeAdditionalMetaDataTypeNone);
+
+ int theHandlerArgumentCount = theAction.m_HandlerArgs.size();
+ ERuntimeDataModelDataType theType;
+ ERuntimeAdditionalMetaDataType theAdditionalType;
+ // Actual handler parameters to pass in.
+ for (int theIndex = 0; theIndex < theHandlerArgumentCount; ++theIndex) {
+ GetHandlerArgumentType(theAction, theIndex, theType, theAdditionalType);
+ ExportCustomActionParameters(inPresentation, theParamSystem, paramGroup,
+ theAction.m_HandlerArgs[theIndex].m_Value.c_str(), theType,
+ theAdditionalType);
+ }
+ theAddActionIndex = theAdder.AddAction(COMMAND_CUSTOMACTION, (UINT32)paramGroup);
+ } else if (theAction.m_Handler == "Set Property") // Plain set action
+ {
+ // ArgumentOne - HashPropertyName
+ // ArgumentTwo - Value
+ SHandlerArgumentInfo theHandlerArg1 = theAction.m_HandlerArgs[0];
+ SHandlerArgumentInfo theHandlerArg2 = theAction.m_HandlerArgs[1];
+
+ eastl::string thePropertyName = theHandlerArg1.m_Value;
+ SElementData *theTargetObject =
+ m_UIPParser->GetElementData(theAction.m_TargetObject.c_str());
+ if (theTargetObject) {
+ SElementPropertyInfo *theProperty = m_UIPParser->m_ParseElementManager.FindProperty(
+ *theTargetObject, thePropertyName.c_str());
+ if (theProperty) {
+ TPropertyDescAndValueList theProperties;
+ ERuntimeDataModelDataType theType = theProperty->m_DataType;
+ ERuntimeAdditionalMetaDataType theAdditionalType = theProperty->m_AdditionalType;
+
+ m_UIPParser->GetAttributeList(inPresentation, theProperties, theType,
+ theAdditionalType, thePropertyName.c_str(),
+ theHandlerArg2.m_Value.c_str(),
+ theProperty->m_PropertyNames);
+
+ UINT32 theActionCount = theProperties.size();
+ Q3DStudio_ASSERT(theActionCount > 0);
+ for (UINT32 theActionIndex = 0; theActionIndex < theActionCount; ++theActionIndex) {
+ INT32 actionId = theAdder.AddAction(
+ COMMAND_SETPROPERTY, theProperties[theActionIndex].first.GetNameHash(),
+ theProperties[theActionIndex].second.m_INT32);
+ if (theActionIndex == 0)
+ theAddActionIndex = actionId;
+ }
+ }
+ }
+ } else if (theAction.m_Handler == "Fire Event") // Fire the selected event on the element
+ {
+ theAddActionIndex = theAdder.AddAction(
+ COMMAND_FIREEVENT, CHash::HashEventCommand(theAction.m_HandlerArgs[0].m_Value.c_str()));
+ } else if (theAction.m_Handler == "Go to Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(
+ COMMAND_GOTOSLIDENAME, CHash::HashString(theAction.m_HandlerArgs[0].m_Value.c_str()));
+ } else if (theAction.m_Handler == "Next Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_GOTONEXTSLIDE);
+ } else if (theAction.m_Handler == "Previous Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_GOTOPREVIOUSSLIDE);
+ } else if (theAction.m_Handler == "Preceding Slide") // Switch slides
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_BACKSLIDE);
+ } else if (theAction.m_Handler == "Play") // Play
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_PLAY);
+ } else if (theAction.m_Handler == "Pause") // Pause
+ {
+ theAddActionIndex = theAdder.AddAction(COMMAND_PAUSE);
+ } else if (theAction.m_Handler == "Go to Time") // Goto Time
+ {
+ float theTime = 0;
+ const char *theValue = theAction.m_HandlerArgs[0].m_Value.c_str();
+ if (!IsTrivial(theValue))
+ WStrOps<float>().StrTo(theValue, theTime);
+
+ theAddActionIndex =
+ theAdder.AddAction(COMMAND_GOTOTIME, static_cast<UINT32>(theTime * 1000.0f));
+
+ bool thePause = false;
+ theValue = theAction.m_HandlerArgs[1].m_Value.c_str();
+ if (!IsTrivial(theValue))
+ WStrOps<bool>().StrTo(theValue, thePause);
+ theAdder.AddAction(thePause ? COMMAND_PAUSE : COMMAND_PLAY);
+ } else if (theAction.m_Handler == "Emit Signal") // Emit a signal
+ {
+ qt3ds::foundation::CStringHandle theStringHandle;
+ if (!theAction.m_HandlerArgs[0].m_Value.empty()) {
+ const char *theValue = theAction.m_HandlerArgs[0].m_Value.c_str();
+ theStringHandle = inPresentation.GetStringTable().GetHandle(theValue);
+ }
+ theAddActionIndex = theAdder.AddAction(COMMAND_EMITSIGNAL, theStringHandle.handle());
+ } else {
+ Q3DStudio_ASSERT(false); // what sort of crazy action is this?
+ }
+
+ if (theAddActionIndex > -1)
+ m_ActionIdentifierMap[theAction.m_Id] = theAddActionIndex;
+}
+
+INT32 CUIPParserActionHelper::GetActionCount(const eastl::string &inActionId)
+{
+ INT32 theStringAttrCount = 0;
+ INT32 theCustomParamCount = 0;
+ return GetActionCount(inActionId, theStringAttrCount, theCustomParamCount);
+}
+
+INT32 CUIPParserActionHelper::GetActionCount(const eastl::string &inActionId,
+ INT32 &outStringAttrCount, INT32 &outCustomParamCount)
+{
+ INT32 theActionCount = 0;
+
+ TActionMap::iterator theIter = m_ActionMap.find(inActionId);
+ if (theIter == m_ActionMap.end()) {
+ Q3DStudio_ASSERT(false);
+ qCWarning(qt3ds::INVALID_OPERATION) << "Can't find action, id: " << inActionId.c_str();
+ return theActionCount;
+ }
+
+ SActionInfo theAction = theIter->second;
+
+ // The list of applicable handler is loaded from metadata xml file (if it is non-custom handler)
+ bool theIsCustomHandler = IsCustomHandler(theAction);
+
+ if (theIsCustomHandler) {
+ theActionCount = 1;
+
+ // First param is the handler name we want to invoke for the custom action.
+ ++outStringAttrCount;
+ ++outCustomParamCount;
+
+ int theHandlerArgumentCount = theAction.m_HandlerArgs.size();
+ ERuntimeDataModelDataType theType;
+ ERuntimeAdditionalMetaDataType theAdditionalType;
+ // Actual handler parameters to pass in.
+ for (int theIndex = 0; theIndex < theHandlerArgumentCount; ++theIndex) {
+ GetHandlerArgumentType(theAction, theIndex, theType, theAdditionalType);
+ GetCustomActionParametersCount(theType, theAdditionalType, outStringAttrCount,
+ outCustomParamCount);
+ }
+ }
+
+ else if (theAction.m_Handler == "Set Property") // Plain set action
+ {
+ SHandlerArgumentInfo theHandlerArg1 = theAction.m_HandlerArgs[0];
+
+ eastl::string thePropertyName = theHandlerArg1.m_Value;
+ SElementData *theData = m_UIPParser->GetElementData(theAction.m_TargetObject.c_str());
+ if (theData) {
+ SElementPropertyInfo *thePropertyInfo =
+ m_UIPParser->m_ParseElementManager.GetOrCreateProperty(*theData,
+ thePropertyName.c_str());
+ if (thePropertyInfo) {
+ theActionCount = thePropertyInfo->m_Arity;
+ if (m_UIPParser->IsStringType(thePropertyInfo->m_DataType))
+ ++outStringAttrCount;
+ }
+ }
+ }
+
+ else if (theAction.m_Handler == "Fire Event" // Fire the selected event on the element
+ || theAction.m_Handler == "Go to Slide" // Switch slides
+ || theAction.m_Handler == "Next Slide" // Switch slides
+ || theAction.m_Handler == "Previous Slide" // Switch slides
+ || theAction.m_Handler == "Preceding Slide" // Switch slides
+ || theAction.m_Handler == "Play" // Play
+ || theAction.m_Handler == "Pause" // Pause
+ ) {
+ theActionCount = 1;
+ }
+
+ else if (theAction.m_Handler == "Go to Time") // Goto Time
+ {
+ theActionCount = 2;
+ } else if (theAction.m_Handler == "Play Sound") // Play Sound
+ {
+ theActionCount = 1;
+ ++outStringAttrCount;
+ } else if (theAction.m_Handler == "Emit Signal") // Emit Signal
+ {
+ theActionCount = 1;
+ ++outStringAttrCount;
+ } else {
+ Q3DStudio_ASSERT(false); // what sort of crazy action is this?
+ }
+
+ return theActionCount;
+}
+
+INT32 CUIPParserActionHelper::GetActionIndex(const eastl::string &inActionId)
+{
+ TActionIdentifierMap::iterator theFind = m_ActionIdentifierMap.find(inActionId);
+ if (theFind != m_ActionIdentifierMap.end())
+ return theFind->second;
+ Q3DStudio_ASSERT(false);
+ return -1;
+}
+
+bool CUIPParserActionHelper::IsCustomHandler(const SActionInfo &inAction)
+{
+ const char *theClass = m_ObjRefHelper->GetClass(inAction.m_TargetObject);
+ if (!IsTrivial(theClass))
+ return m_MetaData.IsCustomHandler(theClass, inAction.m_Handler.c_str());
+ return false;
+}
+
+void CUIPParserActionHelper::GetHandlerArgumentType(
+ const SActionInfo &inAction, int inArgumentIndex, ERuntimeDataModelDataType &outType,
+ ERuntimeAdditionalMetaDataType &outAdditionalType)
+{
+ const char *theClass = m_ObjRefHelper->GetClass(inAction.m_TargetObject);
+ return m_MetaData.GetHandlerArgumentType(theClass, inAction.m_Handler.c_str(),
+ inAction.m_HandlerArgs[inArgumentIndex].m_Name.c_str(),
+ outType, outAdditionalType);
+}
+
+void CUIPParserActionHelper::GetCustomActionParametersCount(
+ ERuntimeDataModelDataType inDataType, ERuntimeAdditionalMetaDataType inAdditionalType,
+ INT32 &outStringAttrCount, INT32 &outCustomParamCount)
+{
+ // This function should match ExportCustomActionParameters
+ switch (inDataType) {
+ case ERuntimeDataModelDataTypeFloat:
+ case ERuntimeDataModelDataTypeLong:
+ case ERuntimeDataModelDataTypeBool: {
+ outCustomParamCount += 1;
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ outCustomParamCount += 2;
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ if (inAdditionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ // Append rgba
+ outCustomParamCount += 4;
+ } else {
+ // Append xyz
+ outCustomParamCount += 3;
+ }
+ break;
+ }
+ // default to string
+ default: {
+ outCustomParamCount += 1;
+ outStringAttrCount += 1;
+ }
+ }
+}
+
+namespace {
+
+ using qt3ds::foundation::IStringTable;
+
+ struct SCustomParameterParseInfoFloat
+ {
+ typedef float TParseType;
+ static const char8_t *Name() { return "float"; }
+ static TParseType Default() { return 0; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = inParseType;
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoLong
+ {
+ typedef QT3DSI32 TParseType;
+ static const char8_t *Name() { return "long"; }
+ static TParseType Default() { return 0; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoBool
+ {
+ typedef bool TParseType;
+ static const char8_t *Name() { return "bool"; }
+ static TParseType Default() { return false; }
+ static Q3DStudio::UVariant ToVariant(const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoFloat2
+ {
+ typedef SFloat2 TParseType;
+ static const char8_t *Name() { return "float2"; }
+ static TParseType Default() { return SFloat2(0, 0); }
+ static QT3DSU32 NumParameters() { return 2; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoFloat3
+ {
+ typedef SFloat3 TParseType;
+ static const char8_t *Name() { return "float3"; }
+ static const char8_t **Extensions()
+ {
+ static const char8_t *retval[] = { ".x", ".y", ".z", NULL };
+ return retval;
+ }
+ static TParseType Default() { return SFloat3(0, 0, 0); }
+ static QT3DSU32 NumParameters() { return 3; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]);
+ return retval;
+ }
+ };
+
+ struct SCustomParameterParseInfoColor
+ {
+ typedef SFloat3 TParseType;
+ static const char8_t *Name() { return "color4"; }
+ static TParseType Default() { return SFloat3(0, 0, 0); }
+ static QT3DSU32 NumParameters() { return 4; }
+ static Q3DStudio::UVariant ToVariant(QT3DSU32 inIdx, const TParseType &inParseType)
+ {
+ if (inIdx < 3) {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = static_cast<float>(inParseType[inIdx]) * 255.0f;
+ return retval;
+ } else {
+ Q3DStudio::UVariant retval;
+ retval.m_FLOAT = 255.0f;
+ return retval;
+ }
+ }
+ };
+
+ template <typename TParseInfo>
+ struct ParseParameter
+ {
+ void operator()(WCharTReader &inReader, const char *inValue, IParametersSystem &inSystem,
+ QT3DSI32 inGroupId)
+ {
+ typename TParseInfo::TParseType theValue = TParseInfo::Default();
+ if (!IsTrivial(inValue))
+ inReader.Read(theValue);
+ Q3DStudio::UVariant theVarValue = TParseInfo::ToVariant(theValue);
+ inSystem.AddParameter(inGroupId, CHash::HashString(TParseInfo::Name()), theVarValue);
+ }
+ };
+
+ template <typename TParseInfo>
+ struct ParseAggregateParameter
+ {
+ void operator()(WCharTReader &inReader, const char *inValue, IParametersSystem &inSystem,
+ QT3DSI32 inGroupId)
+ {
+ typename TParseInfo::TParseType theValue = TParseInfo::Default();
+ if (!IsTrivial(inValue))
+ inReader.ReadRef(NVDataRef<float>(&theValue[0], TParseInfo::NumParameters()));
+
+ for (QT3DSU32 idx = 0, end = TParseInfo::NumParameters(); idx < end; ++idx) {
+ Q3DStudio::UVariant theVarValue = TParseInfo::ToVariant(idx, theValue);
+ inSystem.AddParameter(inGroupId, CHash::HashString(TParseInfo::Name()),
+ theVarValue);
+ }
+ }
+ };
+}
+
+void CUIPParserActionHelper::ExportCustomActionParameters(
+ IPresentation &inPresentation, IParametersSystem &inParamSystem, QT3DSI32 inParamGroupId,
+ const char *inValue, ERuntimeDataModelDataType inDataType,
+ ERuntimeAdditionalMetaDataType inAdditionalType)
+{
+ // Create a destructible value
+ m_UIPParser->m_ValueBuffer.clear();
+ m_UIPParser->m_ValueBuffer.write(inValue, (QT3DSU32)strlen(inValue) + 1);
+ // Clear the destination buffer
+ m_UIPParser->m_TempBuffer.clear();
+ WCharTReader theReader((char8_t *)m_UIPParser->m_ValueBuffer.begin(), m_UIPParser->m_TempBuffer,
+ *m_UIPParser->GetDOMReader().GetStringTable());
+
+ // The function should match CUIPParserActionHelper::GetCustomActionParametersCount
+ switch (inDataType) {
+ case ERuntimeDataModelDataTypeFloat: {
+ ParseParameter<SCustomParameterParseInfoFloat>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeLong: {
+ ParseParameter<SCustomParameterParseInfoLong>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeBool: {
+ ParseParameter<SCustomParameterParseInfoBool>()(theReader, inValue, inParamSystem,
+ inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat2: {
+ ParseAggregateParameter<SCustomParameterParseInfoFloat2>()(theReader, inValue,
+ inParamSystem, inParamGroupId);
+ break;
+ }
+ case ERuntimeDataModelDataTypeFloat3: {
+ if (inAdditionalType == ERuntimeAdditionalMetaDataTypeColor) {
+ ParseAggregateParameter<SCustomParameterParseInfoColor>()(
+ theReader, inValue, inParamSystem, inParamGroupId);
+ } else {
+ ParseAggregateParameter<SCustomParameterParseInfoFloat3>()(
+ theReader, inValue, inParamSystem, inParamGroupId);
+ }
+ break;
+ }
+ // default to string
+ default: {
+ UVariant theValue;
+ theValue.m_StringHandle = inPresentation.GetStringTable().GetHandle(inValue);
+ inParamSystem.AddParameter(inParamGroupId, CHash::HashString("string"), theValue);
+ break;
+ }
+ }
+}
+}