diff options
author | Janne Kangas <janne.kangas@qt.io> | 2019-12-18 12:23:48 +0200 |
---|---|---|
committer | Janne Kangas <janne.kangas@qt.io> | 2019-12-27 11:20:56 +0200 |
commit | 54785b2bf2e26fb3a3dd9a050382db5f679f8907 (patch) | |
tree | 75d6d1046256bd59657241beccc0bcdbed623df3 | |
parent | c059fc4fac16afafa5aea5225d7f1051f35ce214 (diff) |
Ensure that only one camera is active per layer
Only allow one camera to be active on a layer. Activating a camera hides
the previously active one. In case of multi-selection being activated,
pick one of layer cameras in the selection and make only it active.
Also, when loading a presentation, inactivate all but one camera per layer
and show user a popup.
Change-Id: I75768f737d22f52bc94f16f10869486f7c2cad7c
Task-id: QT3DS-2153
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Antti Määttä <antti.maatta@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r-- | src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp | 2 | ||||
-rw-r--r-- | src/Authoring/Client/Code/Core/Doc/Doc.cpp | 66 | ||||
-rw-r--r-- | src/Authoring/Client/Code/Core/Doc/Doc.h | 9 | ||||
-rw-r--r-- | src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp | 44 | ||||
-rw-r--r-- | src/Authoring/Qt3DStudio/Application/StudioApp.cpp | 7 |
5 files changed, 123 insertions, 5 deletions
diff --git a/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp index 104225f0..beb4b358 100644 --- a/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp +++ b/src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp @@ -131,6 +131,7 @@ void CmdDataModel::DataModelUndo() Undo(m_Consumer->m_TransactionList); RunUndoNotifications(); m_Doc.UpdateDatainputMap(); + m_Doc.ensureActiveCamera(); } } @@ -153,6 +154,7 @@ void CmdDataModel::DataModelRedo() Redo(m_Consumer->m_TransactionList); RunDoNotifications(); m_Doc.UpdateDatainputMap(); + m_Doc.ensureActiveCamera(); } } diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.cpp b/src/Authoring/Client/Code/Core/Doc/Doc.cpp index 7a16aa25..e1ed2bb0 100644 --- a/src/Authoring/Client/Code/Core/Doc/Doc.cpp +++ b/src/Authoring/Client/Code/Core/Doc/Doc.cpp @@ -759,6 +759,58 @@ void CDoc::SetActiveLayer(qt3dsdm::Qt3DSDMInstanceHandle inLayerInstance) m_ActiveLayer = inLayerInstance; } +qt3dsdm::Qt3DSDMInstanceHandle CDoc::getActiveCamera(qt3dsdm::Qt3DSDMInstanceHandle inLayer) const +{ + return m_ActiveCameras[inLayer]; +} + +void CDoc::setActiveCamera(qt3dsdm::Qt3DSDMInstanceHandle inCameraLayer, + qt3dsdm::Qt3DSDMInstanceHandle inCameraInstance) +{ + QT3DS_ASSERT(inCameraLayer.Valid()); + m_ActiveCameras.insert(inCameraLayer, inCameraInstance); +} + +bool CDoc::ensureActiveCamera() +{ + m_ActiveCameras.clear(); + + qt3dsdm::IDataCore &theCore(*m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()); + CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge(); + qt3dsdm::TInstanceHandleList cameraInstances; + + theCore.GetInstancesDerivedFrom(cameraInstances, + theBridge->GetObjectDefinitions().m_Camera.m_Instance); + + bool camerasModified = false; + + qt3dsdm::SValue valCamEyeball; + qt3dsdm::Qt3DSDMInstanceHandle cameraLayer; + + for (const auto &inst : qAsConst(cameraInstances)) { + GetPropertySystem()->GetInstancePropertyValue + (inst, theBridge->GetSceneAsset().m_Eyeball.m_Property, valCamEyeball); + + cameraLayer = theBridge->GetResidingLayer(inst); + // Skip over instances without a valid layer. This also skips over the base camera instance + // that is included in the list we get. + if (!cameraLayer.Valid()) + continue; + if (qt3dsdm::get<bool>(valCamEyeball)) { + // Set the first camera that has eyeball=true on this layer to be active and others to + // inactive. We might have several active cameras in old presentations, + // or in presentations modified by hand. + if (!getActiveCamera(cameraLayer).Valid()) { + setActiveCamera(cameraLayer, inst); + } else { + camerasModified = true; + SetInstancePropertyValue(inst, L"eyeball", false); + m_Core->GetDispatch()->FireImmediateRefreshInstance(inst); + } + } + } + return camerasModified; +} /** * Deselects all the items and keyframes that are currently selected. */ @@ -1166,16 +1218,22 @@ void CDoc::OnSlideDeleted(qt3dsdm::Qt3DSDMSlideHandle inSlide) void CDoc::OnInstanceDeleted(qt3dsdm::Qt3DSDMInstanceHandle inInstance) { + using namespace qt3dsdm; + CClientDataModelBridge &theBridge(*m_StudioSystem->GetClientDataModelBridge()); + SComposerObjectDefinitions &theDefinitions(theBridge.GetObjectDefinitions()); + IDataCore &theCore(*m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()); + if (GetSelectedInstance() == inInstance) DeselectAllItems(); if (m_ActiveLayer == inInstance) m_ActiveLayer = 0; - using namespace qt3dsdm; - CClientDataModelBridge &theBridge(*m_StudioSystem->GetClientDataModelBridge()); - SComposerObjectDefinitions &theDefinitions(theBridge.GetObjectDefinitions()); - IDataCore &theCore(*m_StudioSystem->GetFullSystem()->GetCoreSystem()->GetDataCore()); + auto instanceLayer = theBridge.GetResidingLayer(inInstance); + if (m_ActiveCameras[instanceLayer] == inInstance) { + m_ActiveCameras.remove(instanceLayer); + } + if (theCore.IsInstanceOrDerivedFrom(inInstance, theDefinitions.m_SlideOwner.m_Instance)) { Qt3DSDMSlideHandle theSlide = theBridge.GetComponentActiveSlide(inInstance); if (theSlide == m_ActiveSlide) { diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.h b/src/Authoring/Client/Code/Core/Doc/Doc.h index 5fedd509..552cec26 100644 --- a/src/Authoring/Client/Code/Core/Doc/Doc.h +++ b/src/Authoring/Client/Code/Core/Doc/Doc.h @@ -292,6 +292,13 @@ public: void SetActiveLayer(qt3dsdm::Qt3DSDMInstanceHandle inLayerInstance); qt3dsdm::Qt3DSDMSlideHandle GetActiveSlide(); + qt3dsdm::Qt3DSDMInstanceHandle getActiveCamera(qt3dsdm::Qt3DSDMInstanceHandle inLayer) const; + void setActiveCamera(qt3dsdm::Qt3DSDMInstanceHandle inCameraLayer, + qt3dsdm::Qt3DSDMInstanceHandle inCameraInstance); + // Ensure that only one camera per layer is active. + // Returns true if additional cameras were inactivated. + bool ensureActiveCamera(); + void SetPlayMode(EPlayMode inPlayMode, long inRestoreTime = -1); bool IsPlaying(); long GetCurrentClientTime(); @@ -468,6 +475,8 @@ protected: qt3dsdm::Qt3DSDMInstanceHandle m_SceneInstance; // Pointer to the root level Scene object. qt3dsdm::Qt3DSDMSlideHandle m_ActiveSlide; // The currently active Slide Handle. qt3dsdm::Qt3DSDMInstanceHandle m_ActiveLayer; // The currently active layer. + // The currently active camera per-layer + QMap<qt3dsdm::Qt3DSDMInstanceHandle, qt3dsdm::Qt3DSDMInstanceHandle> m_ActiveCameras; CPlaybackClock *m_PlaybackClock; // Playback clock. This is used when user clicks "Play" CCore *m_Core; bool m_IsModified; diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp index 0d5a3d3d..0db1c1fe 100644 --- a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp +++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp @@ -1067,6 +1067,18 @@ public: m_Bridge.GetOrCreateGraphRoot(retval); } + // Only one camera is active by default. If we already have one active, set the new camera + // to inactive. + if (inType == ComposerObjectTypes::Camera) { + auto cameraLayer = m_Bridge.GetResidingLayer(retval); + if (!m_Doc.getActiveCamera(cameraLayer).Valid()) { + m_Doc.setActiveCamera(cameraLayer, retval); + } else { + SetInstancePropertyValue( + retval, m_Bridge.GetSceneAsset().m_Eyeball.m_Property, false); + } + } + // if we did not set time range earlier, let's set it now to match parent TInstanceHandle handle = FinalizeAddOrDrop(retval, inParent, inInsertType, inPosition, !setTimeRange, selectCreatedInstance, false); @@ -1574,6 +1586,20 @@ public: } // Now set the property for reals thePropertySystem.SetInstancePropertyValue(instance, propName, value); + } else if (propName == m_Bridge.GetSceneAsset().m_Eyeball + && m_Bridge.IsCameraInstance(instance)) { + auto cameraLayer = m_Bridge.GetResidingLayer(instance); + auto activeCamera = m_Doc.getActiveCamera(cameraLayer); + if ((instance != activeCamera) && get<bool>(value)) { + // Only one camera per layer should be active. Set the previous one to inactive if + // we are activating another one. + if (activeCamera.Valid()) + thePropertySystem.SetInstancePropertyValue(activeCamera, propName, false); + m_Doc.setActiveCamera(cameraLayer, instance); + } else if (!get<bool>(value) && activeCamera == instance) { + m_Doc.setActiveCamera(cameraLayer, {}); // Inactivating current active camera. + } + thePropertySystem.SetInstancePropertyValue(instance, propName, value); } else { if (propName != m_Bridge.GetAlias().m_ReferencedNode.m_Property) { thePropertySystem.SetInstancePropertyValue(instance, propName, value); @@ -5176,6 +5202,8 @@ public: if (selectedInstances.size() > 0) { bool boolValue = false; SValue value; + qt3dsdm::Qt3DSDMInstanceHandle firstFoundCamera; + qt3dsdm::Qt3DSDMInstanceHandle foundCameraLayer; for (size_t idx = 0, end = selectedInstances.size(); idx < end; ++idx) { qt3dsdm::Qt3DSDMInstanceHandle handle(selectedInstances[idx]); if (handle.Valid()) { @@ -5184,7 +5212,21 @@ public: propertySystem->GetInstancePropertyValue(handle, property, value); boolValue = !qt3dsdm::get<bool>(value); } - propertySystem->SetInstancePropertyValue(handle, property, boolValue); + // First found camera is the one that ends up being activated if there are + // several in selection, per-layer. Skip the rest if setting eyeball to true. + // It is ok to deactivate (hide) all cameras, though. + if (m_DataCore.IsInstanceOrDerivedFrom( + handle, m_Bridge.GetObjectDefinitions().m_Camera.m_Instance)) { + auto currCameraLayer = m_Bridge.GetResidingLayer(handle); + if ((!firstFoundCamera.Valid() || boolValue) + && !(foundCameraLayer == currCameraLayer)) { + firstFoundCamera = handle; + foundCameraLayer = currCameraLayer; + } else if (boolValue) { + continue; + } + } + SetInstancePropertyValue(handle, property, boolValue); } } } diff --git a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp index 3a3db068..8b97630c 100644 --- a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp +++ b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp @@ -1568,6 +1568,13 @@ bool CStudioApp::OnLoadDocument(const QString &inDocument, bool inShowStartupDia } } else { m_dialogs->ResetSettings(loadFile); + if (m_core->GetDoc()->ensureActiveCamera()) + m_dialogs->DisplayMessageBox( + tr("More than one camera active"), + tr("Layer can only have one active camera. " + "Additional cameras were set to inactive."), + Qt3DSMessageBox::ICON_WARNING, false); + m_core->getProjectFile().updateDocPresentationId(); m_core->getProjectFile().loadSubpresentationsAndDatainputs(m_subpresentations, m_dataInputDialogItems); |