diff options
Diffstat (limited to 'src/runtime/Qt3DSPresentation.cpp')
-rw-r--r-- | src/runtime/Qt3DSPresentation.cpp | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/src/runtime/Qt3DSPresentation.cpp b/src/runtime/Qt3DSPresentation.cpp new file mode 100644 index 0000000..0792119 --- /dev/null +++ b/src/runtime/Qt3DSPresentation.cpp @@ -0,0 +1,841 @@ +/**************************************************************************** +** +** 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 "Qt3DSPresentation.h" +#include "Qt3DSCommandEventTypes.h" +#include "Qt3DSIScriptBridge.h" +#include "Qt3DSInputEventTypes.h" +#include "Qt3DSDataLogger.h" +#include "Qt3DSApplication.h" +#include "Qt3DSRuntimeFactory.h" +#include "Qt3DSCommandHelper.h" +#include "Qt3DSActivationManager.h" +#include "Qt3DSRenderContextCore.h" +#include "Qt3DSComponentManager.h" +#include "Qt3DSRenderBufferLoader.h" +#include "Qt3DSSlideSystem.h" +#include "Qt3DSLogicSystem.h" +#include "Qt3DSParametersSystem.h" +#include "Qt3DSApplication.h" + +#include <QtCore/qfileinfo.h> +#include <QtGui/qvector4d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector2d.h> + +namespace Q3DStudio { + +// Maximum number of Event/Command that can be queued in an Update cycle +const INT32 Q3DStudio_EVENTCOMMANDQUEUECAPACITY = 512; + +// Limit to prevent infinite loop during queue processing +const INT32 Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT = Q3DStudio_EVENTCOMMANDQUEUECAPACITY * 10; + +#ifdef WIN32 +#pragma warning(push) +#pragma warning(disable : 4355) +#endif + +CPresentation::CPresentation(const QString &inName, const QString &projectPath, + qt3ds::runtime::IApplication *inApplication) + : m_Name(inName) + , m_Application(inApplication) + , m_Scene(nullptr) + , m_ActivityZone(nullptr) + , m_RootElement(nullptr) + , m_EventCommandQueue(Q3DStudio_EVENTCOMMANDQUEUECAPACITY, "EventCommandQueue") + , m_IsProcessingEventCommandQueue(false) + , m_ComponentManager(*this) + , m_Offset(0) + , m_LocalTime(0) + , m_PreviousGlobalTime(-1) + , m_Paused(false) + , m_OffsetInvalid(true) + , m_Active(true) +{ + m_projectPath = QFileInfo(projectPath).absoluteFilePath(); + m_Size.m_Width = 0; + m_Size.m_Height = 0; + m_Size.m_ScaleMode = SCALEMODE_UNKNOWN; + m_AnimationSystem = IAnimationSystem::CreateAnimationSystem( + inApplication->GetRuntimeFactoryCore().GetFoundation()); + m_SlideSystem = + ISlideSystem::CreateSlideSystem(inApplication->GetRuntimeFactoryCore().GetFoundation(), + inApplication->GetRuntimeFactoryCore().GetStringTable(), + inApplication->GetElementAllocator()); + m_LogicSystem = + ILogicSystem::CreateLogicSystem(inApplication->GetRuntimeFactoryCore().GetFoundation()); + m_ParametersSystem = IParametersSystem::CreateParametersSystem( + inApplication->GetRuntimeFactoryCore().GetFoundation()); +} +#ifdef _WIN32 +#pragma warning(pop) +#endif + +CPresentation::~CPresentation() +{ +} + +/** + * Registers an element for notification when events fired on it. + * @param inElement target element to monitor + * @param inEventHash event hash to register for + * @param inCallback static callback function + * @param inContextData arbitrary data pointer + */ +void CPresentation::RegisterEventCallback(TElement *inElement, const TEventCommandHash inEventHash, + const TEventCallback inCallback, void *inContextData) +{ + m_EventCallbacks.RegisterCallback(inElement, inEventHash, inCallback, inContextData); + inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, true); + + if (qt3ds::runtime::IApplication::isPickingEvent(inEventHash)) + inElement->SetFlag(ELEMENTFLAG_PICKENABLED, true); +} + +/** + * Unregisters a previously registered event callback. + * @param inElement target element to monitor + * @param inEventHash event hash to register for + * @param inCallback static callback function + * @param inContextData arbitrary data pointer + */ +BOOL CPresentation::UnregisterEventCallback(TElement *inElement, + const TEventCommandHash inEventHash, + const TEventCallback inCallback, void *inContextData) +{ + BOOL theLast = false; + BOOL theResult = m_EventCallbacks.UnregisterCallback(inElement, inEventHash, inCallback, + inContextData, theLast); + + // Unflag element if there are no longer any callbacks on it + if (theLast) + inElement->SetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK, false); + + if (qt3ds::runtime::IApplication::isPickingEvent(inEventHash)) + inElement->SetFlag(ELEMENTFLAG_PICKENABLED, false); + + return theResult; +} + +void CPresentation::ClearDirtyList() +{ + FOR_ARRAY(TElement *, theElement, GetFrameData().GetDirtyList()) + { + (*theElement)->Flags().SetDirty(false); + } + GetFrameData().Reset(); +} + +inline void ConvertActivityZoneBufferToElementList(qt3ds::runtime::TActivityItemBuffer inSource, + TElementList &outResult) +{ + for (qt3ds::QT3DSU32 idx = 0, end = inSource.size(); idx < end; ++idx) + outResult.Push(inSource[idx].first); +} + +void CPresentation::PreUpdate(const TTimeUnit inGlobalTime) +{ + if (m_OffsetInvalid || m_Paused) { + m_OffsetInvalid = false; + m_Offset = m_LocalTime - inGlobalTime; + } else + m_LocalTime = inGlobalTime + m_Offset; + + // Event/Command Processing Stage + ProcessEventCommandQueue(); +} + +/** + * Update the presentation to the current time. This will start triggering the + * various stages of the presentation frame rhythm + * @param inGlobalTime time at which to update each presentation + * @return true if there were events to be processed. + */ +void CPresentation::BeginUpdate() +{ + // Active Scan Stage + if (m_ActivityZone) { + m_ActivityZone->BeginUpdate( + m_LocalTime, m_Application->GetRuntimeFactory().GetPerfTimer(), + m_Application->GetRuntimeFactory().GetQt3DSRenderContext().GetThreadPool()); + } +} + +void CPresentation::EndUpdate() +{ + if (m_ActivityZone) { + m_ActivityZone->EndUpdate(); + CPresentationFrameData &theFrameData = GetFrameData(); + ConvertActivityZoneBufferToElementList(m_ActivityZone->GetActivatedItems(), + theFrameData.GetActivationList()); + ConvertActivityZoneBufferToElementList(m_ActivityZone->GetDeactivatedItems(), + theFrameData.GetDeactivationList()); + ConvertActivityZoneBufferToElementList(m_ActivityZone->GetScriptItems(), + theFrameData.GetScriptsList()); + } + + if (!m_Paused) { + // Animation Track Evaluation Stage + m_AnimationSystem->Update(); + } + // Presentation is considered ready to accept external commands when the first frame property + // updates are done. + if (!m_presentationReady) { + m_SignalProxy.SigPresentationReady(); + m_presentationReady = true; + } +} + +void CPresentation::PostUpdate(const TTimeUnit inGlobalTime) +{ + if (!m_Paused) { + // Callback Stage + if (m_Application && m_PreviousGlobalTime != inGlobalTime) + m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessFrameCallbacks(this); + } + + m_PreviousGlobalTime = inGlobalTime; +} + +void CPresentation::NotifyDataOutputs() +{ + if (m_pathToDataOutMap.size() == 0) + return; + + // Based on the dirty list, check if we need to fire DataOutput notifications + Q3DStudio::TElementList &dirtyList = GetFrameData().GetDirtyList(); + for (int idx = 0, end = dirtyList.GetCount(); idx < end; ++idx) { + Q3DStudio::TElement &element = *dirtyList[idx]; + if (m_pathToDataOutMap.contains(element.m_Path)) { + auto outDefIter = m_pathToDataOutMap.find(element.m_Path); + + while (outDefIter != m_pathToDataOutMap.end() && outDefIter.key() == element.m_Path) { + qt3ds::runtime::DataOutputDef &outDef = outDefIter.value(); + + // Get current value + Q3DStudio::UVariant value; + qt3ds::QT3DSU32 attribHash + = CHash::HashAttribute(outDef.observedAttribute.attributeName[0]); + element.GetAttribute(attribHash, value); + QVariant qvar; + switch (outDef.observedAttribute.propertyType) { + case ATTRIBUTETYPE_INT32: + qvar.setValue(value.m_INT32); + break; + case ATTRIBUTETYPE_FLOAT: + qvar.setValue(value.m_FLOAT); + break; + case ATTRIBUTETYPE_BOOL: + qvar.setValue(value.m_INT32); + break; + case ATTRIBUTETYPE_STRING: + qvar.setValue(QString::fromUtf8( + GetStringTable().HandleToStr(value.m_StringHandle).c_str())); + break; + case ATTRIBUTETYPE_FLOAT4: { + QVector4D qvalue(value.m_FLOAT4[0], value.m_FLOAT4[1], + value.m_FLOAT4[2], value.m_FLOAT4[3]); + qvar.setValue(qvalue); + } + break; + case ATTRIBUTETYPE_FLOAT3: { + QVector3D qvalue(value.m_FLOAT3[0], value.m_FLOAT3[1], value.m_FLOAT3[2]); + qvar.setValue(qvalue); + } + break; + case ATTRIBUTETYPE_FLOAT2: { + QVector2D qvalue(value.m_FLOAT3[0], value.m_FLOAT3[1]); + qvar.setValue(qvalue); + } + break; + default: + break; + } + + if (qvar.isValid() && (outDef.value != qvar)) { + outDef.value.setValue(qvar); + m_SignalProxy.SigDataOutputValueUpdated(outDef.name, outDef.value); + } + + ++outDefIter; + } + } + } +} + +void CPresentation::AddToDataOutputMap(const QHash<qt3ds::foundation::CRegisteredString, + qt3ds::runtime::DataOutputDef> &doMap) +{ + if (doMap.size() > 0) + m_pathToDataOutMap.unite(doMap); +} + +/** + * Process the Event/Command queue completely + * PostEventCommand is the method that will add new Event/Command to the queue. + * + * The contract for Event/Command processing: + * 1. If an Event or Command is posted during the processing stage, it will be added + * to the end of the queue and is guaranteed to be processed in the current cycle. + * For example, if an Event (which is processed) triggers a Command to set a model to red, + * the model will turn red in the current frame. + * + * 2. If an Event or Command is posted after the processing stage, such as during the + * Callback stage, it will only be processed on the next Update cycle. + * For example, if the "turn mode to red" Command is posted in a script callback, the + * model will turn red in the next frame. + * + * 3. If an Event or Command is posted before the processing stage, for example an + * external Event posted just before the Update cycle, it will be processed in the current + *cycle. + * For example, if the "turn mode to red" Command is posted from the game engine prior to + * the Update cycle, the model will turn red in the current frame. + * + * @see PostEventCommand + * @return true if there were events that were processed. + */ +BOOL CPresentation::ProcessEventCommandQueue() +{ + PerfLogGeneralEvent2(DATALOGGER_PROCESSEVENTS); + + m_IsProcessingEventCommandQueue = true; + + BOOL theResult = !m_EventCommandQueue.IsEmpty(); + INT32 theEventProcessedCount = 0; + while (!m_EventCommandQueue.IsEmpty()) { + SEventCommand &theEventCommand = m_EventCommandQueue.Top(); + if (theEventCommand.m_IsEvent) + ProcessEvent(theEventCommand, theEventProcessedCount); + else + ProcessCommand(theEventCommand); + + // Infinite-loop check + if (theEventProcessedCount > Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT) { + // Breakout policy: Dump remaining Event/Commands + qCCritical(qt3ds::INVALID_OPERATION) + << "ProcessEventCommandQueue exceeded maximum loop count" + << "Remaining Event/Commands will be cleared. Event count: " + << theEventProcessedCount << "Limit: " << Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT; + m_EventCommandQueue.Clear(); + } else { + m_EventCommandQueue.Pop(); + } + } + + m_IsProcessingEventCommandQueue = false; + + return theResult; +} + +/** + * Pass incoming event to event consumers immediately + * @param ioEvent the incoming event + */ +void CPresentation::ProcessEvent(SEventCommand &ioEvent, INT32 &ioEventCount) +{ + if (ioEventCount < Q3DStudio_MAXEVENTCOMMANDLOOPCOUNT) { + ++ioEventCount; + PerfLogPresentationEvent1(DATALOGGER_PROCESSEVENT); + + // Callbacks can change ioEvent's bubbling flags + if (ioEvent.m_Target->GetFlag(ELEMENTFLAG_REGISTEREDFOREVENTCALLBACK)) { + m_EventCallbacks.FireCallbacks(ioEvent); + } + + // Do an early return if callback do a "stopImmediatePropagation" + if (ioEvent.m_Done) + return; + + if (ioEvent.m_Target) { + // Logic should not be able to change ioEvent's bubbling flags + // ...or can it? + m_LogicSystem->OnEvent(ioEvent.m_Type, *ioEvent.m_Target, *this); + } + + ProcessEventBubbling(ioEvent, ioEventCount); + } +} + +/** + * Handle event bubbling + * @param ioEvent the incoming event + */ +void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventCount) +{ + PerfLogPresentationEvent1(DATALOGGER_PROCESSEVENTBUBBLING); + + // Check for onGroupedMouseOver/Out + // arg1 = the original onMouseOut model and arg2 = the original onMouseOver model + if (ioEvent.m_Type == ON_MOUSEOUT) { + // If original onMouseOver model is nullptr or not a descendent, fire onGroupedMouseOut + TElement *theMouseOverModel = static_cast<TElement *>(ioEvent.m_Arg2.m_VoidPointer); + if (!theMouseOverModel || !ioEvent.m_Target->IsDescendent(*theMouseOverModel)) { + SEventCommand theEvent = ioEvent; + theEvent.m_Type = ON_GROUPEDMOUSEOUT; + theEvent.m_BubbleUp = 0; // no bubbling + theEvent.m_BubbleDown = 0; + FireEvent(theEvent); + } + // set the original onMouseOver model to the target to make IsDescendent queries less + // expensive + else if (theMouseOverModel) { + ioEvent.m_Arg2.m_VoidPointer = ioEvent.m_Target; + } + } else if (ioEvent.m_Type == ON_MOUSEOVER) { + // If original onMouseOut model is nullptr or not a descendent, fire onGroupedMouseOver + TElement *theMouseOutModel = static_cast<TElement *>(ioEvent.m_Arg1.m_VoidPointer); + if (!theMouseOutModel || !ioEvent.m_Target->IsDescendent(*theMouseOutModel)) { + SEventCommand theEvent = ioEvent; + theEvent.m_Type = ON_GROUPEDMOUSEOVER; + theEvent.m_BubbleUp = 0; // no bubbling + theEvent.m_BubbleDown = 0; + FireEvent(theEvent); + } + // set the original onMouseOut model to the target to make IsDescendent queries less + // expensive + else if (theMouseOutModel) { + ioEvent.m_Arg1.m_VoidPointer = ioEvent.m_Target; + } + } + + // Do NOT bubble up onSlideEnter and onSlideExit events from current component to its parent + // scene + // since each component has its own slides. + if (ioEvent.m_BubbleUp && (ioEvent.m_Target->Flags() & ELEMENTFLAG_COMPONENT) + && (ioEvent.m_Type == EVENT_ONSLIDEENTER || ioEvent.m_Type == EVENT_ONSLIDEEXIT)) { + ioEvent.m_BubbleUp = FALSE; + } + + // Event bubbling + if (ioEvent.m_BubbleUp) { + TElement *theParent = ioEvent.m_Target->m_Parent; + if (theParent) { + ioEvent.m_Target = theParent; + ProcessEvent(ioEvent, ioEventCount); + } + } +} + +/** + * Execute command immediately + * @param inCommand incoming command structure + */ +void CPresentation::ProcessCommand(const SEventCommand &inCommand) +{ + PerfLogPresentationEvent1(DATALOGGER_PROCESSCOMMAND); + + // Attributes (Arg1 = key, Arg2 = value) + if (inCommand.m_Type == COMMAND_SETPROPERTY) { + SAttributeKey theAttributeKey; + UINT32 theHash = static_cast<UINT32>(inCommand.m_Arg1.m_Hash); + theAttributeKey.Convert( + theHash); // Need this conversion to prevent problems arising due to endianess + inCommand.m_Target->SetAttribute(theAttributeKey.m_Hash, inCommand.m_Arg2); + + // Events (Arg1 = hashed event name) + } else if (inCommand.m_Type == COMMAND_FIREEVENT) { + FireEvent(inCommand.m_Arg1.m_Hash, inCommand.m_Target); + + // Time (Arg1 = time) + } else if (inCommand.m_Type == COMMAND_PLAY) { + GetComponentManager().SetPause(inCommand.m_Target, false); + } else if (inCommand.m_Type == COMMAND_PAUSE) { + GetComponentManager().SetPause(inCommand.m_Target, true); + } else if (inCommand.m_Type == COMMAND_GOTOTIME) { + GetComponentManager().GoToTime(inCommand.m_Target, inCommand.m_Arg1.m_INT32); + + // Slide (Arg1 = slide index or slide name) + } else if (inCommand.m_Type == COMMAND_GOTOSLIDE) { + // Goto slide commands are handled differently. + IComponentManager &theManager(GetComponentManager()); + Q3DStudio::SComponentGotoSlideData theGotoSlideData = + theManager.GetComponentGotoSlideCommand(inCommand.m_Target); + if (theGotoSlideData.m_Slide > 0) + theManager.GotoSlideIndex(inCommand.m_Target, theGotoSlideData); + + theManager.ReleaseComponentGotoSlideCommand(inCommand.m_Target); + } else if (inCommand.m_Type == COMMAND_GOTOSLIDENAME) { + GetComponentManager().GotoSlideName(inCommand.m_Target, inCommand.m_Arg1.m_Hash); + } else if (inCommand.m_Type == COMMAND_GOTONEXTSLIDE) { + GetComponentManager().GoToNextSlide(inCommand.m_Target); + } else if (inCommand.m_Type == COMMAND_GOTOPREVIOUSSLIDE) { + GetComponentManager().GoToPreviousSlide(inCommand.m_Target); + } else if (inCommand.m_Type == COMMAND_BACKSLIDE) { + GetComponentManager().GoToBackSlide(inCommand.m_Target); + + // Behavior + } else if (inCommand.m_Type == COMMAND_CUSTOMACTION) { + m_Application->GetRuntimeFactoryCore().GetScriptEngineQml() + .ProcessCustomActions(this, inCommand); + } else if (inCommand.m_Type == COMMAND_CUSTOMCALLBACK) { + m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessCustomCallback( + this, inCommand); + } else if (inCommand.m_Type == COMMAND_PLAYSOUND) { + CRegisteredString theSoundPathReg = GetStringTable().HandleToStr(inCommand.m_Arg1.m_INT32); + if (theSoundPathReg.IsValid()) { + const char *theSoundPath = theSoundPathReg.c_str(); + if (strlen(theSoundPath) > 0) { + m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().PlaySoundFile( + theSoundPath); + } + } + } else if (inCommand.m_Type == COMMAND_EMITSIGNAL) { + CRegisteredString nameStr = GetStringTable().HandleToStr(inCommand.m_Arg1.m_INT32); + m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessSignal(this, inCommand); + QString path = QString::fromLatin1(inCommand.m_Target->m_Path.c_str()); + QString name = QString::fromLatin1(nameStr.c_str()); + signalProxy()->SigCustomSignal(path, name); + } else { + qCCritical(qt3ds::INVALID_OPERATION) << "Command not implemented: " << inCommand.m_Type; + } +} + +/** + * Put an Event in the queue to be processed later during the Event/Command + * processing stage in Update + * This method is used by Event-bubbling during ProcessEvent + * + * @param inEvent the incoming event + * @see PostEvent + */ +void CPresentation::FireEvent(const SEventCommand &inEvent) +{ + SEventCommand &theEventCommand = m_EventCommandQueue.NewEntry(); + + theEventCommand = inEvent; + + theEventCommand.m_IsEvent = true; +} + +/** + * Put an Event in the queue to be processed later during the Event/Command + * processing stage in Update See ProcessEventCommandQueue for more + * information on the contract for Event/Command processing. + * + * @param inEventType the incoming event type + * @param inTarget the target for the event + * @param inArg1 optional argument #1 + * @param inArg2 optional argument #2 + * @param inType1 optional type for argument #1 + * @param inType2 optional type for argument #2 + * @see ProcessEventCommandQueue + * @see PostEventCommand + */ +void CPresentation::FireEvent(const TEventCommandHash inEventType, TElement *inTarget, + const UVariant *inArg1, const UVariant *inArg2, + const EAttributeType inType1, const EAttributeType inType2) +{ + + SEventCommand theEvent = { inTarget, inEventType }; + + theEvent.m_IsEvent = true; + theEvent.m_BubbleUp = true; + + theEvent.m_Arg1Type = static_cast<UINT8>(inType1); + theEvent.m_Arg2Type = static_cast<UINT8>(inType2); + + if (inArg1) + theEvent.m_Arg1 = *inArg1; + if (inArg2) + theEvent.m_Arg2 = *inArg2; + + m_EventCommandQueue.NewEntry() = theEvent; +} + +/** + * Put a Command in the queue to be processed later during the Event/Command + * processing stage in Update. See ProcessEventCommandQueue for more information + * on the contract for Event/Command processing. + * + * For cases where the Commands need to be synchronized with the Frame-Rhythm + * An example would be calling "SetSlide" in scripts. + * + * @see ProcessEventCommandQueue + * @see PostEventCommand + * @param inEventType the incoming command type + * @param inTarget the target for the command + * @param inArg1 optional argument #1 + * @param inArg2 optional argument #2 + * @param inType1 optional type for argument #1 + * @param inType2 optional type for argument #2 + */ +void CPresentation::FireCommand(const TEventCommandHash inEventType, TElement *inTarget, + const UVariant *inArg1, const UVariant *inArg2, + const EAttributeType inType1, const EAttributeType inType2) +{ + // Pre-filter gotoslidename commands. + if (inEventType == COMMAND_GOTOSLIDENAME) { + int theSlideHashName = inArg1->m_INT32; + TComponent *theComponent = GetComponentManager().GetComponent(inTarget); + UINT8 theSlideIndex = GetSlideSystem().FindSlide(*theComponent, theSlideHashName); + // Translate into a slide index command. + CCommandHelper::SetupGotoSlideCommand(*inTarget, theSlideIndex, + SScriptEngineGotoSlideArgs()); + } else { + SEventCommand theCommand = { inTarget, inEventType }; + + theCommand.m_Arg1Type = static_cast<UINT8>(inType1); + theCommand.m_Arg2Type = static_cast<UINT8>(inType2); + + if (inArg1) + theCommand.m_Arg1 = *inArg1; + if (inArg2) + theCommand.m_Arg2 = *inArg2; + + m_EventCommandQueue.NewEntry() = theCommand; + } +} + +void CPresentation::FlushEventCommandQueue(void) +{ + if (!m_IsProcessingEventCommandQueue) + ProcessEventCommandQueue(); +} + +void CPresentation::ProcessEvent(SEventCommand &inEvent) +{ + INT32 theEventProcessedCount = 0; + ProcessEvent(inEvent, theEventProcessedCount); +} + +/** + * This method is triggered after the presentation is streamed in. At this point, + * all the stores will be loaded up. + */ +void CPresentation::OnPresentationLoaded() +{ + m_FrameData.Reserve(1000 /*m_ElementManager.GetElementCount( )*/); +} + +/** + * Set the full path for this presentation. This can be used by anyone who + * knows the presentation to form relative paths. + * @param inPath the path to which to set. + */ +void CPresentation::SetFilePath(const CHAR *inPath) +{ + m_FilePath = QFileInfo(inPath).absoluteFilePath(); +} + +/** + * Gets the full file path for this presentation. This can be used by anyone who + * knows the presentation to form relative correct paths. + */ +QString CPresentation::GetFilePath() const +{ + return m_FilePath; +} + +/** + * Gets the absolute file path for the project that owns this presentation. + */ +QString CPresentation::getProjectPath() const +{ + return m_projectPath; +} + +/** + * Gets the pause state + * @return true if the presentation is paused, false if otherwise + */ +BOOL CPresentation::GetPause() const +{ + return m_Paused; +} + +/** + * Sets the pause state + * @param inPause set true to pause, set false if otherwise + */ +void CPresentation::SetPause(const BOOL inPause) +{ + m_Paused = inPause ? true : false; +} + +/** + * Simple manager access: Scene + */ +void CPresentation::SetScene(IScene *inScene) +{ + m_Scene = inScene; +} + +void CPresentation::SetActivityZone(qt3ds::runtime::IActivityZone *inZone) +{ + m_ActivityZone = inZone; + m_ActivityZone->SetZoneActive(m_Active); + TElement *theSceneElement = m_RootElement; + qt3ds::runtime::IActivityZone &theZone(*GetActivityZone()); + // The activity zone requires elements described to it in breadth first search order. + theZone.AddActivityItems(*theSceneElement); +} + +void CPresentation::SetActive(bool inValue) +{ + m_Active = inValue; + m_ActivityZone->SetZoneActive(m_Active); +} + +bool CPresentation::GetActive() const +{ + return m_Active; +} + +/** + * Simple manager access: Scene + */ +IScene *CPresentation::GetScene() const +{ + return m_Scene; +} + +/** +* Simple manager access: Script Bridge Qml +*/ +IScriptBridge *CPresentation::GetScriptBridgeQml() +{ + if (m_Application) + return &m_Application->GetRuntimeFactoryCore().GetScriptEngineQml(); + + return nullptr; +} + +/** + * Simple manager access: Component Manager + */ +IComponentManager &CPresentation::GetComponentManager() +{ + return m_ComponentManager; +} + +/** + * Simple manager access: Slide Manager + */ +ISlideSystem &CPresentation::GetSlideSystem() +{ + return *m_SlideSystem; +} + +/** + * Simple manager access: Animation Manager + */ +qt3ds::runtime::IAnimationSystem &CPresentation::GetAnimationSystem() +{ + return *m_AnimationSystem; +} + +/** + * Simple manager access: Logic Manager + */ +ILogicSystem &CPresentation::GetLogicSystem() +{ + return *m_LogicSystem; +} + +/** + * Simple manager access: Params Manager + */ +IParametersSystem &CPresentation::GetParametersSystem() +{ + return *m_ParametersSystem; +} + +void CPresentation::SetElementPath(TElement &inElement, const char8_t *inPath) +{ + CRegisteredString str; + if (m_Application) + str = m_Application->GetRuntimeFactoryCore().GetStringTable().RegisterStr( + qt3ds::foundation::nonNull(inPath)); + + if (str.IsValid()) + m_ElementPathMap.insert(eastl::make_pair(&inElement, str)); +} + +qt3ds::foundation::CRegisteredString CPresentation::GetElementPath(TElement &inElement) +{ + TElemStringMap::iterator iter = m_ElementPathMap.find(&inElement); + if (iter != m_ElementPathMap.end()) + return iter->second; + + return qt3ds::foundation::CRegisteredString(); +} + +qt3ds::foundation::IStringTable &CPresentation::GetStringTable() +{ + return GetApplication().GetRuntimeFactoryCore().GetStringTable(); +} + +/** + * Current frame data stores traversal lists for use later + */ +CPresentationFrameData &CPresentation::GetFrameData() +{ + return m_FrameData; +} + +void CPresentation::SetLoadedBuffer(qt3ds::render::ILoadedBuffer &inBuffer) +{ + m_LoadedBuffer = inBuffer; +} + +/** + * Retrieve the name of the presentation. This is actually the file path. + * @return the name of this presentation + */ +const QByteArray CPresentation::GetName() const +{ + return m_Name.toLatin1(); +} + +/** + * Retrieve the size of the presentation in Studio + * @return the size of this presentation + */ +SPresentationSize CPresentation::GetSize() const +{ + return m_Size; +} + +/** + * Set the size of the presentation as reflected in Studio + * @param inSize size of presentation ( width, height, scale mode ) in Studio + */ +void CPresentation::SetSize(const SPresentationSize &inSize) +{ + m_Size = inSize; +} + +QPresentationSignalProxy *CPresentation::signalProxy() +{ + return &m_SignalProxy; +} + +} // namespace Q3DStudio |