summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJanne Kangas <janne.kangas@qt.io>2019-12-18 12:23:48 +0200
committerJanne Kangas <janne.kangas@qt.io>2019-12-27 11:20:56 +0200
commit54785b2bf2e26fb3a3dd9a050382db5f679f8907 (patch)
tree75d6d1046256bd59657241beccc0bcdbed623df3
parentc059fc4fac16afafa5aea5225d7f1051f35ce214 (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.cpp2
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.cpp66
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.h9
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp44
-rw-r--r--src/Authoring/Qt3DStudio/Application/StudioApp.cpp7
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);