summaryrefslogtreecommitdiffstats
path: root/src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp')
-rw-r--r--src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp b/src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp
new file mode 100644
index 00000000..4a8341b4
--- /dev/null
+++ b/src/Runtime/ogl-runtime/src/runtime/Qt3DSLogicSystem.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** 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"
+#include "Qt3DSLogicSystem.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "Qt3DSIPresentation.h"
+#include "Qt3DSApplication.h"
+#include "foundation/SerializationTypes.h"
+#include "foundation/IOStreams.h"
+
+using namespace qt3ds::runtime;
+using namespace qt3ds::foundation;
+using namespace qt3ds;
+using namespace qt3ds::runtime::element;
+
+namespace {
+struct SLogicKey
+{
+ QT3DSU32 m_ElementHandle;
+ Q3DStudio::TEventCommandHash m_CommandHash;
+ SLogicKey(QT3DSU32 hdl = 0, Q3DStudio::TEventCommandHash hash = 0)
+ : m_ElementHandle(hdl)
+ , m_CommandHash(hash)
+ {
+ }
+
+ bool operator==(const SLogicKey &other) const
+ {
+ return m_ElementHandle == other.m_ElementHandle && m_CommandHash == other.m_CommandHash;
+ }
+ size_t hash() const
+ {
+ return eastl::hash<QT3DSU32>()(m_ElementHandle) ^ eastl::hash<QT3DSU32>()((QT3DSU32)m_CommandHash);
+ }
+};
+
+struct SLogicData
+{
+ SLogicData *m_NextLogicData;
+ QT3DSU32 m_Owner;
+ QT3DSU32 m_Target;
+ Q3DStudio::TEventCommandHash m_Type;
+ Q3DStudio::UVariant m_Arg1;
+ Q3DStudio::UVariant m_Arg2;
+ QT3DSI32 m_Id;
+ bool m_Active;
+
+ SLogicData()
+ : m_NextLogicData(NULL)
+ , m_Owner(0)
+ , m_Target(0)
+ , m_Type(0)
+ , m_Id(0)
+ , m_Active(false)
+ {
+ m_Arg1.m_INT32 = 0;
+ m_Arg2.m_INT32 = 0;
+ }
+
+ SLogicData(QT3DSU32 owner, QT3DSU32 target, Q3DStudio::TEventCommandHash type, Q3DStudio::UVariant a1,
+ Q3DStudio::UVariant a2, bool active, QT3DSI32 inId)
+ : m_NextLogicData(NULL)
+ , m_Owner(owner)
+ , m_Target(target)
+ , m_Type(type)
+ , m_Arg1(a1)
+ , m_Arg2(a2)
+ , m_Id(inId)
+ , m_Active(active)
+ {
+ }
+};
+
+DEFINE_INVASIVE_SINGLE_LIST(LogicData);
+IMPLEMENT_INVASIVE_SINGLE_LIST(LogicData, m_NextLogicData);
+}
+
+namespace eastl {
+template <>
+struct hash<SLogicKey>
+{
+ size_t operator()(const SLogicKey &inKey) const { return inKey.hash(); }
+};
+}
+
+namespace {
+
+struct SLogicSystem : public ILogicSystem
+{
+ typedef nvhash_map<SLogicKey, TLogicDataList> TLogicKeyHash;
+ typedef nvhash_map<QT3DSI32, SLogicKey> TIdLogicKeyHash;
+ typedef Pool<SLogicData, ForwardingAllocator> TLogicDataPool;
+
+ NVFoundationBase &m_Foundation;
+
+ TLogicKeyHash m_LogicKeys;
+ TIdLogicKeyHash m_IdToLogicKeys;
+ TLogicDataPool m_LogicDataPool;
+ QT3DSI32 m_NextId;
+ NVDataRef<QT3DSU8> m_LoadData;
+
+ QT3DSI32 m_RefCount;
+
+ SLogicSystem(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , m_LogicKeys(inFoundation.getAllocator(), "m_LogicKeys")
+ , m_IdToLogicKeys(inFoundation.getAllocator(), "m_IdToLogicKeys")
+ , m_LogicDataPool(ForwardingAllocator(inFoundation.getAllocator(), "m_LogicDataPool"))
+ , m_NextId(1)
+ , m_RefCount(0)
+ {
+ }
+
+ void addRef() override { atomicIncrement(&m_RefCount); }
+ void release() override
+ {
+ atomicDecrement(&m_RefCount);
+ if (m_RefCount <= 0) {
+ NVAllocatorCallback &alloc(m_Foundation.getAllocator());
+ NVDelete(alloc, this);
+ }
+ }
+ void IncrementNextId()
+ {
+ ++m_NextId;
+ if (m_NextId == 0)
+ ++m_NextId;
+ }
+ static QT3DSU32 GetHandle(element::SElement *elem)
+ {
+ if (elem)
+ return elem->GetHandle();
+ return 0;
+ }
+ // returns the action id
+ QT3DSI32 AddAction(element::SElement &inTrigger,
+ Q3DStudio::TEventCommandHash inEventNameHash,
+ element::SElement *inTarget, element::SElement *inOwner,
+ Q3DStudio::TEventCommandHash inType, Q3DStudio::UVariant inArg1,
+ Q3DStudio::UVariant inArg2, bool inActive) override
+ {
+ SLogicKey theKey(inTrigger.GetHandle(), inEventNameHash);
+ eastl::pair<TLogicKeyHash::iterator, bool> inserter =
+ m_LogicKeys.insert(eastl::make_pair(theKey, TLogicDataList()));
+
+ eastl::pair<TIdLogicKeyHash::iterator, bool> idInserter;
+ for (idInserter = m_IdToLogicKeys.insert(eastl::make_pair(m_NextId, theKey));
+ idInserter.second == false;
+ idInserter = m_IdToLogicKeys.insert(eastl::make_pair(m_NextId, theKey))) {
+ IncrementNextId();
+ }
+ IncrementNextId();
+
+ SLogicData *theData = m_LogicDataPool.construct(__FILE__, __LINE__);
+ *theData = SLogicData(GetHandle(inOwner), GetHandle(inTarget), inType, inArg1, inArg2,
+ inActive, idInserter.first->first);
+ inserter.first->second.push_back(*theData);
+ return idInserter.first->first;
+ }
+
+ void OnEvent(Q3DStudio::TEventCommandHash inEventName, element::SElement &inTarget,
+ Q3DStudio::IPresentation &inPresentation) const override
+ {
+ SLogicKey theKey(inTarget.GetHandle(), inEventName);
+ TLogicKeyHash::const_iterator iter = m_LogicKeys.find(theKey);
+ if (iter != m_LogicKeys.end()) {
+ qt3ds::runtime::IApplication &theApplication = inPresentation.GetApplication();
+ qt3ds::runtime::IElementAllocator &theElemAllocator =
+ theApplication.GetElementAllocator();
+ for (TLogicDataList::const_iterator listIter = iter->second.begin(),
+ endIter = iter->second.end();
+ listIter != endIter; ++listIter) {
+ if (listIter->m_Active) {
+ inPresentation.FireCommand(
+ listIter->m_Type, theElemAllocator.FindElementByHandle(listIter->m_Target),
+ &listIter->m_Arg1, &listIter->m_Arg2);
+ }
+ }
+ }
+ }
+
+ void SetActive(QT3DSI32 inActionIndex, bool inActive, IElementAllocator &inElemAllocator) override
+ {
+ TIdLogicKeyHash::iterator iter = m_IdToLogicKeys.find(inActionIndex);
+ if (iter != m_IdToLogicKeys.end()) {
+ TLogicKeyHash::iterator logicIter = m_LogicKeys.find(iter->second);
+ if (logicIter != m_LogicKeys.end()) {
+ for (TLogicDataList::iterator listIter = logicIter->second.begin(),
+ listEnd = logicIter->second.end();
+ listIter != listEnd; ++listIter)
+ if (listIter->m_Id == inActionIndex) {
+ listIter->m_Active = inActive;
+ if (IApplication::isPickingEvent(logicIter->first.m_CommandHash)) {
+ SElement *theElement = inElemAllocator.FindElementByHandle(
+ logicIter->first.m_ElementHandle);
+ if (theElement && inActive)
+ theElement->SetFlag(Q3DStudio::ELEMENTFLAG_PICKENABLED, true);
+ }
+ }
+ }
+ }
+ }
+
+ void SaveBinaryData(qt3ds::foundation::IOutStream &ioStream) override
+ {
+ qt3ds::foundation::SWriteBuffer theWriter(m_Foundation.getAllocator(), "WriteBuffer");
+ theWriter.write(m_NextId);
+ theWriter.write((QT3DSU32)m_LogicKeys.size());
+ for (TLogicKeyHash::iterator iter = m_LogicKeys.begin(), end = m_LogicKeys.end();
+ iter != end; ++iter) {
+ if (iter->second.m_Head == NULL)
+ continue;
+
+ theWriter.write(iter->first);
+ QT3DSU32 datumOffset = theWriter.size();
+ theWriter.write((QT3DSU32)0);
+ QT3DSU32 datumCount = 0;
+ for (SLogicData *theDatum = iter->second.m_Head; theDatum;
+ theDatum = theDatum->m_NextLogicData, ++datumCount) {
+ theWriter.write(*theDatum);
+ }
+ QT3DSU32 *countPtr = reinterpret_cast<QT3DSU32 *>(theWriter.begin() + datumOffset);
+ *countPtr = datumCount;
+ }
+ ioStream.Write(theWriter.begin(), theWriter.size());
+ }
+
+ void LoadBinaryData(NVDataRef<QT3DSU8> inLoadData) override
+ {
+ m_LoadData = inLoadData;
+ SDataReader theReader(inLoadData.begin(), inLoadData.end());
+ m_NextId = *theReader.Load<QT3DSI32>();
+ QT3DSU32 numKeys = *theReader.Load<QT3DSU32>();
+ for (QT3DSU32 idx = 0, end = numKeys; idx < end; ++idx) {
+ SLogicKey theKey = *theReader.Load<SLogicKey>();
+ QT3DSU32 numActions = *theReader.Load<QT3DSU32>();
+ if (numActions == 0)
+ continue;
+
+ TLogicKeyHash::iterator inserter =
+ m_LogicKeys.insert(eastl::make_pair(theKey, TLogicDataList())).first;
+ SLogicData *lastDatum = NULL;
+ for (QT3DSU32 actIdx = 0, actEnd = numActions; actIdx < actEnd; ++actIdx) {
+ SLogicData *nextDatum = theReader.Load<SLogicData>();
+ if (lastDatum == NULL)
+ inserter->second.m_Head = nextDatum;
+ else
+ lastDatum->m_NextLogicData = nextDatum;
+ lastDatum = nextDatum;
+ m_IdToLogicKeys.insert(eastl::make_pair(nextDatum->m_Id, theKey));
+ }
+ if (lastDatum)
+ lastDatum->m_NextLogicData = NULL;
+ }
+ }
+};
+}
+
+ILogicSystem &ILogicSystem::CreateLogicSystem(NVFoundationBase &inFnd)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), SLogicSystem)(inFnd);
+}