summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.qmake.conf2
-rw-r--r--doc/qt3dstudio-project.qdocconf10
-rw-r--r--doc/src/00-concepts.qdoc2
-rw-r--r--doc/src/03-studio/0-menu.qdoc4
-rw-r--r--doc/src/03-studio/1-toolbar.qdoc4
-rw-r--r--doc/src/03-studio/4-basic-objects-palette.qdoc19
-rw-r--r--doc/src/03-studio/5-timeline-palette.qdoc7
-rw-r--r--doc/src/03-studio/7-inspector-palette.qdoc66
-rw-r--r--doc/src/03-studio/8-action-palette.qdoc31
-rw-r--r--doc/src/04-viewer/0-menu.qdoc62
-rw-r--r--doc/src/04-viewer/1-keyboard.qdoc49
-rw-r--r--doc/src/04-viewer/2-commandline.qdoc90
-rw-r--r--doc/src/04-viewer/3-remote-deployment.qdoc20
-rw-r--r--doc/src/07-file-formats/0-uia.qdoc2
-rw-r--r--doc/src/07-file-formats/5-custom-material-reference.qdoc30
-rw-r--r--doc/src/07-file-formats/6-effect-reference.qdoc21
-rw-r--r--doc/src/07-file-formats/custom-materials-effects.qdoc116
-rw-r--r--doc/src/10-best-practices/100-elementvisibilities.qdoc124
-rw-r--r--doc/src/10-best-practices/30-using-sub-presentations.qdoc4
-rw-r--r--doc/src/10-best-practices/80-effects.qdoc53
-rw-r--r--doc/src/10-best-practices/95-data-input.qdoc11
-rw-r--r--doc/src/10-best-practices/brush-strokes.qdoc65
-rw-r--r--doc/src/10-best-practices/corona.qdoc106
-rw-r--r--doc/src/10-best-practices/emboss-effect.qdoc51
-rw-r--r--doc/src/10-best-practices/exporting-from-3dsmax.qdoc (renamed from doc/Src/10-best-practices/exporting-from-3dsmax.qdoc)0
-rw-r--r--doc/src/10-best-practices/exporting-from-blender.qdoc (renamed from doc/Src/10-best-practices/exporting-from-blender.qdoc)0
-rw-r--r--doc/src/10-best-practices/exporting-from-maya.qdoc (renamed from doc/Src/10-best-practices/exporting-from-maya.qdoc)0
-rw-r--r--doc/src/10-best-practices/exporting-from-modo.qdoc (renamed from doc/Src/10-best-practices/exporting-from-modo.qdoc)0
-rw-r--r--doc/src/10-best-practices/frame-flipper.qdoc60
-rw-r--r--doc/src/10-best-practices/fullscreen-texture-overlay.qdoc57
-rw-r--r--doc/src/10-best-practices/practices-index.qdoc2
-rw-r--r--doc/src/10-best-practices/screen-space-ao.qdoc96
-rw-r--r--doc/src/10-best-practices/sepia.qdoc51
-rw-r--r--doc/src/10-best-practices/smaa1x.qdoc41
-rw-r--r--doc/src/10-best-practices/stylize-scatter.qdoc66
-rw-r--r--doc/src/10-best-practices/vignette.qdoc56
-rw-r--r--doc/src/11-quick-start-guides/quick-start-guide.qdoc9
-rw-r--r--doc/src/comparison.qdoc5
-rw-r--r--doc/src/glossary.qdoc153
-rw-r--r--doc/src/images/ApplicationPreferences.pngbin23388 -> 24617 bytes
-rw-r--r--doc/src/images/Studio-Basic-Signal.pngbin0 -> 9918 bytes
-rw-r--r--doc/src/images/Studio-SceneView.pngbin207201 -> 209545 bytes
-rw-r--r--doc/src/images/Studio-Timeline-SceneGraph.pngbin22222 -> 9931 bytes
-rw-r--r--doc/src/images/Studio-Timeline-SignalAction.pngbin0 -> 8576 bytes
-rw-r--r--doc/src/images/addAssets.pngbin227735 -> 229395 bytes
-rw-r--r--doc/src/images/brush-strokes-icon.pngbin0 -> 8695 bytes
-rw-r--r--doc/src/images/corona-icon.pngbin0 -> 11732 bytes
-rw-r--r--doc/src/images/datainput-meta.pngbin10035 -> 9515 bytes
-rw-r--r--doc/src/images/editListGroupObjects.pngbin0 -> 4209 bytes
-rw-r--r--doc/src/images/effects-brush-strokes.pngbin0 -> 54544 bytes
-rw-r--r--doc/src/images/effects-corona.pngbin0 -> 51977 bytes
-rw-r--r--doc/src/images/effects-emboss.pngbin0 -> 61625 bytes
-rw-r--r--doc/src/images/effects-frame-flipper.pngbin0 -> 107745 bytes
-rw-r--r--doc/src/images/effects-fullscreen-texture-overlay.pngbin0 -> 57512 bytes
-rw-r--r--doc/src/images/effects-screen-space-ao.pngbin0 -> 80226 bytes
-rw-r--r--doc/src/images/effects-sepia.pngbin0 -> 46435 bytes
-rw-r--r--doc/src/images/effects-smaa1x.pngbin0 -> 39146 bytes
-rw-r--r--doc/src/images/effects-stylize-scatter.pngbin0 -> 52224 bytes
-rw-r--r--doc/src/images/effects-vignette.pngbin0 -> 59815 bytes
-rw-r--r--doc/src/images/emboss-icon.pngbin0 -> 8506 bytes
-rw-r--r--doc/src/images/frame-flipper-icon.pngbin0 -> 6009 bytes
-rw-r--r--doc/src/images/fullscreen-texture-overlay-icon.pngbin0 -> 12349 bytes
-rw-r--r--doc/src/images/materials-category-dummy.pngbin0 -> 16852 bytes
-rw-r--r--doc/src/images/materials-category-several.pngbin0 -> 20414 bytes
-rw-r--r--doc/src/images/new-data-input.pngbin8381 -> 7749 bytes
-rw-r--r--doc/src/images/screen-space-ao-icon.pngbin0 -> 11068 bytes
-rw-r--r--doc/src/images/sepia-icon.pngbin0 -> 7583 bytes
-rw-r--r--doc/src/images/smaa1x-icon.pngbin0 -> 10458 bytes
-rw-r--r--doc/src/images/stylize-scatter-icon.pngbin0 -> 10801 bytes
-rw-r--r--doc/src/images/timeline-datainput.pngbin22729 -> 10463 bytes
-rw-r--r--doc/src/images/variant-tags-panel.pngbin8736 -> 9733 bytes
-rw-r--r--doc/src/images/vignette-icon.pngbin0 -> 11702 bytes
-rw-r--r--doc/src/layers.qdoc11
-rw-r--r--doc/src/whatsnew.qdoc64
-rw-r--r--doc/style/qt5-sidebar.html12
-rw-r--r--product_dependencies.yaml3
-rw-r--r--qt3dstudio.pro27
-rw-r--r--src/Authoring/Client/Code/Core/Commands/CmdDataModel.cpp2
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp276
-rw-r--r--src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h49
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.cpp138
-rw-r--r--src/Authoring/Client/Code/Core/Doc/Doc.h14
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp17
-rw-r--r--src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp357
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp141
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h9
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h1
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h4
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h6
-rw-r--r--src/Authoring/Client/Code/Core/Doc/IDocumentReader.h9
-rw-r--r--src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp9
-rw-r--r--src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h4
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp13
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h1
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp41
-rw-r--r--src/Authoring/Client/Code/Core/Utility/StudioPreferences.h13
-rw-r--r--src/Authoring/Common/Code/Qt3DSMessageBox.cpp32
-rw-r--r--src/Authoring/Common/Code/Qt3DSMessageBox.h7
-rw-r--r--src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h7
-rw-r--r--src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.cpp126
-rw-r--r--src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.cpp2
-rw-r--r--src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.h6
-rw-r--r--src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportColladaSGTranslation.cpp12
-rw-r--r--src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportFbxSGTranslation.cpp27
-rw-r--r--src/Authoring/Qt3DStudio/Application/DataInputDlg.cpp29
-rw-r--r--src/Authoring/Qt3DStudio/Application/DataInputDlg.h6
-rw-r--r--src/Authoring/Qt3DStudio/Application/DataInputListDlg.cpp6
-rw-r--r--src/Authoring/Qt3DStudio/Application/DataInputSelectView.cpp5
-rw-r--r--src/Authoring/Qt3DStudio/Application/ProjectFile.cpp6
-rw-r--r--src/Authoring/Qt3DStudio/Application/StudioApp.cpp33
-rw-r--r--src/Authoring/Qt3DStudio/Application/StudioApp.h24
-rw-r--r--src/Authoring/Qt3DStudio/DragAndDrop/BasicObjectDropSource.cpp14
-rw-r--r--src/Authoring/Qt3DStudio/Info.plist146
-rw-r--r--src/Authoring/Qt3DStudio/MainFrm.cpp32
-rw-r--r--src/Authoring/Qt3DStudio/MainFrm.h3
-rw-r--r--src/Authoring/Qt3DStudio/MainFrm.ui31
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp44
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/ActionView.h9
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericBaseColor.qml2
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericFloat.qml4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXY.qml6
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZ.qml9
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZW.qml11
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZ.qml4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZW.qml4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/BasicObjects/BasicObjectsModel.cpp1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.cpp196
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.h6
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.cpp14
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.qml40
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/TextureChooserView.cpp16
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/PaletteManager.cpp1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.cpp62
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.h8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.cpp27
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.h4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.qml29
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Slide/SlideView.qml3
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItem.h10
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp33
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp35
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp13
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp40
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp16
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h3
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTreeLabel.cpp4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/controls/FloatTextField.qml9
-rw-r--r--src/Authoring/Qt3DStudio/PreviewHelper.cpp26
-rw-r--r--src/Authoring/Qt3DStudio/Qt3DStudio.pro10
-rw-r--r--src/Authoring/Qt3DStudio/Render/IStudioRenderer.h2
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioRenderer.cpp26
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.cpp267
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.h24
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioSubPresentationRenderer.cpp9
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioTranslationWidget.cpp112
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioWidget.h2
-rw-r--r--src/Authoring/Qt3DStudio/Render/StudioWidgetImpl.h4
-rw-r--r--src/Authoring/Qt3DStudio/UI/SceneView.cpp7
-rw-r--r--src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.cpp17
-rw-r--r--src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.h1
-rw-r--r--src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.ui23
-rw-r--r--src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.cpp11
-rw-r--r--src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.ui10
-rw-r--r--src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp8
-rw-r--r--src/Authoring/Qt3DStudio/images.qrc6
-rw-r--r--src/Authoring/Qt3DStudio/images/Asset-Signal-Normal.pngbin0 -> 424 bytes
-rw-r--r--src/Authoring/Qt3DStudio/images/Asset-Signal-Normal@2x.pngbin0 -> 915 bytes
-rw-r--r--src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled.pngbin0 -> 1562 bytes
-rw-r--r--src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled@2x.pngbin0 -> 1829 bytes
-rw-r--r--src/Authoring/Qt3DStudio/images/Objects-Signal-Normal.pngbin0 -> 2099 bytes
-rw-r--r--src/Authoring/Qt3DStudio/images/Objects-Signal-Normal@2x.pngbin0 -> 2466 bytes
-rw-r--r--src/Runtime/Runtime.pro20
m---------src/Runtime/ogl-runtime0
m---------src/Runtime/qt3d-runtime0
181 files changed, 3611 insertions, 980 deletions
diff --git a/.gitmodules b/.gitmodules
index 3d43dde3..aad74655 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,9 +4,6 @@
[submodule "src/3rdparty/pcre"]
path = src/3rdparty/pcre
url = ../qt3dstudio-pcre.git
-[submodule "src/Runtime/qt3d-runtime"]
- path = src/Runtime/qt3d-runtime
- url = ../qt3d-runtime.git
[submodule "src/Runtime/ogl-runtime"]
path = src/Runtime/ogl-runtime
url = ../ogl-runtime
diff --git a/.qmake.conf b/.qmake.conf
index daeeb9f2..b89275b0 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,5 +1,5 @@
load(qt_build_config)
-MODULE_VERSION = 2.5.0
+MODULE_VERSION = 2.8.0
CMAKE_MODULE_TESTS=-
diff --git a/doc/qt3dstudio-project.qdocconf b/doc/qt3dstudio-project.qdocconf
index 0f32aae9..d0c896e9 100644
--- a/doc/qt3dstudio-project.qdocconf
+++ b/doc/qt3dstudio-project.qdocconf
@@ -5,15 +5,17 @@ url = https://doc.qt.io/qt3dstudio
moduleheader =
sources.fileextensions = "*.qdoc *.html"
-sourcedirs = . \
- ../src/Viewer
+sourcedirs = src/ \
+ ../src/Runtime/ogl-runtime/src/viewer
-headerdirs = ../src/Viewer
+headerdirs = src/ \
+ ../src/Runtime/ogl-runtime/src/viewer
# TODO: Move images to doc/images
imagedirs = ./src/images
-depends = qtcore qtgui qtwidgets qtqml qtquick qtmultimedia qtdoc qt3dstudioruntime2
+depends = qtcore qtgui qtwidgets qtqml qtquick qtmultimedia qtdoc
+
qhp.projects = Qt3DStudio
diff --git a/doc/src/00-concepts.qdoc b/doc/src/00-concepts.qdoc
index 61f1d1f4..88d02d74 100644
--- a/doc/src/00-concepts.qdoc
+++ b/doc/src/00-concepts.qdoc
@@ -34,6 +34,8 @@
Qt 3D Studio is a compositing tool where you import 3D models, images and other assets to create
interactive presentations, UIs and applications.
+See \l{What's New}{what's new} in Qt 3D Studio.
+
\table
\row
\li
diff --git a/doc/src/03-studio/0-menu.qdoc b/doc/src/03-studio/0-menu.qdoc
index f1359cf2..fecaff8b 100644
--- a/doc/src/03-studio/0-menu.qdoc
+++ b/doc/src/03-studio/0-menu.qdoc
@@ -116,10 +116,6 @@
\li
\uicontrol{Timeline Snapping Grid} - When using snapping in the
timeline, controls which ticks to snap to.
- \li
- \uicontrol{Legacy Viewer} - Enables the legacy viewer preview button in the toolbar. Legacy
- viewer uses Runtime from Qt 3D Studio 1.1, whereas the default viewer uses Runtime from
- Qt 3D Studio 2.0. Requires a restart.
\endlist
\li
\uicontrol{Editing View}
diff --git a/doc/src/03-studio/1-toolbar.qdoc b/doc/src/03-studio/1-toolbar.qdoc
index 98a5400a..8f3e8a5d 100644
--- a/doc/src/03-studio/1-toolbar.qdoc
+++ b/doc/src/03-studio/1-toolbar.qdoc
@@ -253,10 +253,6 @@ The preview toolbar buttons are used to preview your presentation.
The \b{Remote Preview} button (keyboard shortcut: \c{F6})will launch the presentation on the
connected remote device Qt 3D Studio Viewer application. This button is only enabled if you are
connected to a remote device.
- \li
- The \b{Preview with Qt 3D Runtime} button
- will launch the Qt 3D Runtime Viewer application and preview the
- application for the presentation.
\endlist
\note If there is no \c{.uia} file in the folder for the presentation, then the
diff --git a/doc/src/03-studio/4-basic-objects-palette.qdoc b/doc/src/03-studio/4-basic-objects-palette.qdoc
index 9da6ff8e..a45bdf67 100644
--- a/doc/src/03-studio/4-basic-objects-palette.qdoc
+++ b/doc/src/03-studio/4-basic-objects-palette.qdoc
@@ -113,6 +113,25 @@ of the following:
This will create a group and move the selected objects into the group.
\endlist
+\section1 Signal
+
+\table
+ \row
+ \li \image Studio-Basic-Signal.png
+\endtable
+
+A signal is a lightweight object specifically designed for triggering actions
+during timeline animations. When signal object is created, it automatically
+adds also initial \c{onActivate} action which gets triggered at the beginning
+of signal timeline. Signals can also contain \c{onDeactivate} actions which
+are triggered at the end of signal timeline. If an object contains these
+actions, its timeline bar contains markers at the beginning (\c{onActivate})
+and/or end (\c{onDeactivate}).
+
+\note Signal time bar length should be long enough (say 100ms) to make sure
+it becomes active even on less performant target hardware. Too short
+time bar might be skipped leading to actions not being triggered.
+
\section1 Text
\table
diff --git a/doc/src/03-studio/5-timeline-palette.qdoc b/doc/src/03-studio/5-timeline-palette.qdoc
index 0f917151..9597987c 100644
--- a/doc/src/03-studio/5-timeline-palette.qdoc
+++ b/doc/src/03-studio/5-timeline-palette.qdoc
@@ -121,6 +121,13 @@ Elsewhere in the interface, a green item indicates an action on the
master slide, while a light gray item indicates an action specific to
this slide.
+When an object has \c{onActivate} or \c{onDeactivate} timeline actions
+on it, those are indicated with markers at the beginning and at the
+end of the time bar. These actions are usually used with
+\l{studio-basic-objects-palette.html#Signal}{Signal} objects.
+
+\image Studio-Timeline-SignalAction.png
+
\section2 Editing Components
Components are somewhat like mini scenes. A component has its own set of
diff --git a/doc/src/03-studio/7-inspector-palette.qdoc b/doc/src/03-studio/7-inspector-palette.qdoc
index 392e788b..45b9f19b 100644
--- a/doc/src/03-studio/7-inspector-palette.qdoc
+++ b/doc/src/03-studio/7-inspector-palette.qdoc
@@ -236,14 +236,34 @@ in the Inspector palette:
presentation and the layer, either in pixels or as a percentage of the
presentation's height.
\li
- \b{Ambient Occlusion} - Controls the strength of ambient
- occlusion (AO). AO is a form of approximated global illumination which
+ \b{Dynamic Resize} - The layer is resized dynamically based on the content.
+ This allows the layer texture to be the smallest possible in order to increase performance.
+ The texture is continuously resized as the content changes.
+\li
+ \b{Padding} - The resized layer can be padded. This lowers the amount of resizes
+ needed as the content changes. The layer is resized only when the content changes
+ so much that it exceeds the previous padded size. Padding is also used in reverse
+ to calculate the lower bounds. When the content changes to be smaller, the resize
+ only happens after it takes less space than the lower bounds. The padding can be
+ expressed in pixels or as percentage of the layer size.
+\li
+ \b{Combine Bounds} - When \c{Dynamic Resize} is in use, the bounds of the objects
+ inside the layer have to be calculated. When this property is disabled, all object
+ bounds are calculated separately and a more accurate layer resize is done based on
+ those separated bounds. When this property is enabled, the object bound calculations
+ are combined, causing more inaccurate but faster results.
+\li
+ \b{Ambient Occlusion} - Enables ambient occlusion (AO).
+ AO is a form of approximated global illumination which
causes non-directional self-shadowing where objects are close
- together. A value of \c{100} causes full darkness shadows; lower
- values cause the shadowing to appear lighter. A value of \c{0}
- disables ambient occlusion entirely, improving performance at a cost
- to the visual realism of 3D objects rendered in the layer. All values
- other than \c{0} have the same impact to the performance.
+ together. Disabling ambient occlusion improves performance
+ at a cost to the visual realism of 3D objects rendered in the layer.
+\li
+ \b{AO Strength} - Controls the strength of the ambient occlusion.
+ A value of \c{100} causes full darkness shadows; lower values cause the
+ shadowing to appear lighter. A value of \c{0} effectively disables ambient
+ occlusion. All values other than \c{0} have the same impact to the performance,
+ when \b{Ambient Occlusion} is toggled on.
\li
\b{AO Distance} - Roughly how far (in world units) ambient
occlusion shadows spread away from objects. The following graphic
@@ -586,6 +606,24 @@ in the Inspector palette (in addition to the
\endomit
\endlist
+\target group-properties
+\section1 Group Properties
+
+A group selected in the Timeline palette shows the usual basic properties, but has one more
+option \e{Ordered}.
+
+\list
+\li
+ \b{Ordered} - This flag changes the order which the objects are being drawn in.
+ Having \e{Ordered} enabled gives you the ability to place objects in your desired draw order
+ under the group, regardless of the object's position in the scene.
+ The last object in the group is drawn first and the first one last,
+ so the objects higher up in the group are drawn on top of the objects below them.
+ This property only affects rendering of transparent object unless the layer
+ \e{\l{best-practices-disable-depth-test.html}{Depth Test}}
+ is disabled.
+\endlist
+
\target material-properties
\section1 Material Properties
@@ -838,9 +876,9 @@ The Inspector palette shows only a single property:
\section1 Image Properties
When image maps (e.g. Diffuse, Specular, Opacity, etc.) are applied to an animated material,
-a new element appears in the scene graph as a child of the material. This element represents
-the properties that control that image, allowing them to be animated over time. Selecting one of
-these images shows the image properties in the Inspector palette.
+custom material or effect, a new element appears in the scene graph as a child of the material.
+This element represents the properties that control that image, allowing them to be animated
+over time. Selecting one of these images shows the image properties in the Inspector palette.
For basic and referenced materials, you need to first select the material in the scene graph. Then,
right-click the map property name in the inspector and select \uicontrol {Open in inspector} from
@@ -880,6 +918,14 @@ the context menu. Now the properties of the image map will show in the inspector
\li
\b{U/V Pivot} - Sets the pivot location in UV space.
\li
+ \b{Minification Filter} - Sets the minification filter for the Image. Setting
+ the filter to \c NearestMipmapNearest, \c LinearMipmapNearest or \c LinearMipmapLinear
+ enables mipmapping. If the source image doesn't have mipmaps they are autogenerated.
+ Enabling mipmapping to image with sub-presentation should be avoided since they need to be
+ generated each time the sub-presentation is updated.
+\li
+ \b{Magnification Filter} - Sets the magnification filter for the Image.
+\li
\b{Sub-Presentation} - If you specify a value here, it is
intepreted to be the \c{id} attribute of another presentation in
\omit
diff --git a/doc/src/03-studio/8-action-palette.qdoc b/doc/src/03-studio/8-action-palette.qdoc
index 501b4264..e381647d 100644
--- a/doc/src/03-studio/8-action-palette.qdoc
+++ b/doc/src/03-studio/8-action-palette.qdoc
@@ -136,35 +136,4 @@ was specified with a Path Reference then the new action will use element
This allows you to quickly
copy and paste actions to multiple elements with a minimum of editing on
each new action.
-
-\omit
-TODO: Not appropriate until we have state machine or somesuch back.
-\section1 When to Use Actions
-
-Generally, actions are appropriate for:
-
-\list
-\li
- Reporting the intention of touch interactions to the state machine
- - \e{"when the user taps on this component, it means that you should
- mute the volume"}.
-\li
- Communicating events raised by presentation behaviors - \e {"you told
- the the list manager to show the next item, but it says that there are
- no more to show"}.
-\li
- Performing trivial view changes that do not affect the state machine
- - \e{"when the user presses down on this button, make it glow a
- little"}
-\endlist
-
-Using actions beyond the above is fine for rough prototyping
-(\e{"when the user taps the `music' button tell the scene to switch
-to to the Music slide"}), but should be evaluated for implementation at
-the application level (\e{"when the user taps the `music' button,
-tell the state machine that they want to see music; separately,
-\b{only if} the state machine tells me that we should be seeing
-music then a visual action will make the scene to go to the Music
-slide"}).
-\endomit
*/
diff --git a/doc/src/04-viewer/0-menu.qdoc b/doc/src/04-viewer/0-menu.qdoc
index 253e59ca..6075b8fe 100644
--- a/doc/src/04-viewer/0-menu.qdoc
+++ b/doc/src/04-viewer/0-menu.qdoc
@@ -36,30 +36,64 @@
\list
\li
- \b{Open...} - Open a \c{.uip} presentation or
- \c{.uia} application file to view.
+ \uicontrol {Open...} - Open a \c {.uip} presentation or \c {.uia} project file to view.
\li
- \b{Open Without Profiling...} - Same as \uicontrol Open but with certain profiling related
- features disabled in order to improve performance.
+ \uicontrol {Connect...} - Open the remote deployment port setting dialog.
\li
- \b{Remote Setup} - Switches to the remote deployment settings screen with
- instructions on how to remotely send presentations to this viewer.
+ \uicontrol {Reload} - Restart the presentation from the beginning.
\li
- \b{Reload} - Restart the presentation/application from the
- beginning.
-\li
- \b{Exit} - Quit the Viewer.
+ \uicontrol {Quit} - Quit the Viewer.
\endlist
\section1 View
\list
\li
- \b{Toggle Full Screen} - Switches to fullscreen mode. The menu bar may still
- be visible, depending on the windowing system.
+ \uicontrol {Show Matte} - Toggle matte on or off. If this is disabled, the whole screen will be
+ filled with the background color.
+\li
+ \uicontrol {Scale Mode} - Open the scale mode sub menu.
+ \list
+ \li
+ \uicontrol {Center} - Center the presentation inside the window without scaling.
+ \li
+ \uicontrol {Scale to Fit} - Scale the presentation to fit the window without extending the
+ background.
+ \li
+ \uicontrol {Scale to Fill} - Scale the presentation to fit the window while extending the
+ background to fill the window.
+ \endlist
+\li
+ \uicontrol {Stereo Mode} - Open the stereo mode sub menu.
+ \list
+ \li
+ \uicontrol {Mono} - Disable stereo mode.
+ \li
+ \uicontrol {Top-Bottom} - Switch to top-bottom stereo mode. In this mode image for left
+ eye is rendered on top and image for right eye is rendered at the bottom.
+ \li
+ \uicontrol {Left-Right} - Switch to left-right stereo mode. In this mode images for left
+ and right eye are rendered side-by-side.
+ \li
+ \uicontrol {Anaglyph (Red - Cyan)} - Switch to red-cyan anaglyph stereo mode.
+ \note Anaglyph modes do not support all features.
+ \li
+ \uicontrol {Anaglyph (Green - Magenta)} - Switch to green-magenta anaglyph stereo mode.
+ \note Anaglyph modes do not support all features.
+ \li
+ \uicontrol {Progressive Rendering} - Toggle progressive rendering on or off.
+ \li
+ \uicontrol {Increase Separation} - Increase the eye separation.
+ \li
+ \uicontrol {Decrease Separation} - Decrease the eye separation.
+\endlist
+\li
+ \uicontrol {Show Render Statistics} - Switch the render statistics on or off. Render
+ statistics include information of the FPS, frame time, and init time of the whole presentation,
+ as well as time taken by different passes for each layer.
\li
- \b{Profile and Debug} - Submenu with options to show/hide the built-in, in-scene
- profiling and information pane, and to control its scale factor.
+ \uicontrol {Full Screen} - Switch to fullscreen mode. The menu bar may still be visible,
+ depending on the windowing system.
\endlist
*/
diff --git a/doc/src/04-viewer/1-keyboard.qdoc b/doc/src/04-viewer/1-keyboard.qdoc
index 10296605..a0e61e40 100644
--- a/doc/src/04-viewer/1-keyboard.qdoc
+++ b/doc/src/04-viewer/1-keyboard.qdoc
@@ -46,12 +46,17 @@
\li \c{Ctrl + O}
\li \c{Cmd + O}
\row
+ \li Connect
+ \li \c{F9}
+ \li \c{F9}
+ \li \c{F9}
+ \row
\li Reload
\li \c{F5}
\li \c{Ctrl + R}
\li \c{F5}
\row
- \li Exit
+ \li Quit
\li \c{Ctrl + Q}
\li \c{Ctrl + Q}
\li \c{Cmd + Q}
@@ -66,58 +71,48 @@
\li Linux
\li macOS
\row
- \li Show matte
+ \li Show Matte
\li \c{Ctrl + D}
\li \c{Ctrl + D}
\li \c{Cmd + D}
\row
- \li Scale mode (toggle)
+ \li Scale Mode (toggle)
\li \c{Ctrl + Shift + S}
\li \c{Ctrl + Shift + S}
\li \c{Cmd + Shift + S}
\row
- \li Stereo mode (toggle)
+ \li Stereo Mode (toggle)
\li \c{Ctrl + Shift + T}
\li \c{Ctrl + Shift + T}
\li \c{Cmd + Shift + T}
\row
- \li Increase separation (in stereo mode)
+ \li Progressive Rendering (in stereo mode)
+ \li \c{Ctrl + Shift + P}
+ \li \c{Ctrl + Shift + P}
+ \li \c{Cmd + Shift + P}
+ \row
+ \li Increase Separation (in stereo mode)
\li \c{Ctrl + Shift + +}
\li \c{Ctrl + Shift + +}
\li \c{Cmd + Shift + +}
\row
- \li Decrease separation (in stereo mode)
+ \li Decrease Separation (in stereo mode)
\li \c{Ctrl + Shift + -}
\li \c{Ctrl + Shift + -}
\li \c{Cmd + Shift + -}
\row
- \li Full screen
+ \li Show Render Statistics
+ \li \c{F7}
+ \li \c{F7}
+ \li \c{F7}
+ \row
+ \li Full Screen
\li \c{F11}
\li \c{Ctrl + F11}
\li \c{F11}
\row
\li
\li {3, 1} To exit full screen, \c {F11}, \c {ESC} or swipe down gesture can be used.
- \row
- \li Toggle in-scene debug view
- \li \c{F10}
- \li \c{F10}
- \li \c{F10}
- \row
- \li Toggle console
- \li \c{`}
- \li \c{`}
- \li \c{`}
- \row
- \li Scale in-scene debug up
- \li \c{Ctrl + F10}
- \li \c{Ctrl + F10}
- \li \c{Cmd + F10}
- \row
- \li Scale in-scene debug down
- \li \c{Alt + F10}
- \li \c{Alt + F10}
- \li \c{Option + F10}
\endtable
*/
diff --git a/doc/src/04-viewer/2-commandline.qdoc b/doc/src/04-viewer/2-commandline.qdoc
index e45a0e78..4469cff3 100644
--- a/doc/src/04-viewer/2-commandline.qdoc
+++ b/doc/src/04-viewer/2-commandline.qdoc
@@ -37,7 +37,7 @@ for incoming connections with a presentation sent remotely.
\section1 Usage
\badcode
- q3dsviewer [options] [presentation file]
+ Qt3DViewer [options] [presentation file]
\endcode
When no filename is given, the viewer is launched in remote connection mode.
@@ -49,29 +49,77 @@ The following command line options are supported:
\li Option
\li Description
\row
- \li -?, -h, --help
+ \li -h, --help
\li Displays help for command line usage.
\row
- \li -f, --fullscreen
+ \li --sequence
+ \li Generates an image sequence. The file argument must be specified. Specifying any of
+ the \c {seq-*} arguments implies setting this option.
+ \row
+ \li --seq-start <ms>
+ \li Start time of the sequence in milliseconds. The default value is \c {0}.
+ \row
+ \li --seq-end <ms>
+ \li End time of the sequence in milliseconds. The default value is \c {1000}.
+ \row
+ \li --seq-fps <fps>
+ \li Frames per second for the sequence. The default value is \c {60}.
+ \row
+ \li --seq-interval <ms>
+ \li Time interval between frames in the sequence in milliseconds. The \c {seq-fps} argument
+ is ignored if this argument is used.
+ \row
+ \li --seq-width <pixels>
+ \li Width of the image sequence. The default value is \c {1920}.
+ \row
+ \li --seq-height <pixels>
+ \li Height of the image sequence. The default value is \c {1080}.
+ \row
+ \li --seq-outpath <path>
+ \li Output path of the image sequence. The default value is the current directory.
+ \row
+ \li --seq-outfile <file>
+ \li Output filename base for the image sequence. The default value is derived from the
+ presentation filename.
+ \row
+ \li --connect <port>
+ \li If this parameter is specified, the viewer is started in connection mode. The default
+ value is \c {36000}.
+ \row
+ \li --fullscreen
\li Starts the viewer in fullscreen mode.
\row
- \li -w, --no-main-window
- \li Disables the widget-based user interface, such as the menu bar.
- This mode simulates the operating mode typical on embedded devices:
- using a Qt platform plugin like \c eglfs, there will only be a single,
- fullscreen QWindow (or, with Qt Quick applications, QQuickWindow or
- QQuickView) present. This argument achieves the same even when running
- on a desktop operating system. Combined with \c{-f} (going fullscreen)
- this allows seeing the presentation in real full screen (no menu bar).
- \row
- \li -p, --no-profile
- \li Loads the presentation with some profiling options disabled. This
- provides minimal performance improvements.
- \row
- \li --port <port_number>
- \li Sets the port on which the viewer listens for remote connections.
- The remote connection mode is active either when launching with no
- presentation file specified, or when choosing \uicontrol{File > Remote Setup}.
+ \li --maximized
+ \li Starts the viewer in maximized mode.
+ \row
+ \li --windowgeometry <geometry>
+ \li Specifies the initial window geometry using the X11-syntax. For example:
+ \c {1000x800+50+50}
+ \row
+ \li --mattecolor <color>
+ \li Specifies custom matte color using #RRGGBB syntax. For example, white matte:
+ \c {#ffffff}
+ \row
+ \li --showstats
+ \li Show render statistics on screen.
+ \row
+ \li --scalemode <center|fit|fill>
+ \li Specifies scaling mode. The default value is \c {center}.
+ \row
+ \li --stereomode <mono|topbottom|leftright>
+ \li Specifies stereo mode. The default value is \c {mono}.
+ \row
+ \li --stereoeyeseparation <separation>
+ \li Specifies stereo eye separation. The default value is \c {0.4}.
+ \row
+ \li --enableprogressivestereo
+ \li Enables progressive stereoscopic rendering.
+ \row
+ \li --convert-shader-cache <filename>
+ \li Convert base64 dump to shader cache file.
+ \row
+ \li -v, --variants <variants>
+ \li Gives list of variant groups and variants to be loaded from the presentation. For
+ example \c {VarGroupA:var1,VarGroupB:var4}.
\endtable
-
*/
diff --git a/doc/src/04-viewer/3-remote-deployment.qdoc b/doc/src/04-viewer/3-remote-deployment.qdoc
index d2379546..544658df 100644
--- a/doc/src/04-viewer/3-remote-deployment.qdoc
+++ b/doc/src/04-viewer/3-remote-deployment.qdoc
@@ -34,7 +34,7 @@
Qt 3D Studio supports remote deployment to Qt 3D Studio Viewer. This enables seeing design changes
live in the target device, for example an Android tablet.
-\note For supported devices and operating systems see the \l{Requirements} page.
+\note For supported devices and operating systems see the \l {Requirements} page.
\section1 Setting Up the Target Device
@@ -59,39 +59,39 @@ For embedded systems you will have to compile the application on the target devi
You can run the Viewer from the command line. The default mode is connection mode. To start the
Viewer, use the following command:
\badcode
-q3dsviewer
+Qt3DViewer
\endcode
When you run the Viewer in connection mode it will display connection details, IP address and port,
right away.
-For full usage, see the \l{Viewer: Command Line Usage}{Command line usage documentation}.
+For full usage, see the \l {Viewer: Command Line Usage}{Command line usage documentation}.
\section1 Connecting to the Target Device
To connect to the target device Viewer from Qt 3D Studio, follow the steps below.
\list 1
- \li From the file menu, select \uicontrol {File > Connect to Device}.
+ \li From the menu, select \uicontrol {Edit > Connect to Device}.
\li Enter the connection information displaying in the Viewer on the target device, then press
- \uicontrol{OK}.
+ \uicontrol {OK}.
\note Previous used IP and port is automatically inserted when you click
\uicontrol {Connect to Device}.
- \li You are now connected. The Viewer on the target device should display \e{Remote Connected}.
+ \li You are now connected. The Viewer on the target device should display \e {Remote Connected}.
\endlist
\section1 Preview Presentation
-To preview the presentation on the target device, press the \uicontrol{Remote Preview} button
+To preview the presentation on the target device, press the \uicontrol {Remote Preview} button
\inlineimage remote-preview-button.png
in the Studio toolbar.
-After making changes to your presentation, press the \uicontrol{Remote Preview} button to see the
+After making changes to your presentation, press the \uicontrol {Remote Preview} button to see the
changes on the target device.
\section1 Disconnecting from the Target Device
-You can disconnect from the target device by selecting \uicontrol{File > Connect to Device}
-from the Studio file menu.
+You can disconnect from the target device by selecting \uicontrol {Edit > Connect to Device}
+from the Studio menu.
*/
diff --git a/doc/src/07-file-formats/0-uia.qdoc b/doc/src/07-file-formats/0-uia.qdoc
index 47d90531..103971d7 100644
--- a/doc/src/07-file-formats/0-uia.qdoc
+++ b/doc/src/07-file-formats/0-uia.qdoc
@@ -298,7 +298,7 @@ following (as many as you like, in any order):
id-prefixed path to any element in a presentation.
\li
The \b{\c{attribute}} attribute must match the
- \l{Attribute Names}{scripting name} of an attribute on that element.
+ scripting name of an attribute on that element.
\li
The \b{\c{value}} attribute must provide a Lua expression to
evaluate, the result of which will be set as the value on the element.
diff --git a/doc/src/07-file-formats/5-custom-material-reference.qdoc b/doc/src/07-file-formats/5-custom-material-reference.qdoc
index 4d3d93b7..8e46d7a6 100644
--- a/doc/src/07-file-formats/5-custom-material-reference.qdoc
+++ b/doc/src/07-file-formats/5-custom-material-reference.qdoc
@@ -48,8 +48,16 @@ index-of-refraction and fragment cutoff(masking).
It is also possible to write custom material without using the boilerplate code,
in which case the main function must be implemented in the shader.
-\note The Qt 3D Studio 2.0 runtime does not support multiple render passes for
-custom materials.
+For more information on the XML format see \l{Custom Materials and Effects} and
+\l{Effect Reference}.
+
+\note Some characters used in shader code such as '<' break the XML parsing.
+It is advisable to surround any shader code with <![CDATA[]]> to enable use of such characters.
+Example usage:
+
+\badcode
+<FragmentShader><![CDATA[ void main() { } ]]></FragmentShader>
+\endcode
\section1 Required Functions
@@ -489,6 +497,20 @@ void main()
\note Previous versions stated that the closing parenthesis should not be added to the main function.
This is no longer the case and the main function should add the closing parenthesis.
+\section2 Accessing Textures with Image Transformations
+
+When the custom material is generated, uniforms for the image transformation are also generated,
+as well as accessor functions to get the transformed coordinate and texture sample.
+
+For texture named \"basecolor\" the generated uniforms and functions are
+\badcode
+uniform vec3 basecolorTransformU;
+uniform vec3 basecolorTransformV;
+
+vec3 texcoordTransformed_basecolor(vec3 texcoord);
+vec4 sampleTransformed_basecolor(vec3 texcoord);
+\endcode
+
\section2 Simple Custom Material Example
\badcode
@@ -504,7 +526,7 @@ This is no longer the case and the main function should add the closing parenthe
<Shared></Shared>
<VertexShader>
</VertexShader>
- <FragmentShader>
+ <FragmentShader><![CDATA[
#define UIC_ENABLE_UV0 1
#define UIC_ENABLE_WORLD_POSITION 1
#define UIC_ENABLE_TEXTAN 0
@@ -525,7 +547,7 @@ out vec4 fragColor;
c.rgb *= vec3(red_weight, green_weight, blue_weight);
fragColor = c;
}
- </FragmentShader>
+ ]]></FragmentShader>
</Shader>
</Shaders>
<Passes >
diff --git a/doc/src/07-file-formats/6-effect-reference.qdoc b/doc/src/07-file-formats/6-effect-reference.qdoc
index a448464f..faaa08d2 100644
--- a/doc/src/07-file-formats/6-effect-reference.qdoc
+++ b/doc/src/07-file-formats/6-effect-reference.qdoc
@@ -356,6 +356,7 @@ The element attributes are:
\li name
\li \list
\li \c Stencil
+ \li \c CullFace
\endlist
\li Name of the render state
\row
@@ -435,4 +436,24 @@ The boolean operator values are:
\li \c greater-than-or-equal
\li \c always
\endlist
+
+\section2 <Culling>
+
+This element can be used to select which faces are culled by CullFace.
+
+The element attributes are:
+\table
+\header
+ \li attribute
+ \li values
+ \li description
+\row
+ \li mode
+ \li \list
+ \li \c Back - Back faces.
+ \li \c Front - Front faces.
+ \li \c All - All faces.
+ \endlist
+ \li Specifies CullFace mode.
+\endtable
*/
diff --git a/doc/src/07-file-formats/custom-materials-effects.qdoc b/doc/src/07-file-formats/custom-materials-effects.qdoc
index 7a1521cc..a083546d 100644
--- a/doc/src/07-file-formats/custom-materials-effects.qdoc
+++ b/doc/src/07-file-formats/custom-materials-effects.qdoc
@@ -170,6 +170,13 @@ A \c{property} element can have the following attributes:
\li Text
\li -
\li Creates UI dropdown list.
+\row
+ \li category
+ \li Text
+ \li
+ \li Use to group material properties into separate categories. \note Required field for
+ materials. If this is not added, the property will not be displayed in the Inspector palette.
+ Adding category with empty string will not suffice.
\endtable
The only required attribute in the \c{<property>} element is \c{name}.
@@ -304,4 +311,113 @@ identifier-like name.
<Shader name="tonemap">
\endcode
+\section2 \c{<Passes>}
+The \c{<Passes>} element can contain \c{<Pass>} elements.
+
+\section2 \c{<Pass>}
+The \c{<Pass>} element contains different properties that are applied to the pass. More details
+are provided in the \l{Effect Reference}.
+
+\section2 <Depth>
+Custom materials have an additional Depth pass element not provided to effects. It determines
+the depth function and masking used during this pass of the custom shader.
+
+The element attributes are:
+\table
+\header
+ \li attribute
+ \li values
+ \li description
+\row
+ \li func
+ \li \list
+ \li \c never
+ \li \c less
+ \li \c less-than-or-equal
+ \li \c equal
+ \li \c not-equal
+ \li \c greater
+ \li \c greater-than-or-equal
+ \li \c always
+ \endlist
+ \li Specifies the depth function used.
+\row
+ \li mask
+ \li bool
+ \li Specifies if depth is written or not. With "true" depth is written, with "false" it's not.
+\endtable
+
+\section1 Things to Note
+
+\section2 Materials
+When creating a custom material with several properties, it is a good practice to use categories
+to separate them. If there is a need to be able to change the material for the mesh, at least one
+property needs to be added to \b Materials category. This will pull in \b {Material Type} and
+\b Shader properties into the Inspector palette.
+
+Consider a custom material with the following metadata:
+\badcode
+ <MetaData >
+ <Property category="ExampleMaterial" formalName="Environment Map" name="uEnvironmentTexture" description="Environment texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png"/>
+ <Property category="ExampleMaterial" formalName="Enable Environment" name="uEnvironmentMappingEnabled" description="Enable environment mapping" type="Boolean" default="True"/>
+ <Property category="ExampleMaterial" formalName="Baked Shadow Map" name="uBakedShadowTexture" description="Baked shadow texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png"/>
+ <Property category="ExampleMaterial" formalName="Shadow Mapping" name="uShadowMappingEnabled" description="Enable shadow mapping" type="Boolean" default="False"/>
+ <Property category="ExampleMaterial" formalName="Roughness" name="roughness" type="Float" min="0.0" max="1.0" default="0.3" description="Roughness of the material.\n0 = fully specular\n1 = fully diffuse"/>
+ <Property category="ExampleMaterial" formalName="Base color" name="base_color" type="Color" default="0.7 0.7 0.7" description="Color of the material"/>
+ </MetaData>
+\endcode
+and the same material with sensible categories defined, including \b {Material}:
+\badcode
+ <MetaData >
+ <Property category="Environment" formalName="Environment Map" name="uEnvironmentTexture" description="Environment texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png"/>
+ <Property category="Environment" formalName="Enable Environment" name="uEnvironmentMappingEnabled" description="Enable environment mapping" type="Boolean" default="True"/>
+ <Property category="Shadow" formalName="Baked Shadow Map" name="uBakedShadowTexture" description="Baked shadow texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png"/>
+ <Property category="Shadow" formalName="Shadow Mapping" name="uShadowMappingEnabled" description="Enable shadow mapping" type="Boolean" default="False"/>
+ <Property category="Material" formalName="Roughness" name="roughness" type="Float" min="0.0" max="1.0" default="0.3" description="Roughness of the material.\n0 = fully specular\n1 = fully diffuse"/>
+ <Property category="Material" formalName="Base color" name="base_color" type="Color" default="0.7 0.7 0.7" description="Color of the material"/>
+ </MetaData>
+\endcode
+
+The first option results in
+\image materials-category-dummy.png
+and the seconds one results in
+\image materials-category-several.png
+
+\section2 Controlling Custom Properties
+When some of the properties in custom materials or effects need to be adjusted during run-time,
+the \c setAttribute API is required. The usage may differ slightly from normal usage, depending on
+the property being controlled, as all of the properties in custom materials and effects are handled
+as dynamic properties.
+
+\note Since 2.8 the custom property textures use images and are controlled the same way as standard
+material textures.
+
+\omit
+For example, a texture is not handled as an image like it is when controlling it in standard
+material.
+\endomit
+\section3 Controlling a texture in standard material
+\badcode
+<presentation id>.setAttribute("<element path to texture>", "sourcepath", "<path to image>");
+\endcode
+For example:
+\badcode
+myPresentation.setAttribute("Scene.Layer.Sphere.Default_animatable.diffusemap", "sourcepath", "../maps/myTexture.png");
+\endcode
+\section3 Controlling a texture in a custom material
+\badcode
+<presentation id>.setAttribute("<element path to material>", "sourcepath", "<path to image>");
+\endcode
+With a material that has a metadata entry as follows:
+\badcode
+<MetaData >
+ ...
+ <Property name="diffuseTexture" type="Texture" category="Material" formalName="Diffuse texture"/>
+ ...
+</MetaData>
+\endcode
+This is the way to control it:
+\badcode
+myPresentation.setAttribute("Scene.Layer.Sphere.MyMaterial.diffuseTexture", "sourcepath", "../maps/myTexture.png");
+\endcode
*/
diff --git a/doc/src/10-best-practices/100-elementvisibilities.qdoc b/doc/src/10-best-practices/100-elementvisibilities.qdoc
new file mode 100644
index 00000000..f7c3a0ea
--- /dev/null
+++ b/doc/src/10-best-practices/100-elementvisibilities.qdoc
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\title Manipulating Element Visibility
+\page bestpractices-elementvisibilities.html
+\ingroup qt3dstudio-best-practices
+
+Element visibilities are controlled with element attribute "eyeball". This attribute can be set
+per-slide for each element. See \l{Studio: Timeline Palette}.
+
+Eyeball attribute can also be controlled in Runtime with data inputs or setAttribute API.
+
+Eyeball attribute controls not only element visibility, but also entire element active state.
+Element active state determines if element participates in animations, or if it in general exists
+in the scene at any given moment. Thus, changing element eyeball state is more than just hiding or
+revealing an existing element.
+
+\section1 Using Data Inputs to Control Active State
+
+A boolean type data input can be bound to element "eyeball" property and used to control element
+active state. See \l{Using Data Inputs} for details.
+
+\section2 Master Slide Elements versus Per-slide Elements
+
+When a data input is used to change element eyeball property, runtime behavior depends on whether
+the element exists on master slide, or on a single slide.
+
+\b{For elements on master slide, data input control is persistent.} This means that after element
+visibility has been changed using a data input, element is no longer affected by visibility states
+set in slides, and will not change visibility at slide transitions. This helps avoid - often
+tricky! - bugs where element visibility is controlled by several sources.
+
+\b{For elements existing on a single slide, data input visibility control is not persistent.}
+Element visibility can be set using a data input, but when the slide containing the element is
+re-entered, element visibility will have the state that was assigned to it in Editor.
+
+\section2 SetAttribute API Visibility Control versus Data Inputs
+
+Q3DSElement::setAttribute API can also be used to directly set eyeball attribute. Visibility
+persistence does not apply to any visibility changes done using setAttribute API.
+
+\note Data input is the preferred method for controlling element attributes.
+
+\note Mixing setAttribute and data input control can lead to unexpected behavior. Due to
+performance optimizations, Q3DSDataInput::setValue API by default only generates a change event
+when the new Data Input value differs from the old one. Thus, a data input might discard value even
+though the underlying target element visibility has actually been changed by another controller.
+See \l{Best practices for dynamic visibility control} for example.
+
+\section1 Best Practices for Dynamic Visibility Control
+
+If an element on master slide must be controlled dynamically, consider the following approach:
+
+\list
+\li Use a single visibility controller instead of relying on a combination of slide transitions,
+data inputs and setAttribute calls. For example, the following sequence where element "Element"
+visibility is bound to data input \c visCtrlDI will fail and leave "Element" in non-visible state:
+\code
+visCtrlDI.setValue(true)
+Element.setAttribute("eyeball", false)
+visCtrlDI.setValue(true) // this value change will be discarded, because force=true is not set
+\endcode
+
+\li For data input -controlled elements, set visibility explicitly with data input at
+presentationReady to make sure that visibility is at a known state. This also makes sure that
+master slide element visibility is persistent and not affected by slide transitions. Use parameter
+force = true.
+
+\li Use onSlideChanged signal and data input to explicitly set element visibility at slide
+transition, especially for master slide elements. Do not rely on visibility state set in slide.
+
+\li To make sure that visibility change event is actually created regardless of data input current
+value, use force=true parameter in Q3DSdata input::setValue interface. Do not call setValue
+needlessly when force parameter is set to true, as this can have performance implications.
+\endlist
+
+\section1 Debugging Element Visibility Issues
+
+\b{Element has wrong visibility after slide change, element is on master slide, and \
+visibility (eyeball) was changed with data input before this?}
+
+Slide-based visibility states are no longer used because data input control overrides them. Make
+sure that you will do all visibility changes using data input.
+
+\b{Element visibility was changed using Q3DSElement::setAttribute, and data input \
+visibility setting now has no effect?}
+
+Do not mix setAttribute, slide-based and data input visibility control. Use force = true parameter
+for Q3DSDataInput::setValue API to make sure that data input does not discard incoming value.
+
+\b{Element is not on master slide, and data input visibility control has no effect after \
+slide change?}
+
+Element visibility might have been changed by slide transition. Data input is not creating change
+event, if the new value is not different from previously set value. Use force = true parameter to
+bypass this optimization. Also remember that for non-master slide elements, data input control is
+not persistent. Entering this slide later on will again set visibility to slide-based initial
+value.
+*/
diff --git a/doc/src/10-best-practices/30-using-sub-presentations.qdoc b/doc/src/10-best-practices/30-using-sub-presentations.qdoc
index 21aff488..c8124d6b 100644
--- a/doc/src/10-best-practices/30-using-sub-presentations.qdoc
+++ b/doc/src/10-best-practices/30-using-sub-presentations.qdoc
@@ -129,7 +129,9 @@ To add a sub-presentation to a layer, do one of the following:
One benefit of displaying a sub-presentation as a texture is that you can use Studio
presentations and QML files to map the materials of objects in your presentation. You can apply
sub-presentations to any map or image property of a material, i.e. diffuse maps, specular maps and
-displacement maps. This way you can for example create animated textures.
+displacement maps. This way you can for example create animated textures. For performance reasons
+it is best to disable mipmapping for subpresentation images by setting the minification filter to
+\c Nearest or \c Linear.
To add a sub-presentation as a texture of a 3D object, do one of the following:
\list
diff --git a/doc/src/10-best-practices/80-effects.qdoc b/doc/src/10-best-practices/80-effects.qdoc
index 17316b35..74ad47e1 100644
--- a/doc/src/10-best-practices/80-effects.qdoc
+++ b/doc/src/10-best-practices/80-effects.qdoc
@@ -149,6 +149,59 @@ lower in the scene graph will be applied before effects that are above them.
\image tiltshift-icon.png
\b{\l{Tilt shift}}
\enddiv
+\row
+ \li
+ \div {align="center"}
+ \image brush-strokes-icon.png
+ \b {\l{Brush Strokes}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image sepia-icon.png
+ \b {\l{Sepia}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image stylize-scatter-icon.png
+ \b {\l{Stylize Scatter}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image emboss-icon.png
+ \b {\l{Emboss}}
+ \enddiv
+\row
+ \li
+ \div {align="center"}
+ \image fullscreen-texture-overlay-icon.png
+ \b {\l{Fullscreen Texture Overlay}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image corona-icon.png
+ \b {\l{Corona}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image vignette-icon.png
+ \b {\l{Vignette}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image frame-flipper-icon.png
+ \b {\l{Frame Flipper}}
+ \enddiv
+\row
+ \li
+ \div {align="center"}
+ \image screen-space-ao-icon.png
+ \b {\l{Screen Space AO}}
+ \enddiv
+ \li
+ \div {align="center"}
+ \image smaa1x-icon.png
+ \b {\l{SMAA1X}}
+ \enddiv
\endtable
\enddiv
diff --git a/doc/src/10-best-practices/95-data-input.qdoc b/doc/src/10-best-practices/95-data-input.qdoc
index a71fdb30..1177e7ad 100644
--- a/doc/src/10-best-practices/95-data-input.qdoc
+++ b/doc/src/10-best-practices/95-data-input.qdoc
@@ -65,6 +65,9 @@ Q3DSPresentation in the C++ API.
\row
\li Vector3
\li 3 float values
+ \row
+ \li Vector4
+ \li 4 float values
\endtable
\section1 Manage Data Inputs
@@ -151,8 +154,6 @@ To edit a metadata key, follow the steps below:
\list 1
\li
- Double-click the desired metadata key in the list.
- \li
Edit desired values.
\li
Press \uicontrol{OK}.
@@ -176,7 +177,6 @@ To add a data input to control the timeline animation, follow the instructions b
\li Click the \inlineimage datainput-to-timeline-icon-inactive.png
icon located in the bottom of the scene graph.
\li Select the desired data input from the list by clicking it.
- \li Press \uicontrol{OK}.
\endlist
\image timeline-datainput.png
@@ -198,7 +198,6 @@ To remove the data input, repeat step 2 above. Then select \uicontrol{[No contro
\li In the slide palette, click the \inlineimage datainput-to-timeline-icon-inactive.png
icon located below the slides.
\li Select the desired data input from the list by clicking it.
- \li Press \uicontrol{OK}.
\endlist
\image slide-palette-data-input-active.png
@@ -241,6 +240,9 @@ The following data input types can be used to control object properties:
\row
\li Vector3
\li To control properties with three numeric values such as 3D coordinates or RGB colors
+ \row
+ \li Vector4
+ \li To control properties with four numeric values such as RGBA colors
\endtable
\list 1
@@ -250,7 +252,6 @@ The following data input types can be used to control object properties:
\li In the inspector palette, click the \inlineimage datainput-to-timeline-icon-inactive.png
icon next to the object property you wish to control.
\li Select the desired data input from the list by clicking it.
- \li Press \uicontrol{OK}.
\endlist
\image datainput-property-active-icon.png
diff --git a/doc/src/10-best-practices/brush-strokes.qdoc b/doc/src/10-best-practices/brush-strokes.qdoc
new file mode 100644
index 00000000..dfb4cc56
--- /dev/null
+++ b/doc/src/10-best-practices/brush-strokes.qdoc
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Brush Strokes
+\page brush-strokes.html
+\ingroup qt3dstudio-best-practices
+
+The brush strokes effect will apply a painted look for your layer.
+\image effects-brush-strokes.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Noise
+ \li
+ Texture to be used as the brush.
+ \row
+ \li
+ Brush Angle
+ \li
+ Rotation of the brush texture.
+ \row
+ \li
+ Stroke Length
+ \li
+ Length of the brush texture.
+ \row
+ \li
+ Stroke Size
+ \li
+ Overall scale of the brush.
+\endtable
+
+*/
diff --git a/doc/src/10-best-practices/corona.qdoc b/doc/src/10-best-practices/corona.qdoc
new file mode 100644
index 00000000..19a554d1
--- /dev/null
+++ b/doc/src/10-best-practices/corona.qdoc
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Corona
+\page corona.html
+\ingroup qt3dstudio-best-practices
+
+The corona effect creates colored rings around an object.
+
+\image effects-corona.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Horizontal Blur
+ \li
+ Horizontal amount of corona glow.
+ \row
+ \li
+ Vertical Blur
+ \li
+ Vertical amount of corona glow.
+ \row
+ \li
+ Fade Amount
+ \li
+ How quickly the effect fades away. 0 means there is no glow, and 1 means the glow is permanent.
+ \row
+ \li
+ Glow Clor
+ \li
+ The color of the glow.
+ \row
+ \li
+ Noise
+ \li
+ Texture to be used for the glow noise.
+ \row
+ \li
+ Noise Density
+ \li
+ Scale of the noise texture.
+ \row
+ \li
+ Noise Brightness
+ \li
+ Brightness of the noise texture.
+ \row
+ \li
+ Noise Amount
+ \li
+ Scale of the noise texture.
+ \row
+ \li
+ Crawl Length
+ \li
+ Length of the trail for the glow animation.
+ \row
+ \li
+ Crawl Angle
+ \li
+ Angle of the glow trail.
+\endtable
+
+*/
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/src/10-best-practices/emboss-effect.qdoc b/doc/src/10-best-practices/emboss-effect.qdoc
new file mode 100644
index 00000000..b2a7209c
--- /dev/null
+++ b/doc/src/10-best-practices/emboss-effect.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Emboss
+\page emboss-effect.html
+\ingroup qt3dstudio-best-practices
+
+The emboss effect creates an 3D embossed look for your layer.
+
+\image effects-emboss.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Amount
+ \li
+ Controls the depth of the emboss.
+\endtable
+
+*/
diff --git a/doc/Src/10-best-practices/exporting-from-3dsmax.qdoc b/doc/src/10-best-practices/exporting-from-3dsmax.qdoc
index 79754adc..79754adc 100644
--- a/doc/Src/10-best-practices/exporting-from-3dsmax.qdoc
+++ b/doc/src/10-best-practices/exporting-from-3dsmax.qdoc
diff --git a/doc/Src/10-best-practices/exporting-from-blender.qdoc b/doc/src/10-best-practices/exporting-from-blender.qdoc
index 528dcbad..528dcbad 100644
--- a/doc/Src/10-best-practices/exporting-from-blender.qdoc
+++ b/doc/src/10-best-practices/exporting-from-blender.qdoc
diff --git a/doc/Src/10-best-practices/exporting-from-maya.qdoc b/doc/src/10-best-practices/exporting-from-maya.qdoc
index 10d1525b..10d1525b 100644
--- a/doc/Src/10-best-practices/exporting-from-maya.qdoc
+++ b/doc/src/10-best-practices/exporting-from-maya.qdoc
diff --git a/doc/Src/10-best-practices/exporting-from-modo.qdoc b/doc/src/10-best-practices/exporting-from-modo.qdoc
index b8c34f77..b8c34f77 100644
--- a/doc/Src/10-best-practices/exporting-from-modo.qdoc
+++ b/doc/src/10-best-practices/exporting-from-modo.qdoc
diff --git a/doc/src/10-best-practices/frame-flipper.qdoc b/doc/src/10-best-practices/frame-flipper.qdoc
new file mode 100644
index 00000000..d56a54c8
--- /dev/null
+++ b/doc/src/10-best-practices/frame-flipper.qdoc
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Frame Flipper
+\page frame-flipper-effect.html
+\ingroup qt3dstudio-best-practices
+
+The frame flipper effect gives you the ability to flip the layer horizontally and vertically.
+
+In the image below, the left picture is vertically flipped and the right picture is
+horizontally flipped.
+
+\image effects-frame-flipper.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Flip Horizontally
+ \li
+ Flips the image upside down.
+ \row
+ \li
+ Flip Vertically
+ \li
+ Flips the image sideways.
+\endtable
+
+
+*/
diff --git a/doc/src/10-best-practices/fullscreen-texture-overlay.qdoc b/doc/src/10-best-practices/fullscreen-texture-overlay.qdoc
new file mode 100644
index 00000000..f7ae9b7d
--- /dev/null
+++ b/doc/src/10-best-practices/fullscreen-texture-overlay.qdoc
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2029 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Fullscreen Texture Overlay
+\page fullscreen-texture-overlay.html
+\ingroup qt3dstudio-best-practices
+
+With fullscreen texture overlay effect you can take any image and use it as
+texture overlay.
+
+\image effects-fullscreen-texture-overlay.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Overlay Texture
+ \li
+ Texture to use on the overlay.
+ \row
+ \li
+ Repeat
+ \li
+ How many times the texture is repeated vertically and horizontally.
+\endtable
+
+*/
diff --git a/doc/src/10-best-practices/practices-index.qdoc b/doc/src/10-best-practices/practices-index.qdoc
index 22c17646..f34c1067 100644
--- a/doc/src/10-best-practices/practices-index.qdoc
+++ b/doc/src/10-best-practices/practices-index.qdoc
@@ -43,6 +43,8 @@
\li \l {Blend Mode}
\li \l {3D Assets}
\li \l {Applying Layer Effects}
+\li \l {Manipulating Element Visibility}
+
\endlist
//! [toc]
diff --git a/doc/src/10-best-practices/screen-space-ao.qdoc b/doc/src/10-best-practices/screen-space-ao.qdoc
new file mode 100644
index 00000000..fbfee194
--- /dev/null
+++ b/doc/src/10-best-practices/screen-space-ao.qdoc
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Screen Space AO
+\page screen-space-ao-effect.html
+\ingroup qt3dstudio-best-practices
+
+Screen space ambient occlusion efficiently approximates the ambient occlusion of you layer
+in real time. It is independent from the layers complexity and works with dynamic scenes.
+
+\image effects-screen-space-ao.png
+
+\table
+ \header
+ \li
+ Pros
+ \li
+ Cons
+ \row
+ \li
+ \list
+ \li
+ Independent from scene complexity.
+ \li
+ No data pre-processing needed.
+ \li
+ Works with dynamic scenes.
+ \li
+ Works in the same consistent way for every pixel on the screen.
+ \li
+ No CPU usage.
+ \endlist
+ \li
+ \list
+ \li
+ Rather local and in many cases view-dependent, as it is dependent on
+ adjacent texel depths which may be generated by any geometry whatsoever.
+ \li
+ Hard to correctly smooth/blur out the noise without bleeding onto objects.
+ \endlist
+\endtable
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Filter Size
+ \li
+ Controls the shadows size.
+ \row
+ \li
+ Distance Scale
+ \li
+ How strong the shadows are.
+ \row
+ \li
+ Distance Bias
+ \li
+ Controls distance offset.
+\endtable
+
+
+\section1 Usage
+
+The layer which the effect is applied to requires depth prepass for the effect to work.
+Make sure in your layer's advanced options "disable depth prepass" is unchecked.
+
+*/
diff --git a/doc/src/10-best-practices/sepia.qdoc b/doc/src/10-best-practices/sepia.qdoc
new file mode 100644
index 00000000..c8633f31
--- /dev/null
+++ b/doc/src/10-best-practices/sepia.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Sepia
+\page sepia.html
+\ingroup qt3dstudio-best-practices
+
+Sepia effect will give your layer a warm color tint.
+
+\image effects-sepia.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Amount
+ \li
+ Controls how strong the tint is.
+\endtable
+
+*/
diff --git a/doc/src/10-best-practices/smaa1x.qdoc b/doc/src/10-best-practices/smaa1x.qdoc
new file mode 100644
index 00000000..94fb5958
--- /dev/null
+++ b/doc/src/10-best-practices/smaa1x.qdoc
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title SMAA1X
+\page smaa.html
+\ingroup qt3dstudio-best-practices
+
+Subpixel Morphological Antialiasing is a very efficient GPU-based MLAA implementation,
+capable of handling subpixel features seamlessly, and featuring an improved
+and advanced pattern detection & handling mechanism.
+
+\image Effects-smaa1x.png
+
+
+*/
diff --git a/doc/src/10-best-practices/stylize-scatter.qdoc b/doc/src/10-best-practices/stylize-scatter.qdoc
new file mode 100644
index 00000000..fb212c66
--- /dev/null
+++ b/doc/src/10-best-practices/stylize-scatter.qdoc
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Stylize Scatter
+\page stylize-scatter-effect.html
+\ingroup qt3dstudio-best-practices
+
+The scatter effect scatters the layers pixels around their original
+positions, giving it a smeared look.
+
+\image effects-stylize-scatter.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Scatter Amount
+ \li
+ Controls the scatter amount and displacement area size.
+ \row
+ \li
+ Grain
+ \li
+ Controls the direction where the pixels are displaced.
+ \row
+ \li
+ Randomize Every Frame
+ \li
+ If set to true, the displacement is calculated again for every frame.
+\endtable
+
+\section1 Usage
+
+
+
+*/
diff --git a/doc/src/10-best-practices/vignette.qdoc b/doc/src/10-best-practices/vignette.qdoc
new file mode 100644
index 00000000..1b3aaf4b
--- /dev/null
+++ b/doc/src/10-best-practices/vignette.qdoc
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title Vignette
+\page vignette-effect.html
+\ingroup qt3dstudio-best-practices
+
+The vignette effect darkens the corners of your layer.
+
+\image effects-vignette.png
+
+\section1 Properties
+
+\table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li
+ Strength
+ \li
+ Changes the opacity of the vignette.
+ \row
+ \li
+ Radius
+ \li
+ Adjust the size of the vignette
+\endtable
+
+*/
diff --git a/doc/src/11-quick-start-guides/quick-start-guide.qdoc b/doc/src/11-quick-start-guides/quick-start-guide.qdoc
index 5a6a6dbf..2c35bb78 100644
--- a/doc/src/11-quick-start-guides/quick-start-guide.qdoc
+++ b/doc/src/11-quick-start-guides/quick-start-guide.qdoc
@@ -116,11 +116,20 @@ textures and maps.
\image objectTimeline.png "Object in timeline"
+\section2 Creating groups
+By selecting multiple objects and clicking \e{Group Objects} from \e{Edit} list or using a
+keyboard shortcut \e{Ctrl+G} you can create a group that contains the objects you had selected.
+
+\image editListGroupObjects.png "Group Objects in Edit list"
+
\section2 Related Content
\table
\row
\li \inlineimage moreinfoicon.png
+ \li \l{studio-inspector-palette.html#group-properties} {Studio: Inspector Palette: Group}
+ \row
+ \li \inlineimage moreinfoicon.png
\li \l{studio-inspector-palette.html#material-properties} {Studio: Inspector Palette: Material}
\endtable
diff --git a/doc/src/comparison.qdoc b/doc/src/comparison.qdoc
index 19f12e14..6e18e3ba 100644
--- a/doc/src/comparison.qdoc
+++ b/doc/src/comparison.qdoc
@@ -30,9 +30,6 @@
\title Comparison of Qt 3D and Qt 3D Studio
\page comparison-qt3d-qt3dstudio.html
-In short, Qt 3D Studio is built on top of Qt 3D. The flexible architecture of Qt 3D makes it
-suitable to build 3D runtimes, or engines, such as Qt 3D Studio.
-
\section1 Qt 3D
Qt 3D is programmer-oriented engine building toolkit and great for both simple and complex scenes.
@@ -72,7 +69,7 @@ Below, we list some common use cases and how they apply to the two:
\li
Suitable.
\li
- Not possible.
+ Creating meshes and materials dynamically is supported.
\row
\li
Using existing materials and effects.
diff --git a/doc/src/glossary.qdoc b/doc/src/glossary.qdoc
index 950b64be..5e63078b 100644
--- a/doc/src/glossary.qdoc
+++ b/doc/src/glossary.qdoc
@@ -40,86 +40,88 @@ This page provides short explanations of terms used in Qt 3D Studio.
Meaning
\row
\li
- \l{Studio: Action Palette}{Action}
+ \target actions
+ \l {Studio: Action Palette#Creating Actions}{Action}
\li
Actions provide a way to create interactivity in a \l presentation without scripting.
\row
\li
- \l{Studio: Action Palette}{Action palette}
+ \l {Studio: Action Palette}{Action palette}
\li
- The action palette is used to manage \l {action}{actions} for the selected element.
+ The action palette is used to manage \l actions for the selected element.
\row
\li
\target {animation portion}
- \l{Studio: Timeline Palette#Animation portion}{Animation Portion}
+ \l {Studio: Timeline Palette#Animation portion}{Animation Portion}
\li
- To the right of the \l{scene graph} in the \l{timeline palette} is the actual \l timeline.
- The \l{time bar}{time bars} for each element control element lifespan.
+ To the right of the \l {scene graph} in the \l {timeline palette} is the actual timeline.
+ The \l {time bar}{time bars} for each element control element lifespan.
The \l keyframe markers control the timing of the animation. The \l playhead allows the
preview of animation effects.
\row
\li
\target application
- \l{About Qt 3D Studio#Concepts}{Application}
+ \l {About Qt 3D Studio#Application}{Application}
\li
Your application is the entry point of your \l project. It is represented by a single
- \l{uia}{.uia file} at the root of your project folder. This file references the
- \l presentation and \l{sub-presentation}{sub-presentations} in your project.
+ \l {uia}{.uia file} at the root of your project folder. This file references the
+ \l presentation and \l {sub-presentation}{sub-presentations} in your project.
The application is what is displayed by the \l Viewer.
\row
\li
\target asset
- Asset
+ \l {Studio: Project Palette#Using Assets}{Asset}
\li
- Assets are elements which you can use in your \l presentation. Assets can be images, 3D
- models, \l{effect}{effects}, fonts, \l{material}{materials}, \l{shader}{shaders},
- \l {behavior}{scripts} and \l{sub-presentation}{sub-presentations}.
+ Assets are elements which you can use in your \l presentation. Assets can be
+ \l {2D Assets}{images}, \l {3D Assets}{3D models}, \l {effect}{effects},
+ \l {Studio: Project Palette#Fonts}{fonts}, \l {material}{materials}, \l {shader}{shaders},
+ \l {behavior}{scripts} and \l {sub-presentation}{sub-presentations}.
\row
\li
- Asset library
+ \l {Studio: Project Palette#Importing Assets from the Asset Library}{Asset library}
\li
- Included in \l studio is a set of \l{asset}{assets} ranging from images to 3d models.
+ Included in \l studio is a set of \l {asset}{assets} ranging from images to 3d models.
\row
\li
- \l{Studio: Basic Objects Palette}{Basic objects palette}
+ \l {Studio: Basic Objects Palette}{Basic objects palette}
\li
The Basic objects palette provides a mechanism for creating objects unique to a
\l presentation, not represented by a file on disk in your \l {project palette}.
\row
\li
\target behavior
- \l{Using Behavior Scripts}{Behavior}
+ \l {Using Behavior Scripts}{Behavior}
\li
Behavior scripts can be applied to objects to give the specific object a certain behavior.
\row
\li
- \l{Studio: Basic Objects Palette#Component}{Component}
+ \l {Studio: Basic Objects Palette#Component}{Component}
\li
Components are somewhat like mini-scenes. Although they are 3D geometry (not a 2D
composition of rendered layers), they have their own \l {slide}{slides} and
- \l {timeline}{timelines}.
+ \l {timeline palette}{timelines}.
\row
\li
- \l{Using Data Inputs}{Data input}
+ \l {Using Data Inputs}{Data input}
\li
- This makes it possible to control \l timeline animations, object properties and
- \l{slide}{slides} with data.
+ This makes it possible to control \l {Studio: Timeline Palette#Data Input}{timeline}
+ animations, object properties and \l {slide}{slides} with data.
\row
\li
- \l{Studio: Toolbar#Edit Cameras}{Edit cameras}
+ \l {Studio: Toolbar#Edit Cameras}{Edit cameras}
\li
Sometimes you want to move around the 3D space of your scene in the editor without
adjusting the final rendered view. \l Studio calls this concept edit cameras.
\row
\li
\target effect
- \l{Applying Layer Effects}{Effect}
+ \l {Applying Layer Effects}{Effect}
\li
- Each \l layer in a \l presentation may have one or more post-processing effects
- applied to the visual result
+ Each \l layer in a \l presentation may have one or more
+ \l {Applying Layer Effects}{post-processing effects} applied to the visual result.
\row
\li
- \l{Studio: Basic Objects Palette#Group}{Group}
+ \l {Studio: Basic Objects Palette#Group}{Group}
\li
A group is an empty transform element. Attaching models to the group
(placing them as children of the group in the \l {timeline palette}) allows you to
@@ -132,48 +134,48 @@ This page provides short explanations of terms used in Qt 3D Studio.
\e .import files.
\row
\li
- \l{Studio: Inspector Palette}{Inspector palette}
+ \l {Studio: Inspector Palette}{Inspector palette}
\li
The inspector palette is used to control values and animations of element properties.
\row
\li
- \l{Animations#Interpolation}{Interpolation}
+ \l {Animations#Animation Types}{Interpolation}
\li
Interpolation defines the easing of \l keyframe animations.
\row
\li
\target keyframe
- \l{Animations}{Keyframe}
+ \l {Animations}{Keyframe}
\li
A keyframe is a a time marker that stores the value of a property.
A keyframe can for example define the X position for an element. To create an animation,
- add another keyframe for the X position of the same element but in another position on the
- \l timeline. \l Studio will determine the correct X position for all frames between the
- two keyframes.
+ add another \l {Animations#Insert Keyframes}{keyframe} for the X position of the same element
+ but in another position on the timeline. \l Studio will determine the correct X position
+ for all frames between the two keyframes.
\row
\li
\target layer
- \l{About Qt 3D Studio#Concepts}{Layer}
+ \l {About Qt 3D Studio#Layer}{Layer}
\li
A single Studio \l presentation combines one or more layers. The visual result of each
layer comes from rendering a 3D scene, 2D scene (via an orthographic camera),
- or \l{sub-presentation}{sub-presentation}. Layers are then composited with items on upper
+ or \l {sub-presentation}{sub-presentation}. Layers are then composited with items on upper
layers drawing on top of the content on lower layers.
\row
\li
- \l{Studio: Slide Palette#The Master Slide}{Master slide}
+ \l {Studio: Slide Palette#The Master Slide}{Master slide}
\li
Each scene and \l component have one master slide.
Elements placed on this \l slide exist on all slides of that scene or \l component.
\row
\li
- \l{Materials and Shaders#Materials}{Material}
+ \l {Materials and Shaders#Materials}{Material}
\li
Materials define how object surfaces are rendered in \l studio and \l viewer. You can create
your own basic materials, save them in your \l project, and assign them to objects.
\row
\li
- \l{Studio: Scene View and Matte#Matte}{Matte}
+ \l {Studio: Scene View and Matte#Matte}{Matte}
\li
Surrounding the \l {scene view} is the matte. The matte may not be visible if your
\l presentation is larger than the available space.
@@ -185,128 +187,135 @@ This page provides short explanations of terms used in Qt 3D Studio.
\row
\li
\target playhead
- \l{Animations}{Playhead}
+ \l {Animations}{Playhead}
\li
- The playhead in the \l timeline is used to set the time for new keyframes, and for previewing
- animations.
+ The \l {Studio: Timeline Palette#Setting Playhead Time}{playhead} in the timeline is used to
+ set the time for new keyframes, and for previewing animations.
\row
\li
\target presentation
- \l{About Qt 3D Studio#Concepts}{Presentation}
+ \l {About Qt 3D Studio#Presentation}{Presentation}
\li
- Presentations are represented by \l{uip}{.uip files} in your project. A presentation
- has one or more \l{layer}{layers} composited to the screen, comprised of 2D assets
+ Presentations are represented by \l {uip}{.uip files} in your project. A presentation
+ has one or more \l {layer}{layers} composited to the screen, comprised of 2D assets
and 3D assets created in other applications.
Each application can only have one main presentation shown on screen (specified by the
\l {uia}{.uia file}) but this presentation may reference other
- \l{sub-presentation}{sub-presentations}, either on flat layers or as images and textures
+ \l {sub-presentation}{sub-presentations}, either on flat layers or as images and textures
drawn in a scene.
\row
\li
\target project
- \l{About Qt 3D Studio#Concepts}{Project}
+ \l {About Qt 3D Studio#Project}{Project}
\li
A project is simply a folder on your computer holding all the assets needed for your
\l application. When you start a new project, a default folder structure will be created.
\row
\li
\target {project palette}
- \l{Studio: Project Palette}{Project palette}
+ \l {Studio: Project Palette}{Project palette}
\li
The project palette displays the files and folders on disk for your \l project.
Only files usable by \l Studio are displayed in the palette.
\row
\li
- QML Stream
+ \target {qml stream}
+ \l {About Qt 3D Studio#QML}{QML Stream}
\li
- A QML stream is a \e .qml file used as a \l{sub-presentation}.
+ A QML stream is a \e .qml file used as a \l {sub-presentation}.
\row
\li
- \l{Studio: Scene Camera Palette}{Scene Camera palette}
+ \l {Studio: Scene Camera Palette}{Scene Camera palette}
\li
The scene camera palette allows you to zoom in to pixel perfect level with the scene camera.
\row
\li
\target {scene graph}
- \l{Studio: Timeline Palette#Scene Graph}{Scene graph}
+ \l {Studio: Timeline Palette#Scene Graph}{Scene graph}
\li
- The left half of the \l{timeline palette} shows the scene graph where all elements in your
+ The left half of the \l {timeline palette} shows the scene graph where all elements in your
\l presentation for the current \l slide.
\row
\li
\target {scene view}
- \l{Studio: Scene View and Matte#Scene View}{Scene view}
+ \l {Studio: Scene View and Matte#Scene View}{Scene view}
\li
The scene view is the center region of \l Studio, showing you the visual result of rendering
- and compositing the \l{layer}{layers} of your \l presentation, and also allowing you to
+ and compositing the \l {layer}{layers} of your \l presentation, and also allowing you to
select and transform elements graphically.
\row
\li
\target shader
- \l{Materials}{Shader}
+ \l {Materials and Shaders#Shaders}{Shader}
\li
Shaders are arbitrary GLSL Shaders, wrapped in a file format providing an artist-friendly
interface for adjusting properties in \l studio.
\row
\li
- \l{Studio:Slide Palette}{Slide}
+ \l {Studio: Basic Objects Palette#Signal}{Signal}
+ \li
+ A signal is a lightweight object specifically designed for triggering \l actions during
+ \l {Studio: Timeline Palette#Action Indicators}{timeline} animations.
+ \row
+ \li
+ \l {Studio:Slide Palette#Using Slides}{Slide}
\li
A Studio \l presentation combines 3D assets with animations and slides.
Slides can be thought of as states and provide visual variations within the \l presentation.
\row
\li
- \l{Studio:Slide Palette}{Slide palette}
+ \l {Studio:Slide Palette}{Slide palette}
\li
The slide palette shows all slides in a \l presentation or a \l component.
\row
\li
\target studio
- \l{About Qt 3D Studio#Concepts}{Studio}
+ \l {About Qt 3D Studio#Applications}{Studio}
\li
An authoring tool for creating interactive 3D presentations and applications.
\row
\li
\target {sub-presentation}
- \l{Using Sub-Presentations}{Sub-presentation}
+ \l {Using Sub-Presentations}{Sub-presentation}
\li
- Sub-Presentations is a feature which allows a \l studio \l presentation (\l{uia}{.uia file})
- or a QML file to be embedded in a \l studio \l presentation.
+ Sub-Presentation is a feature which allows a \l studio \l presentation (\l {uip}{.uip file})
+ or a \l {qml stream}{QML} file to be embedded in a \l studio \l presentation.
\row
\li
\target {time bar}
- \l{Studio: Timeline Palette#Adjusting Time Bars}{Time bar}
+ \l {Studio: Timeline Palette#Adjusting Time Bars}{Time bar}
\li
- Each element has a time bar in the \l timeline. The time bar control the lifespan
- during which the element is active.
+ Each element has a time bar in the \l {timeline palette}{timeline}. The time bar control the
+ lifespan during which the element is active.
\row
\li
\target {timeline palette}
- \l{Studio: Timeline Palette}{Timeline palette}
+ \l {Studio: Timeline Palette}{Timeline palette}
\li
The timeline palette provides direct access to all elements in your scene,
- and also gives you control over the animation and timing within a \l slide.
+ and also gives you control over the animation and timing within a \l slide.
The timeline palette is comprised of two connected sections: the \l {scene graph} and the
\l {animation portion}.
\row
\li
\target uia
- \l{About Qt 3D Studio#Concepts}{.uia file}
+ \l {About Qt 3D Studio#Application}{.uia file}
\li
- The \e .uia file is the application file, it is by default located in the root folder of
- your \l project.
+ The \e .uia file is the application file, and it is located in the root folder of
+ your \l project by default.
\row
\li
\target uip
- \l{About Qt 3D Studio#Concepts}{.uip file}
+ \l {About Qt 3D Studio#Presentation}{.uip file}
\li
- The \e .iup file is a presentation file. A \l project can have one or more presentation files
+ The \e .uip file is a presentation file. A \l project can have one or more presentation files
located in \e presentations folder of your \l project.
\row
\li
\target viewer
- \l{About Qt 3D Studio#Concepts}{Viewer}
+ \l {About Qt 3D Studio#Applications}{Viewer}
\li
A runtime player to test and deploy interfaces created in \l Studio.
\endtable
diff --git a/doc/src/images/ApplicationPreferences.png b/doc/src/images/ApplicationPreferences.png
index 4be41125..a191d256 100644
--- a/doc/src/images/ApplicationPreferences.png
+++ b/doc/src/images/ApplicationPreferences.png
Binary files differ
diff --git a/doc/src/images/Studio-Basic-Signal.png b/doc/src/images/Studio-Basic-Signal.png
new file mode 100644
index 00000000..ba241de9
--- /dev/null
+++ b/doc/src/images/Studio-Basic-Signal.png
Binary files differ
diff --git a/doc/src/images/Studio-SceneView.png b/doc/src/images/Studio-SceneView.png
index 6b7fd212..e9b4bbdf 100644
--- a/doc/src/images/Studio-SceneView.png
+++ b/doc/src/images/Studio-SceneView.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-SceneGraph.png b/doc/src/images/Studio-Timeline-SceneGraph.png
index b39908b3..0f8cb5b8 100644
--- a/doc/src/images/Studio-Timeline-SceneGraph.png
+++ b/doc/src/images/Studio-Timeline-SceneGraph.png
Binary files differ
diff --git a/doc/src/images/Studio-Timeline-SignalAction.png b/doc/src/images/Studio-Timeline-SignalAction.png
new file mode 100644
index 00000000..e8f24e3b
--- /dev/null
+++ b/doc/src/images/Studio-Timeline-SignalAction.png
Binary files differ
diff --git a/doc/src/images/addAssets.png b/doc/src/images/addAssets.png
index 0aeb610b..c3384fad 100644
--- a/doc/src/images/addAssets.png
+++ b/doc/src/images/addAssets.png
Binary files differ
diff --git a/doc/src/images/brush-strokes-icon.png b/doc/src/images/brush-strokes-icon.png
new file mode 100644
index 00000000..4a3b7194
--- /dev/null
+++ b/doc/src/images/brush-strokes-icon.png
Binary files differ
diff --git a/doc/src/images/corona-icon.png b/doc/src/images/corona-icon.png
new file mode 100644
index 00000000..31cbfa68
--- /dev/null
+++ b/doc/src/images/corona-icon.png
Binary files differ
diff --git a/doc/src/images/datainput-meta.png b/doc/src/images/datainput-meta.png
index 2e399dc1..aeee877a 100644
--- a/doc/src/images/datainput-meta.png
+++ b/doc/src/images/datainput-meta.png
Binary files differ
diff --git a/doc/src/images/editListGroupObjects.png b/doc/src/images/editListGroupObjects.png
new file mode 100644
index 00000000..f454ffc7
--- /dev/null
+++ b/doc/src/images/editListGroupObjects.png
Binary files differ
diff --git a/doc/src/images/effects-brush-strokes.png b/doc/src/images/effects-brush-strokes.png
new file mode 100644
index 00000000..9d9b7c46
--- /dev/null
+++ b/doc/src/images/effects-brush-strokes.png
Binary files differ
diff --git a/doc/src/images/effects-corona.png b/doc/src/images/effects-corona.png
new file mode 100644
index 00000000..3e40ec53
--- /dev/null
+++ b/doc/src/images/effects-corona.png
Binary files differ
diff --git a/doc/src/images/effects-emboss.png b/doc/src/images/effects-emboss.png
new file mode 100644
index 00000000..2014f3bc
--- /dev/null
+++ b/doc/src/images/effects-emboss.png
Binary files differ
diff --git a/doc/src/images/effects-frame-flipper.png b/doc/src/images/effects-frame-flipper.png
new file mode 100644
index 00000000..1c7a37e2
--- /dev/null
+++ b/doc/src/images/effects-frame-flipper.png
Binary files differ
diff --git a/doc/src/images/effects-fullscreen-texture-overlay.png b/doc/src/images/effects-fullscreen-texture-overlay.png
new file mode 100644
index 00000000..af15778e
--- /dev/null
+++ b/doc/src/images/effects-fullscreen-texture-overlay.png
Binary files differ
diff --git a/doc/src/images/effects-screen-space-ao.png b/doc/src/images/effects-screen-space-ao.png
new file mode 100644
index 00000000..7062d04f
--- /dev/null
+++ b/doc/src/images/effects-screen-space-ao.png
Binary files differ
diff --git a/doc/src/images/effects-sepia.png b/doc/src/images/effects-sepia.png
new file mode 100644
index 00000000..1d46583f
--- /dev/null
+++ b/doc/src/images/effects-sepia.png
Binary files differ
diff --git a/doc/src/images/effects-smaa1x.png b/doc/src/images/effects-smaa1x.png
new file mode 100644
index 00000000..6ce6ab91
--- /dev/null
+++ b/doc/src/images/effects-smaa1x.png
Binary files differ
diff --git a/doc/src/images/effects-stylize-scatter.png b/doc/src/images/effects-stylize-scatter.png
new file mode 100644
index 00000000..e249f49d
--- /dev/null
+++ b/doc/src/images/effects-stylize-scatter.png
Binary files differ
diff --git a/doc/src/images/effects-vignette.png b/doc/src/images/effects-vignette.png
new file mode 100644
index 00000000..f3e0d27c
--- /dev/null
+++ b/doc/src/images/effects-vignette.png
Binary files differ
diff --git a/doc/src/images/emboss-icon.png b/doc/src/images/emboss-icon.png
new file mode 100644
index 00000000..c59098d5
--- /dev/null
+++ b/doc/src/images/emboss-icon.png
Binary files differ
diff --git a/doc/src/images/frame-flipper-icon.png b/doc/src/images/frame-flipper-icon.png
new file mode 100644
index 00000000..2c34e609
--- /dev/null
+++ b/doc/src/images/frame-flipper-icon.png
Binary files differ
diff --git a/doc/src/images/fullscreen-texture-overlay-icon.png b/doc/src/images/fullscreen-texture-overlay-icon.png
new file mode 100644
index 00000000..9fbda5c7
--- /dev/null
+++ b/doc/src/images/fullscreen-texture-overlay-icon.png
Binary files differ
diff --git a/doc/src/images/materials-category-dummy.png b/doc/src/images/materials-category-dummy.png
new file mode 100644
index 00000000..5e66e737
--- /dev/null
+++ b/doc/src/images/materials-category-dummy.png
Binary files differ
diff --git a/doc/src/images/materials-category-several.png b/doc/src/images/materials-category-several.png
new file mode 100644
index 00000000..5ef32fb3
--- /dev/null
+++ b/doc/src/images/materials-category-several.png
Binary files differ
diff --git a/doc/src/images/new-data-input.png b/doc/src/images/new-data-input.png
index 486fd0ff..a52166a9 100644
--- a/doc/src/images/new-data-input.png
+++ b/doc/src/images/new-data-input.png
Binary files differ
diff --git a/doc/src/images/screen-space-ao-icon.png b/doc/src/images/screen-space-ao-icon.png
new file mode 100644
index 00000000..ad9c0468
--- /dev/null
+++ b/doc/src/images/screen-space-ao-icon.png
Binary files differ
diff --git a/doc/src/images/sepia-icon.png b/doc/src/images/sepia-icon.png
new file mode 100644
index 00000000..d248ee2e
--- /dev/null
+++ b/doc/src/images/sepia-icon.png
Binary files differ
diff --git a/doc/src/images/smaa1x-icon.png b/doc/src/images/smaa1x-icon.png
new file mode 100644
index 00000000..c6a989fc
--- /dev/null
+++ b/doc/src/images/smaa1x-icon.png
Binary files differ
diff --git a/doc/src/images/stylize-scatter-icon.png b/doc/src/images/stylize-scatter-icon.png
new file mode 100644
index 00000000..b9747566
--- /dev/null
+++ b/doc/src/images/stylize-scatter-icon.png
Binary files differ
diff --git a/doc/src/images/timeline-datainput.png b/doc/src/images/timeline-datainput.png
index be359d63..6cfb3366 100644
--- a/doc/src/images/timeline-datainput.png
+++ b/doc/src/images/timeline-datainput.png
Binary files differ
diff --git a/doc/src/images/variant-tags-panel.png b/doc/src/images/variant-tags-panel.png
index b5f8f29d..0ec3aa9f 100644
--- a/doc/src/images/variant-tags-panel.png
+++ b/doc/src/images/variant-tags-panel.png
Binary files differ
diff --git a/doc/src/images/vignette-icon.png b/doc/src/images/vignette-icon.png
new file mode 100644
index 00000000..bc130d01
--- /dev/null
+++ b/doc/src/images/vignette-icon.png
Binary files differ
diff --git a/doc/src/layers.qdoc b/doc/src/layers.qdoc
index 6bec78dc..016ee81f 100644
--- a/doc/src/layers.qdoc
+++ b/doc/src/layers.qdoc
@@ -116,4 +116,15 @@ the order objects are rendered.
\l{Using Variant Tags}{Variant tags} makes it possible to exclude layers during loading to
optimize performance.
+\section2 Dynamic Resize
+The Dynamic Resize property causes the layer to be dynamically resized based on the content.
+This makes the layer texture as small as it can be while still showing all the content.
+Thus effects like SSAA can be done more efficiently on the layer, since the empty space around
+the content doesn't take up computing power. This can also, depending on the hardware, cause
+performance problems due to constant resizing. This can be mitigated with the Padding property.
+While resizing may cause problems on the GPU side, the content bounds calculation also takes time
+on the CPU. If more inaccurate bounds are enough, Combine Bounds can be used to have less
+calculations per object in the layer. The user has to balance the performance cost of the resize
+to the performance gain of the lower texture size when evaluating the use of this feature.
+
*/
diff --git a/doc/src/whatsnew.qdoc b/doc/src/whatsnew.qdoc
new file mode 100644
index 00000000..5a68ce67
--- /dev/null
+++ b/doc/src/whatsnew.qdoc
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+
+\title What's New
+\page whatsnew.html
+
+\section1 New Features in Qt 3D Studio 2.8
+
+\section2 Image Filtering
+
+It is now possible to specify
+\l{studio-inspector-palette.html#Image Properties}{minification and magnification filters} for
+the Images. This enables mipmapping for the textures.
+
+\section2 Custom Material and Effect Textures
+
+The Custom Material and Effect Textures have been converted to use Images. This means that the same
+image properties as previously only available for the standard materials can now be used to change
+the texture properties for the user-defined shaders. In order to support the image transformation,
+new per-texture uniforms and functions have been added to access transformed texture coordinates and
+texture sample. See \l{custom-material-reference.html#Accessing Textures with Image Transformations}
+{Accessing Textures with Image Transformations} how to use them in the shaders.
+
+When old presentation is opened for the first time with Studio Editor, it needs to convert
+the old texture paths into Images. If the presentation has sub-presentations they should be opened
+separately to ensure that the whole presentation has the same presentation version.
+
+Controlling the Custom property texture using API has been changed to reflect this change. They
+can now be controlled the same way as standard material textures.
+See \l {custom-materials-effects.html#Controlling Custom Properties}{Controlling Custom Properties}
+for more details.
+
+\section2 Timeline Signals
+
+It is now possible to trigger actions from timeline using the new
+\l{studio-basic-objects-palette.html#Signal}{Signal} type.
+
+*/
diff --git a/doc/style/qt5-sidebar.html b/doc/style/qt5-sidebar.html
index 822add38..0259d2ca 100644
--- a/doc/style/qt5-sidebar.html
+++ b/doc/style/qt5-sidebar.html
@@ -15,18 +15,6 @@
</div>
<div class="sectionlist normallist">
<div class="heading">
- <h2>Qt 3D Runtime</h2>
- </div>
- <div class="indexboxcont indexboxbar">
- <ul>
- <li><a href="runtime/index.html">Table of Contents</a></li>
- <li><a href="runtime/qt3d-runtime-qml.html">QML API Reference</a></li>
- <li><a href="runtime/qt3d-runtime-cpp.html">C++ API Reference</a></li>
- </ul>
- </div>
-</div>
-<div class="sectionlist normallist">
- <div class="heading">
<h2>OpenGL Runtime</h2>
</div>
<div class="indexboxcont indexboxbar">
diff --git a/product_dependencies.yaml b/product_dependencies.yaml
new file mode 100644
index 00000000..b6035e89
--- /dev/null
+++ b/product_dependencies.yaml
@@ -0,0 +1,3 @@
+dependencies:
+ ../../qt/tqtc-qt5.git:
+ ref: "b76f628f02c32c28fecb7b7cfa561f9861fd3326"
diff --git a/qt3dstudio.pro b/qt3dstudio.pro
index 56e18268..e1c60dd8 100644
--- a/qt3dstudio.pro
+++ b/qt3dstudio.pro
@@ -99,33 +99,6 @@ load(qt_parts)
$$DEPLOY_TOOL $$shell_quote(\$(DEPLOY_DIR)/Qt3DViewer$${exesuffix}) \
$$EXTRA_DEPLOY_OPTIONS
}
-
- greaterThan(QT_MAJOR_VERSION, 5)|greaterThan(QT_MINOR_VERSION, 10) {
- # Viewer 2.0
- win32 {
- # Viewer 2.0 has similar issues with dependent library naming as viewer 1.0,
- # but it only has one library that is causing problems and no qml (so far),
- # so lets just copy the problem lib over to where windeployqt can find it,
- # i.e. under Qt's bin dir. This pollutes the Qt's bin dir a bit, but as the main
- # use case for this is gathering installer content in CI after everything is
- # already built, this shouldn't be a problem.
- release {
- RUNTIME2_LIB = Qt53DStudioRuntime2$${QT_LIBINFIX}.dll
- } else {
- RUNTIME2_LIB = Qt53DStudioRuntime2$${QT_LIBINFIX}d.dll
- }
- QMAKE_EXTRA_TARGETS += copyRuntime2
- deployTarget.depends += copyRuntime2
- copyRuntime2.commands = \
- $$QMAKE_COPY $$shell_quote($$shell_path( \
- $$OUT_PWD/src/Runtime/qt3d-runtime/bin/$$RUNTIME2_LIB)) \
- $$shell_quote($$shell_path($$[QT_INSTALL_BINS]/$$RUNTIME2_LIB))
- }
-
- deployTarget.commands += && \
- $$DEPLOY_TOOL $$shell_quote(\$(DEPLOY_DIR)/q3dsviewer$${exesuffix}) \
- $$EXTRA_DEPLOY_OPTIONS
- }
} else {
# Create a dummy target for other platforms
deployTarget.commands = @echo deployqt target is not supported for this platform.
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/ClientDataModelBridge/ClientDataModelBridge.cpp b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
index c487d1ae..9d7837f6 100644
--- a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.cpp
@@ -81,6 +81,7 @@ CClientDataModelBridge::CClientDataModelBridge(
, m_Camera(inDefinitions->m_Camera)
, m_Text(inDefinitions->m_Text)
, m_Group(inDefinitions->m_Group)
+ , m_Signal(inDefinitions->m_Signal)
, m_Component(inDefinitions->m_Component)
, m_Behavior(inDefinitions->m_Behavior)
, m_Scene(inDefinitions->m_Scene)
@@ -214,6 +215,9 @@ Qt3DSDMInstanceHandle CClientDataModelBridge::CreateAssetInstance(Q3DStudio::CId
case OBJTYPE_GROUP:
m_DataCore->DeriveInstance(theNewInstance, m_Group.m_Instance);
break;
+ case OBJTYPE_SIGNAL:
+ m_DataCore->DeriveInstance(theNewInstance, m_Signal.m_Instance);
+ break;
case OBJTYPE_COMPONENT:
m_DataCore->DeriveInstance(theNewInstance, m_Component.m_Instance);
break;
@@ -520,7 +524,7 @@ void CClientDataModelBridge::SetName(qt3dsdm::Qt3DSDMInstanceHandle inInstanceHa
}
Q3DStudio::CString CClientDataModelBridge::GetName(
- qt3dsdm::Qt3DSDMInstanceHandle inInstanceHandle, bool renameMaterials) const
+ qt3dsdm::Qt3DSDMInstanceHandle inInstanceHandle, bool renameMaterials)
{
IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
TDataStrPtr theString;
@@ -576,12 +580,29 @@ std::wstring GetInstanceType(IPropertySystem *inPropertySystem, Qt3DSDMInstanceH
// Find which material that uses this image instance
bool CClientDataModelBridge::GetMaterialFromImageInstance(
qt3dsdm::Qt3DSDMInstanceHandle inInstance, qt3dsdm::Qt3DSDMInstanceHandle &outMaterialInstance,
- qt3dsdm::Qt3DSDMPropertyHandle &outProperty) const
+ qt3dsdm::Qt3DSDMPropertyHandle &outProperty)
{
IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
SLong4 theDeletedImageLong4 =
GetNamedInstancePropertyValue<SLong4>(thePropertySystem, inInstance, L"id");
+ auto iter = m_cachedImageParents.find(inInstance);
+ if (iter != m_cachedImageParents.end()) {
+ // We have to recheck the property
+ qt3dsdm::Qt3DSDMInstanceHandle theInstance = iter->second.first;
+ qt3dsdm::Qt3DSDMPropertyHandle theProperty = iter->second.second;
+ SValue value = GetInstancePropertyValue(thePropertySystem, theInstance, theProperty);
+ if (!value.empty() && value.getType() == qt3dsdm::DataModelDataType::Long4) {
+ SLong4 theLong4PropertyValue = value.getData<SLong4>();
+ if (theLong4PropertyValue == theDeletedImageLong4) {
+ outMaterialInstance = theInstance;
+ outProperty = theProperty;
+ return true;
+ }
+ }
+ m_cachedImageParents.erase(iter);
+ }
+
TInstanceHandleList theInstances;
m_DataCore->GetInstancesDerivedFrom(
theInstances, m_DefaultMaterial.m_Instance); // Get all default material instances
@@ -605,6 +626,8 @@ bool CClientDataModelBridge::GetMaterialFromImageInstance(
if (theDeletedImageLong4 == theLong4PropertyValue) {
outMaterialInstance = theInstance;
outProperty = theProperty;
+ m_cachedImageParents.insert({inInstance,
+ std::make_pair(theInstance, theProperty)});
return true;
}
}
@@ -612,6 +635,7 @@ bool CClientDataModelBridge::GetMaterialFromImageInstance(
}
}
+ theInstances.clear();
m_DataCore->GetInstancesDerivedFrom(
theInstances, m_CustomMaterial.m_Instance); // Get all custom material instances
theInstanceCount = theInstances.size();
@@ -628,12 +652,16 @@ bool CClientDataModelBridge::GetMaterialFromImageInstance(
AdditionalMetaDataType::Value theAdditionalMetaDataType =
thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
- if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
- SLong4 theLong4PropertyValue = GetSpecificInstancePropertyValue<SLong4>(
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image
+ || theAdditionalMetaDataType == AdditionalMetaDataType::Texture) {
+ SValue propertyValue = GetInstancePropertyValue(
thePropertySystem, theInstance, theProperty);
- if (theDeletedImageLong4 == theLong4PropertyValue) {
+ if (propertyValue.getType() == qt3dsdm::DataModelDataType::Long4
+ && theDeletedImageLong4 == propertyValue.getData<SLong4>()) {
outMaterialInstance = theInstance;
outProperty = theProperty;
+ m_cachedImageParents.insert({inInstance,
+ std::make_pair(theInstance, theProperty)});
return true;
}
}
@@ -1172,34 +1200,55 @@ Qt3DSDMInstanceHandle CClientDataModelBridge::getMaterialReference(Qt3DSDMInstan
return Qt3DSDMInstanceHandle();
}
-bool CClientDataModelBridge::isMaterialContainer(Qt3DSDMInstanceHandle instance) const
+bool CClientDataModelBridge::isMaterialContainer(Qt3DSDMInstanceHandle instance,
+ Qt3DSDMInstanceHandle materialContainer) const
+{
+ return instance.Valid() && instance == materialContainer;
+}
+
+bool CClientDataModelBridge::isMaterialContainer(Qt3DSDMInstanceHandle instance)
{
return instance.Valid() && instance == getMaterialContainer();
}
-bool CClientDataModelBridge::isInsideMaterialContainer(Qt3DSDMInstanceHandle instance) const
+bool CClientDataModelBridge::isInsideMaterialContainer(Qt3DSDMInstanceHandle instance)
{
- auto parentInstance = GetParentInstance(instance);
- if (parentInstance.Valid() && isMaterialContainer(parentInstance))
+ return isInsideMaterialContainer(instance, GetParentInstance(instance), getMaterialContainer());
+}
+
+bool CClientDataModelBridge::isInsideMaterialContainer(
+ qt3dsdm::Qt3DSDMInstanceHandle instance, qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
+ qt3dsdm::Qt3DSDMInstanceHandle materialContainer)
+{
+ Q_UNUSED(instance);
+ if (parentInstance.Valid() && isMaterialContainer(parentInstance, materialContainer))
return true;
//Check if an image inside a material inside the material container
parentInstance = GetParentInstance(parentInstance);
if (parentInstance.Valid())
- return isMaterialContainer(parentInstance);
+ return isMaterialContainer(parentInstance, materialContainer);
return false;
}
bool CClientDataModelBridge::isInsideMaterialContainerAndNotReferenced(
- Qt3DSDMInstanceHandle instance) const
+ qt3dsdm::Qt3DSDMInstanceHandle instance)
+{
+ return isInsideMaterialContainerAndNotReferenced(instance, GetParentInstance(instance),
+ getMaterialContainer());
+}
+
+bool CClientDataModelBridge::isInsideMaterialContainerAndNotReferenced(
+ Qt3DSDMInstanceHandle instance, qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
+ Qt3DSDMInstanceHandle materialContainer)
{
- if (isInsideMaterialContainer(instance)) {
+ if (isInsideMaterialContainer(instance, parentInstance, materialContainer)) {
QVector<Qt3DSDMInstanceHandle> usedMats;
m_Doc->getUsedSharedMaterials(usedMats);
bool isReferenced = false;
for (auto &usedMat : qAsConst(usedMats)) {
- if (usedMat == instance || usedMat == GetParentInstance(instance)) {
+ if (usedMat == instance || usedMat == parentInstance) {
isReferenced = true;
break;
}
@@ -1219,12 +1268,12 @@ QString CClientDataModelBridge::getMaterialContainerName() const
return QStringLiteral("__Container");
}
-QString CClientDataModelBridge::getMaterialContainerParentPath() const
+QString CClientDataModelBridge::getMaterialContainerParentPath()
{
return GetName(m_Doc->GetSceneInstance()).toQString();
}
-QString CClientDataModelBridge::getMaterialContainerPath() const
+QString CClientDataModelBridge::getMaterialContainerPath()
{
return getMaterialContainerParentPath() + QStringLiteral(".") + getMaterialContainerName();
}
@@ -1252,7 +1301,7 @@ bool CClientDataModelBridge::isBasicMaterial(Qt3DSDMInstanceHandle instance)
return false;
}
-Qt3DSDMInstanceHandle CClientDataModelBridge::getMaterialContainer() const
+Qt3DSDMInstanceHandle CClientDataModelBridge::getMaterialContainer()
{
IObjectReferenceHelper *objRefHelper = m_Doc->GetDataModelObjectReferenceHelper();
if (objRefHelper) {
@@ -1277,37 +1326,6 @@ TInstanceHandleList CClientDataModelBridge::GetItemBaseInstances() const
}
/**
- * Get list of values from all instances derived from inParentInstance
- */
-std::vector<SValue> CClientDataModelBridge::GetValueList(Qt3DSDMInstanceHandle inParentInstance,
- Qt3DSDMPropertyHandle inProperty,
- IValueFilter *inFilter) const
-{
- std::vector<SValue> theValueList;
- TInstanceHandleList theInstances;
- m_DataCore->GetInstancesDerivedFrom(theInstances, inParentInstance);
-
- // Iterate through each instance derived from inParentInstance and get the inProperty property
- // value.
- for (TInstanceHandleList::const_iterator theIter = theInstances.begin();
- theIter != theInstances.end(); ++theIter) {
- // Skip the parent instance.
- if (*theIter == inParentInstance)
- continue;
-
- if (!GetParentInstance(*theIter).Valid())
- continue;
-
- if (isInsideMaterialContainerAndNotReferenced(*theIter))
- continue;
-
- GetValueListFromAllSlides(*theIter, inProperty, theValueList, inFilter);
- }
-
- return theValueList;
-}
-
-/**
* Get list of values from all slides
*/
void CClientDataModelBridge::GetValueListFromAllSlides(Qt3DSDMInstanceHandle inInstance,
@@ -1364,15 +1382,111 @@ struct SValueListFilter : public IValueFilter
}
};
+std::vector<SValue> CClientDataModelBridge::getSourcePathListFromInstances(
+ const std::vector<Qt3DSDMInstanceHandle> &inParentInstance,
+ const std::vector<Qt3DSDMPropertyHandle> &inProperty,
+ IValueFilter *inFilter)
+{
+ IPropertySystem *thePropertySystem = m_Doc->GetStudioSystem()->GetPropertySystem();
+
+ auto getImageIds = [this, thePropertySystem](TInstanceHandleList instances) {
+ std::vector<std::pair<SLong4, qt3dsdm::Qt3DSDMInstanceHandle>> imageIds;
+ for (TInstanceHandleList::const_iterator theIter = instances.begin();
+ theIter != instances.end(); ++theIter) {
+ TPropertyHandleList theProperties;
+ auto theInstance = *theIter;
+ thePropertySystem->GetAggregateInstanceProperties(theInstance, theProperties);
+ size_t thePropertyCount = theProperties.size();
+ for (size_t thePropertyIndex = 0; thePropertyIndex < thePropertyCount;
+ ++thePropertyIndex) {
+ Qt3DSDMPropertyHandle theProperty = theProperties[thePropertyIndex];
+ AdditionalMetaDataType::Value theAdditionalMetaDataType =
+ thePropertySystem->GetAdditionalMetaDataType(theInstance, theProperty);
+
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ theProperties.push_back(theProperty);
+ SLong4 theLong4PropertyValue = GetSpecificInstancePropertyValue<SLong4>(
+ thePropertySystem, theInstance, theProperty);
+ imageIds.push_back(std::make_pair(theLong4PropertyValue, theInstance));
+ }
+ }
+ }
+ return imageIds;
+ };
+
+ auto materialContainer = getMaterialContainer();
+
+ // Get all image parent instances
+ TInstanceHandleList parentInstances;
+ m_DataCore->GetInstancesDerivedFrom(parentInstances, m_DefaultMaterial.m_Instance);
+ m_DataCore->GetInstancesDerivedFrom(parentInstances, m_CustomMaterial.m_Instance);
+ m_DataCore->GetInstancesDerivedFrom(parentInstances, m_Layer.m_Instance);
+
+ // Get all image properties
+ std::vector<std::pair<SLong4, qt3dsdm::Qt3DSDMInstanceHandle>> imageIdsParents
+ = getImageIds(parentInstances);
+
+ auto getValueList = [this, thePropertySystem, materialContainer](std::vector<SValue> &theValueList,
+ Qt3DSDMInstanceHandle parentInstance,
+ Qt3DSDMPropertyHandle property, IValueFilter *inFilter,
+ const std::vector<std::pair<SLong4, qt3dsdm::Qt3DSDMInstanceHandle>> &imageIdsParents) {
+ TInstanceHandleList theInstances;
+ m_DataCore->GetInstancesDerivedFrom(theInstances, parentInstance);
+
+ auto findParent = [](std::vector<std::pair<SLong4, qt3dsdm::Qt3DSDMInstanceHandle>> pairs,
+ const SLong4 &long4) -> qt3dsdm::Qt3DSDMInstanceHandle {
+ for (auto iter = pairs.begin(); iter != pairs.end(); iter++) {
+ if (iter->first == long4)
+ return iter->second;
+ }
+ return {};
+ };
+
+ Q3DStudio::TGraphPtr theGraph = m_Doc->GetAssetGraph();
+
+ // Iterate through each instance derived from inParentInstance and get the inProperty property
+ // value.
+ for (TInstanceHandleList::const_iterator theIter = theInstances.begin();
+ theIter != theInstances.end(); ++theIter) {
+ auto instance = *theIter;
+ // Skip the parent instance.
+ if (*theIter == m_SceneAsset.m_Instance)
+ continue;
+
+ qt3dsdm::Qt3DSDMInstanceHandle parentInstance;
+ if (IsImageInstance(instance)) {
+ // find the image from the image properties
+ SLong4 theDeletedImageLong4 =
+ GetNamedInstancePropertyValue<SLong4>(thePropertySystem, instance, L"id");
+ parentInstance = findParent(imageIdsParents, theDeletedImageLong4);
+ } else if (theGraph->IsExist(instance)) {
+ parentInstance = theGraph->GetParent(instance);
+ }
+
+ if (!parentInstance.Valid())
+ continue;
+
+ if (isInsideMaterialContainerAndNotReferenced(*theIter, parentInstance, materialContainer))
+ continue;
+
+ GetValueListFromAllSlides(*theIter, property, theValueList, inFilter);
+ }
+ };
+ std::vector<SValue> theValueList;
+ for (int i = 0; i < inParentInstance.size(); i++)
+ getValueList(theValueList, inParentInstance[i], inProperty[i], inFilter, imageIdsParents);
+ return theValueList;
+}
+
/**
* Get SourcePath list from all instances
*/
-std::set<QString> CClientDataModelBridge::GetSourcePathList() const
+std::set<QString> CClientDataModelBridge::GetSourcePathList()
{
// Get the source path property list
SValueListFilter theFilter(*this);
- std::vector<SValue> theValueList =
- GetValueList(m_SceneAsset.m_Instance, m_SceneAsset.m_SourcePath, &theFilter);
+ auto theValueList = getSourcePathListFromInstances({m_SceneAsset.m_Instance},
+ {m_SceneAsset.m_SourcePath}, &theFilter);
// Translate from SValue to QString and also remove the identifier
std::set<QString> theSourcePathList;
@@ -1388,10 +1502,11 @@ std::set<QString> CClientDataModelBridge::GetSourcePathList() const
/**
* Get Font file list from all Text instances
*/
-std::set<QString> CClientDataModelBridge::GetFontFileList() const
+std::set<QString> CClientDataModelBridge::GetFontFileList()
{
// Get the font name property list
- std::vector<SValue> theValueList = GetValueList(m_Text.m_Instance, m_Text.m_Font);
+ std::vector<SValue> theValueList = getSourcePathListFromInstances({m_Text.m_Instance},
+ {m_Text.m_Font}, nullptr);
std::set<QString> theFontNameList;
for (auto &val : theValueList) {
QString font = get<QString>(val);
@@ -1432,7 +1547,7 @@ std::set<QString> CClientDataModelBridge::GetFontFileList() const
static void GetDynamicObjecTextures(IDataCore &inDataCore, IPropertySystem &inPropertySystem,
Qt3DSDMInstanceHandle inBaseInstance,
std::vector<SValue> &outValues,
- const CClientDataModelBridge &inBridge)
+ CClientDataModelBridge &inBridge)
{
std::vector<SValue> &theValueList(outValues);
// Get all effect instances
@@ -1481,7 +1596,7 @@ static void GetDynamicObjecTextures(IDataCore &inDataCore, IPropertySystem &inPr
/**
* Get texture list from all effect instances
*/
-std::set<QString> CClientDataModelBridge::GetDynamicObjectTextureList() const
+std::set<QString> CClientDataModelBridge::GetDynamicObjectTextureList()
{
std::vector<SValue> theValueList;
@@ -1497,21 +1612,46 @@ std::set<QString> CClientDataModelBridge::GetDynamicObjectTextureList() const
// Translate from SValue to QString and also remove the identifier
std::set<QString> theSourcePathList;
for (auto &val : theValueList) {
- Q3DStudio::CFilePath theSourcePath = qt3dsdm::get<QString>(val);
- if (!theSourcePath.filePath().isEmpty())
- theSourcePathList.insert(theSourcePath.toQString());
+ if (val.getType() == qt3dsdm::DataModelDataType::String) {
+ Q3DStudio::CFilePath theSourcePath = qt3dsdm::get<QString>(val);
+ if (!theSourcePath.filePath().isEmpty())
+ theSourcePathList.insert(theSourcePath.toQString());
+ }
}
return theSourcePathList;
}
-std::set<QString> CClientDataModelBridge::getRenderableList() const
+TInstanceHandleList CClientDataModelBridge::GetShaderInstances()
+{
+ TInstanceHandleList theCustomMatInstances;
+ TInstanceHandleList theEffectInstances;
+ m_DataCore->GetInstancesDerivedFrom(theCustomMatInstances, m_CustomMaterial.m_Instance);
+ m_DataCore->GetInstancesDerivedFrom(theEffectInstances, m_Effect.m_Instance);
+
+ TInstanceHandleList cleanedMatInstances;
+ for (const auto &it : theCustomMatInstances) {
+ if (it != m_CustomMaterial.m_Instance)
+ cleanedMatInstances.insert(cleanedMatInstances.end(), it);
+ }
+ TInstanceHandleList cleanedFxInstances;
+
+ // Pick only effects that are not base instances, and which have a valid parent
+ for (const auto &it : theEffectInstances) {
+ if (it != m_Effect.m_Instance && GetParentInstance(it).Valid())
+ cleanedFxInstances.insert(cleanedFxInstances.end(), it);
+ }
+
+ cleanedFxInstances.insert(cleanedFxInstances.end(), cleanedMatInstances.begin(),
+ cleanedMatInstances.end());
+ return cleanedFxInstances;
+}
+
+std::set<QString> CClientDataModelBridge::getRenderableList()
{
- std::vector<SValue> valueList
- = GetValueList(m_Layer.m_Instance, m_SceneAsset.m_SourcePath, nullptr);
- std::vector<SValue> imageList
- = GetValueList(m_SceneImage.m_Instance, m_SceneImage.m_SubPresentation, nullptr);
- valueList.insert(valueList.end(), imageList.begin(), imageList.end());
+ auto valueList = getSourcePathListFromInstances(
+ {m_Layer.m_Instance, m_SceneImage.m_Instance},
+ {m_SceneAsset.m_SourcePath, m_SceneImage.m_SubPresentation}, nullptr);
std::set<QString> idList;
for (auto &val : valueList) {
@@ -1577,6 +1717,7 @@ bool CClientDataModelBridge::CanDelete(qt3dsdm::Qt3DSDMInstanceHandle inInstance
case OBJTYPE_MODEL:
case OBJTYPE_TEXT:
case OBJTYPE_GROUP:
+ case OBJTYPE_SIGNAL:
case OBJTYPE_CAMERA:
case OBJTYPE_LIGHT:
case OBJTYPE_IMAGE:
@@ -1685,7 +1826,7 @@ Q3DStudio::CId CClientDataModelBridge::GetGUID(qt3dsdm::Qt3DSDMInstanceHandle in
}
qt3dsdm::Qt3DSDMInstanceHandle
-CClientDataModelBridge::GetParentInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const
+CClientDataModelBridge::GetParentInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
{
if (IsImageInstance(inInstance)) {
qt3dsdm::Qt3DSDMInstanceHandle theParentInstance;
@@ -1720,6 +1861,8 @@ CClientDataModelBridge::GetObjectType(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
return OBJTYPE_CAMERA;
else if (theType == L"Group")
return OBJTYPE_GROUP;
+ else if (theType == L"Signal")
+ return OBJTYPE_SIGNAL;
else if (theType == L"Component")
return OBJTYPE_COMPONENT;
else if (theType == L"Image" || theType == L"LibraryImage")
@@ -1775,6 +1918,11 @@ bool CClientDataModelBridge::IsGroupInstance(qt3dsdm::Qt3DSDMInstanceHandle inIn
return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Group.m_Instance);
}
+bool CClientDataModelBridge::IsSignalInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const
+{
+ return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_Signal.m_Instance);
+}
+
bool CClientDataModelBridge::IsActionInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const
{
return m_DataCore->IsInstanceOrDerivedFrom(inInstance, m_ActionItem.m_Instance);
diff --git a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
index 3233bd42..f0f5004d 100644
--- a/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
+++ b/src/Authoring/Client/Code/Core/Doc/ClientDataModelBridge/ClientDataModelBridge.h
@@ -75,6 +75,7 @@ typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Light>
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Camera> SDataModelCamera;
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Text> SDataModelText;
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Group> SDataModelGroup;
+typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Signal> SDataModelSignal;
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Component> SDataModelComponent;
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Behavior> SDataModelBehavior;
typedef qt3dsdm::SComposerObjectDefinition<qt3dsdm::ComposerObjectTypes::Scene> SDataModelScene;
@@ -133,6 +134,7 @@ class CClientDataModelBridge
SDataModelCamera &m_Camera;
SDataModelText &m_Text;
SDataModelGroup &m_Group;
+ SDataModelSignal &m_Signal;
SDataModelComponent &m_Component;
SDataModelBehavior &m_Behavior;
SDataModelScene &m_Scene;
@@ -164,6 +166,8 @@ class CClientDataModelBridge
qt3dsdm::TInstanceHandleList m_CacheMaterialInstances;
qt3dsdm::TInstanceHandleList m_CacheModelInstances;
+ std::unordered_map<int, std::pair<int, int>> m_cachedImageParents;
+
public:
CClientDataModelBridge(qt3dsdm::IDataCore *inDataCore, qt3dsdm::ISlideCore *inSlideCore,
qt3dsdm::ISlideGraphCore *inSlideGraphCore,
@@ -230,6 +234,7 @@ public:
const SDataModelCamera &GetCamera() const { return m_Camera; }
const SDataModelText &GetText() const { return m_Text; }
const SDataModelGroup &GetGroup() const { return m_Group; }
+ const SDataModelSignal &GetSignal() const { return m_Signal; }
const SDataModelComponent &GetComponent() const { return m_Component; }
const SDataModelBehavior &GetBehavior() const { return m_Behavior; }
const SDataModelScene &GetScene() const { return m_Scene; }
@@ -246,7 +251,7 @@ public:
// Operations which likely don't belong on this class
bool GetMaterialFromImageInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMInstanceHandle &outMaterialInstance,
- qt3dsdm::Qt3DSDMPropertyHandle &outProperty) const;
+ qt3dsdm::Qt3DSDMPropertyHandle &outProperty);
bool GetLayerFromImageProbeInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMInstanceHandle &outLayerInstance,
qt3dsdm::Qt3DSDMPropertyHandle &outProperty) const;
@@ -330,7 +335,7 @@ public:
void SetName(qt3dsdm::Qt3DSDMInstanceHandle inInstanceHandle, const Q3DStudio::CString &inName);
Q3DStudio::CString GetName(qt3dsdm::Qt3DSDMInstanceHandle inInstanceHandle,
- bool renameMaterials = false) const;
+ bool renameMaterials = false);
// Helper for old methods in CAsset
bool IsInActiveComponent(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
@@ -347,20 +352,21 @@ public:
QString GetSourcePath(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
Q3DStudio::CString getSubpresentation(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
qt3dsdm::Qt3DSDMInstanceHandle getMaterialReference(qt3dsdm::Qt3DSDMInstanceHandle instance);
- bool isMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance) const;
- bool isInsideMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance) const;
- bool isInsideMaterialContainerAndNotReferenced(qt3dsdm::Qt3DSDMInstanceHandle instance) const;
+ bool isMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance);
+ bool isInsideMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance);
+ bool isInsideMaterialContainerAndNotReferenced(qt3dsdm::Qt3DSDMInstanceHandle instance);
QString getDefaultMaterialName() const;
QString getMaterialContainerName() const;
- QString getMaterialContainerParentPath() const;
- QString getMaterialContainerPath() const;
+ QString getMaterialContainerParentPath();
+ QString getMaterialContainerPath();
bool isDefaultMaterial(qt3dsdm::Qt3DSDMInstanceHandle instance) const;
bool isBasicMaterial(qt3dsdm::Qt3DSDMInstanceHandle instance);
- qt3dsdm::Qt3DSDMInstanceHandle getMaterialContainer() const;
- std::set<QString> GetSourcePathList() const;
- std::set<QString> GetFontFileList() const;
- std::set<QString> GetDynamicObjectTextureList() const;
- std::set<QString> getRenderableList() const;
+ qt3dsdm::Qt3DSDMInstanceHandle getMaterialContainer();
+ std::set<QString> GetSourcePathList();
+ std::set<QString> GetFontFileList();
+ std::set<QString> GetDynamicObjectTextureList();
+ qt3dsdm::TInstanceHandleList GetShaderInstances();
+ std::set<QString> getRenderableList();
bool IsLockedAtAll(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
bool IsDuplicateable(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
bool IsMultiSelectable(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
@@ -373,8 +379,7 @@ public:
IValueFilter *inFilter = nullptr) const;
Q3DStudio::CId GetGUID(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
- qt3dsdm::Qt3DSDMInstanceHandle GetParentInstance(
- qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
+ qt3dsdm::Qt3DSDMInstanceHandle GetParentInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
// TODO: EStudioObjectType and EASSETTYPE can't co-exist, one must go. Think EStudioObjectType
// should win since things are better classified
@@ -382,6 +387,7 @@ public:
bool IsBehaviorInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
bool IsCameraInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
bool IsGroupInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
+ bool IsSignalInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
bool IsActionInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
bool IsComponentInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
bool IsLayerInstance(qt3dsdm::Qt3DSDMInstanceHandle inInstance) const;
@@ -409,11 +415,20 @@ protected:
qt3dsdm::Qt3DSDMInstanceHandle GetChildByName(qt3dsdm::Qt3DSDMInstanceHandle inParent,
Q3DStudio::CString inChildName,
qt3dsdm::Qt3DSDMInstanceHandle skipInstance);
- std::vector<qt3dsdm::SValue> GetValueList(qt3dsdm::Qt3DSDMInstanceHandle inParentInstance,
- qt3dsdm::Qt3DSDMPropertyHandle inProperty,
- IValueFilter *inFilter = nullptr) const;
private:
+ std::vector<qt3dsdm::SValue> getSourcePathListFromInstances(
+ const std::vector<qt3dsdm::Qt3DSDMInstanceHandle> &inParentInstance,
+ const std::vector<qt3dsdm::Qt3DSDMPropertyHandle> &inProperty,
+ IValueFilter *inFilter);
+ bool isMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance,
+ qt3dsdm::Qt3DSDMInstanceHandle materialContainer) const;
+ bool isInsideMaterialContainer(qt3dsdm::Qt3DSDMInstanceHandle instance,
+ qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
+ qt3dsdm::Qt3DSDMInstanceHandle materialContainer);
+ bool isInsideMaterialContainerAndNotReferenced(qt3dsdm::Qt3DSDMInstanceHandle instance,
+ qt3dsdm::Qt3DSDMInstanceHandle parentInstance,
+ qt3dsdm::Qt3DSDMInstanceHandle materialContainer);
qt3dsdm::Qt3DSDMInstanceHandle GetInstanceByGUIDDerivedFrom(qt3dsdm::SLong4 inLong4,
qt3dsdm::Qt3DSDMInstanceHandle inParentHandle,
qt3dsdm::Qt3DSDMPropertyHandle inProperty);
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.cpp b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
index e0b6af8c..e0d2479b 100644
--- a/src/Authoring/Client/Code/Core/Doc/Doc.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/Doc.cpp
@@ -74,7 +74,7 @@
#include <QtCore/qtimer.h>
#include <QtGui/qvalidator.h>
-const long UIP_VERSION = 6; // current version (latest supported)
+const long UIP_VERSION = 7; // current version (latest supported)
const long LAST_SUPPORTED_UIP_VERSION = 1;
IMPLEMENT_OBJECT_COUNTER(CDoc)
@@ -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.
*/
@@ -806,12 +858,13 @@ void CDoc::CutObject(qt3dsdm::TInstanceHandleList inInstances)
using namespace Q3DStudio;
if (theContinueCutFlag) {
- CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances));
+ CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances, true));
Qt3DSFile theFile(thePath);
CStudioClipboard::CopyObjectToClipboard(
theFile, false, false,
m_StudioSystem->GetClientDataModelBridge()->GetObjectType(inInstances[0]));
SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Cut Object"))->DeleteInstances(inInstances);
+ m_firstPasteAfterCut = true;
}
}
@@ -822,11 +875,12 @@ void CDoc::CopyObject(qt3dsdm::TInstanceHandleList inInstances)
if (inInstances.empty())
return;
using namespace Q3DStudio;
- CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances));
+ CFilePath thePath(GetDocumentReader().CopySceneGraphObjects(inInstances, false));
Qt3DSFile theFile(thePath);
CStudioClipboard::CopyObjectToClipboard(
theFile, false, false,
m_StudioSystem->GetClientDataModelBridge()->GetObjectType(inInstances[0]));
+ m_firstPasteAfterCut = false;
}
void CDoc::PasteObject(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
@@ -838,7 +892,9 @@ void CDoc::PasteObject(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
Qt3DSFile theTempAPFile = CStudioClipboard::GetObjectFromClipboard(false, dummy);
SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Paste Object"))
->PasteSceneGraphObject(theTempAPFile.GetAbsolutePath(), theInstance, true,
- DocumentEditorInsertType::LastChild, CPt());
+ DocumentEditorInsertType::LastChild, CPt(),
+ m_firstPasteAfterCut);
+ m_firstPasteAfterCut = false;
}
}
@@ -851,7 +907,9 @@ void CDoc::PasteObjectMaster(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
Qt3DSFile theTempAPFile = CStudioClipboard::GetObjectFromClipboard(false, dummy);
SCOPED_DOCUMENT_EDITOR(*this, QObject::tr("Paste Object"))
->PasteSceneGraphObjectMaster(theTempAPFile.GetAbsolutePath(), theInstance, true,
- DocumentEditorInsertType::LastChild, CPt());
+ DocumentEditorInsertType::LastChild, CPt(),
+ m_firstPasteAfterCut);
+ m_firstPasteAfterCut = false;
}
}
@@ -1160,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) {
@@ -1205,15 +1269,15 @@ void CDoc::onPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
{
using namespace qt3dsdm;
const auto bridge = m_StudioSystem->GetClientDataModelBridge();
+ bool isInsideMaterialContainer = bridge->isInsideMaterialContainer(inInstance);
// Save the material definition upon undo and redo
- if (m_Core->GetCmdStack()->isUndoingOrRedoing() &&
- bridge->isInsideMaterialContainer(inInstance)) {
+ if (m_Core->GetCmdStack()->isUndoingOrRedoing() && isInsideMaterialContainer) {
getSceneEditor()->saveIfMaterial(inInstance);
}
// If a material inside the material container is renamed, the file has to be renamed too
// and the referenced materials that refer to that renamed material
- if (inProperty == bridge->GetNameProperty() && bridge->isInsideMaterialContainer(inInstance)) {
+ if (inProperty == bridge->GetNameProperty() && isInsideMaterialContainer) {
const auto sceneEditor = getSceneEditor();
const QString dirPath = GetDocumentDirectory();
@@ -2113,13 +2177,28 @@ void CDoc::LoadPresentationFile(CBufferedInputStream *inInputStream)
m_StudioSystem->GetFullSystem()->GetSignalSender()->SendActiveSlide(theMasterSlide, 1,
theChildSlide);
- if (uipVersion < 6) {
+ if (uipVersion < 6 || g_StudioApp.IsConvertingPresentationOn()) {
QTimer::singleShot(0, [=](){
// uipVersion 6 introduced vec4 colors
- g_StudioApp.GetDialogs()->DisplayMessageBox(
- tr("Old Presentation Version"),
- tr("Some custom materials, effects, and behaviors may not work correctly."),
- Qt3DSMessageBox::ICON_WARNING, false);
+ if (g_StudioApp.IsConvertingPresentationOn() && uipVersion < 6) {
+ g_StudioApp.GetDialogs()->DisplayMessageBox(
+ tr("Old Presentation Version and Texture Paths"),
+ tr("Some custom materials, effects, and behaviors may not work correctly.\n" \
+ "Converting custom material and effect textures into images."),
+ Qt3DSMessageBox::ICON_WARNING, false);
+ g_StudioApp.SetConvertingPresentationOff();
+ } else if (g_StudioApp.IsConvertingPresentationOn()) {
+ g_StudioApp.GetDialogs()->DisplayMessageBox(
+ tr("Old Texture Paths"),
+ tr("Converting custom material and effect textures into images."),
+ Qt3DSMessageBox::ICON_WARNING, false);
+ g_StudioApp.SetConvertingPresentationOff();
+ } else {
+ g_StudioApp.GetDialogs()->DisplayMessageBox(
+ tr("Old Presentation Version"),
+ tr("Some custom materials, effects, and behaviors may not work correctly."),
+ Qt3DSMessageBox::ICON_WARNING, false);
+ }
});
}
@@ -2165,11 +2244,9 @@ int CDoc::LoadStudioData(CBufferedInputStream *inInputStream)
CreateDOMReader(*inInputStream, theVersion);
if (!theReaderPtr)
throw CInvalidFileFormatException();
-
+ g_StudioApp.setDocumentVersion(theVersion);
IDOMReader &theReader(*theReaderPtr);
- theReader.Att("version", theVersion);
-
CProjectSettingsSerializer theProjectSettingsSerializer(
m_Core->GetStudioProjectSettings());
theReader.Serialize(L"ProjectSettings", theProjectSettingsSerializer);
@@ -2430,6 +2507,7 @@ void CDoc::SavePresentationFile(CBufferedOutputStream *inOutputStream)
using namespace qt3dsdm;
using namespace Q3DStudio;
+ g_StudioApp.setDocumentVersion(UIP_VERSION);
std::shared_ptr<IDOMWriter> theWriterPtr(CreateDOMWriter());
IDOMWriter &theWriter(*theWriterPtr);
@@ -2482,20 +2560,18 @@ void CDoc::SavePresentationFile(CBufferedOutputStream *inOutputStream)
IDOMWriter::Scope __BufferData(theWriter, L"BufferData");
for (size_t idx = 0, end = theImageBuffers.size(); idx < end; ++idx) {
SImageTextureData theBuffer = theImageBuffers[idx].second;
- if (theBuffer.m_TextureFlags.HasTransparency()) {
- IDOMWriter::Scope __ImageScope(theWriter, L"ImageBuffer");
- theWriter.Att(L"sourcepath", theImageBuffers[idx].first.c_str());
- // Writing boolean in wide text results just in "T" or "F" on Linux
- theWriter.Att("hasTransparency", true);
- if (theBuffer.m_TextureFlags.HasOpaquePixels())
- theWriter.Att("hasOpaquePixels", true);
- }
+ IDOMWriter::Scope __ImageScope(theWriter, L"ImageBuffer");
+ theWriter.Att(L"sourcepath", theImageBuffers[idx].first.c_str());
+ // Writing boolean in wide text results just in "T" or "F" on Linux
+ theWriter.Att("hasTransparency", theBuffer.m_TextureFlags.HasTransparency());
+ if (theBuffer.m_TextureFlags.HasOpaquePixels())
+ theWriter.Att("hasOpaquePixels", true);
}
}
}
std::shared_ptr<IComposerSerializer> theSerializer(CreateSerializer());
- theSerializer->SerializeScene(theWriter);
+ theSerializer->SerializeScene(theWriter, GetDocumentDirectory());
SBufferedOutputStreamOutStream theStream(*inOutputStream);
CDOMSerializer::WriteXMLHeader(theStream);
@@ -2838,9 +2914,9 @@ void CDoc::OnPresentationDeactivated()
* @param outMats list of scene materials
*/
void CDoc::getSceneMaterials(qt3dsdm::Qt3DSDMInstanceHandle inParent,
- QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats) const
+ QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats)
{
- const CClientDataModelBridge *bridge = m_StudioSystem->GetClientDataModelBridge();
+ CClientDataModelBridge *bridge = m_StudioSystem->GetClientDataModelBridge();
for (long i = 0, count = m_AssetGraph->GetChildCount(inParent); i < count; ++i) {
qt3dsdm::Qt3DSDMInstanceHandle theChild(m_AssetGraph->GetChild(inParent, i));
if (!bridge->isMaterialContainer(theChild) && !bridge->isInsideMaterialContainer(theChild)
diff --git a/src/Authoring/Client/Code/Core/Doc/Doc.h b/src/Authoring/Client/Code/Core/Doc/Doc.h
index af91c59e..0d05880b 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();
@@ -396,7 +403,7 @@ public:
bool preUndo() override;
void getSceneMaterials(qt3dsdm::Qt3DSDMInstanceHandle inParent,
- QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats) const;
+ QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats);
void getSceneReferencedMaterials(qt3dsdm::Qt3DSDMInstanceHandle inParent,
QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats) const;
void getUsedSharedMaterials(QVector<qt3dsdm::Qt3DSDMInstanceHandle> &outMats) const;
@@ -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;
@@ -505,6 +514,9 @@ protected:
Q3DStudio::CRect m_ClientSize;
Q3DStudio::CRect m_SceneRect; // The dimensions of the active scene view
+ // Indicate that the paste operation is first after cut operation
+ bool m_firstPasteAfterCut = false;
+
private:
bool m_playbackPreviewOn = false;
QString m_presentationId;
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp
index a22a1376..e64a3a6f 100644
--- a/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentBufferCache.cpp
@@ -135,15 +135,22 @@ struct SDocBufferCache : public IDocumentBufferCache
}
}
- void reloadImageSet(const QSet<QString> &imageSet) override
+ void reloadImageSet(const QSet<QString> &imageSet, bool flipCompressedTextures) override
{
auto bufMan = GetBufferManager();
if (bufMan) {
bufMan->unloadSet(imageSet);
- bufMan->loadSet(imageSet);
+ bufMan->loadSet(imageSet, flipCompressedTextures);
}
}
+ void reloadAll(bool flipCompressedTextures) override
+ {
+ auto bufMan = GetBufferManager();
+ if (bufMan)
+ bufMan->reloadAll(flipCompressedTextures);
+ }
+
// Names are declared in the same order as the primitives
// offset by the empty primitive
const wchar_t **GetPrimitiveNames() override
@@ -239,10 +246,8 @@ struct SDocBufferCache : public IDocumentBufferCache
return entry->second.m_ImageBuffer;
CFilePath thePath(m_Doc.GetResolvedPathToDoc(inPath));
SImageTextureData retval;
- if (thePath.IsFile() && GetBufferManager()) {
- retval = GetBufferManager()->LoadRenderImage(
- GetBufferManager()->GetStringTable().RegisterStr(thePath.toCString()));
- }
+ if (thePath.IsFile() && GetBufferManager())
+ retval = GetBufferManager()->LoadRenderImage(thePath.toQString());
if (retval.m_Texture)
m_Buffers.insert(
make_pair(m_StringTablePtr->RegisterStr(inPath.toCString()), SModelBufferOrImage(retval)));
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
index f1139d7d..f2627e05 100644
--- a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp
@@ -94,6 +94,9 @@
#include "StudioUtils.h"
#include "Qt3DSDMHandles.h"
#include "IStudioRenderer.h"
+#include "Qt3DSRenderBufferManager.h"
+#include "Qt3DSRenderDynamicObjectSystem.h"
+#include "Qt3DSRenderUIPSharedTranslation.h"
namespace {
@@ -289,7 +292,8 @@ public:
if (m_SlideCore.GetSpecificInstancePropertyValue(theAssociatedSlide, instance, inProperty,
theGuid)
|| m_DataCore.GetInstancePropertyValue(instance, inProperty, theGuid)) {
- return m_Bridge.GetInstanceByGUID(get<SLong4>(theGuid));
+ if (theGuid.getType() == qt3dsdm::DataModelDataType::Long4)
+ return m_Bridge.GetInstanceByGUID(get<SLong4>(theGuid));
}
return TInstanceHandle();
}
@@ -699,7 +703,7 @@ public:
}
pair<std::shared_ptr<qt3dsdm::IDOMWriter>, CFilePath>
- DoCopySceneGraphObject(const TInstanceHandleList &inInstances)
+ DoCopySceneGraphObject(const TInstanceHandleList &inInstances, bool preserveFileIds)
{
if (inInstances.empty())
return pair<std::shared_ptr<qt3dsdm::IDOMWriter>, CFilePath>();
@@ -707,7 +711,8 @@ public:
std::shared_ptr<IDOMWriter> theWriter(m_Doc.CreateDOMWriter());
TInstanceHandleList theInstances = ToGraphOrdering(inInstances);
m_Doc.CreateSerializer()->SerializeSceneGraphObjects(*theWriter, theInstances,
- GetActiveSlide(inInstances[0]));
+ GetActiveSlide(inInstances[0]),
+ preserveFileIds);
CFilePath theFile = WriteWriterToFile(*theWriter, L"SceneGraph");
return make_pair(theWriter, theFile);
}
@@ -716,7 +721,7 @@ public:
std::shared_ptr<qt3dsdm::IDOMReader>
CopySceneGraphObjectsToMemory(const qt3dsdm::TInstanceHandleList &instanceList)
{
- return DoCopySceneGraphObject(instanceList).first->CreateDOMReader();
+ return DoCopySceneGraphObject(instanceList, false).first->CreateDOMReader();
}
// Exposed through document reader interface
@@ -762,7 +767,7 @@ public:
return theFinalPath;
}
- CFilePath CopySceneGraphObjects(TInstanceHandleList inInstances) override
+ CFilePath CopySceneGraphObjects(TInstanceHandleList inInstances, bool preserveFileIds) override
{
if (inInstances.empty())
return L"";
@@ -773,7 +778,7 @@ public:
if (!shouldCopy)
return L"";
- return DoCopySceneGraphObject(inInstances).second;
+ return DoCopySceneGraphObject(inInstances, preserveFileIds).second;
}
CFilePath CopyAction(Qt3DSDMActionHandle inAction, Qt3DSDMSlideHandle inSlide) override
@@ -1066,6 +1071,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);
@@ -1166,8 +1183,15 @@ public:
if (!m_Bridge.GetMaterialFromImageInstance(instance, theParent, theProperty))
m_Bridge.GetLayerFromImageProbeInstance(instance, theParent, theProperty);
- if (theParent.Valid())
- m_PropertySystem.SetInstancePropertyValue(theParent, theProperty, SLong4());
+ if (theParent.Valid()) {
+ auto type = m_PropertySystem.GetAdditionalMetaDataType(theParent, theProperty);
+ if (type == AdditionalMetaDataType::Image) {
+ m_PropertySystem.SetInstancePropertyValue(theParent, theProperty, SLong4());
+ } else if (type == AdditionalMetaDataType::Texture) {
+ m_PropertySystem.SetInstancePropertyValue(theParent, theProperty,
+ std::make_shared<CDataStr>(Q3DStudio::CString()));
+ }
+ }
} else if (m_Bridge.IsBehaviorInstance(instance) || m_Bridge.IsEffectInstance(instance)
|| m_Bridge.IsCustomMaterialInstance(instance)) {
// Check if this is the last instance that uses the same sourcepath property
@@ -1423,6 +1447,24 @@ public:
SetName(theMaterial, materialName);
}
+ const dynamic::SPropertyDefinition *findDynamicProperty(const SMetaDataDynamicObject &dynObj,
+ CRegisteredString name)
+ {
+ for (int i = 0; i < dynObj.m_Properties.size(); i++) {
+ if (dynObj.m_Properties[i].m_Name == name)
+ return &dynObj.m_Properties[i];
+ }
+ return nullptr;
+ }
+
+ bool isDynamicObjectInstance(TInstanceHandle instance) const
+ {
+ return m_DataCore.IsInstanceOrDerivedFrom(
+ instance, m_Bridge.GetObjectDefinitions().m_CustomMaterial.m_Instance)
+ || m_DataCore.IsInstanceOrDerivedFrom(
+ instance, m_Bridge.GetObjectDefinitions().m_Effect.m_Instance);
+ }
+
// Normal way in to the system.
void SetInstancePropertyValue(TInstanceHandle instance, TPropertyHandle propName,
const SValue &value, bool inAutoDelete = true) override
@@ -1431,25 +1473,64 @@ public:
AdditionalMetaDataType::Value theProperytMetaData =
thePropertySystem.GetAdditionalMetaDataType(instance, propName);
TSlideHandle theNewSlide(GetSlideForProperty(instance, propName));
- if (theProperytMetaData == AdditionalMetaDataType::Image) {
+ if (theProperytMetaData == AdditionalMetaDataType::Image
+ || theProperytMetaData == AdditionalMetaDataType::Texture) {
TDataStrPtr theImageSourcePath = get<TDataStrPtr>(value);
bool hasValue = theImageSourcePath && theImageSourcePath->GetLength() > 0;
qt3dsdm::Qt3DSDMInstanceHandle theImageInstance =
GetImageInstanceForProperty(instance, propName);
+ SMetaDataDynamicObject *dynObj = nullptr;
+ if (isDynamicObjectInstance(instance)) {
+ TInstanceHandleList parents;
+ m_DataCore.GetInstanceParents(instance, parents);
+ if (parents.size() > 0)
+ dynObj = m_MetaData.GetDynamicObjectByInstance(parents[0]);
+ }
if (hasValue) {
- if (theImageInstance.Valid() == false)
+ bool imageInstanceCreated = false;
+ if (theImageInstance.Valid() == false) {
theImageInstance = CreateImageInstanceForMaterialOrLayer(instance, propName);
+ imageInstanceCreated = true;
+ }
if (theImageInstance) {
SetInstancePropertyValue(theImageInstance, m_Bridge.GetSourcePathProperty(),
value, inAutoDelete);
+ SetInstancePropertyValue(theImageInstance, m_Bridge.GetNameProperty(),
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(thePropertySystem
+ .GetName(propName).wide_str())));
+ if (dynObj && (g_StudioApp.IsConvertingPresentationOn()
+ || imageInstanceCreated)) {
+ // In this case we are just loading the presentation and need to convert old-style
+ // texture paths into images.
+ // Set the image defaults from the dynamic object
+ const dynamic::SPropertyDefinition *dynamicProperty
+ = findDynamicProperty(*dynObj, m_StringTable.GetRenderStringTable()
+ .RegisterStr(thePropertySystem.GetName(propName).c_str()));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_MinFilter,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_MinFilterOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_MagFilter,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_MagFilterOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TilingU,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_CoordOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TilingV,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_CoordOp))));
+ }
// Clear subpresentation value
SetInstancePropertyValue(theImageInstance,
m_Bridge.GetSceneImage().m_SubPresentation,
std::make_shared<CDataStr>(Q3DStudio::CString()),
inAutoDelete);
}
-
} else {
if (theImageInstance.Valid()) {
TSlideHandle theInstanceSlide = GetAssociatedSlide(instance);
@@ -1573,6 +1654,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);
@@ -1854,6 +1949,7 @@ public:
// Keep material names the same so that if you change the material type
// any relative path links will still work.
// Next bug is harder (keep id's the same).
+ Q3DStudio::CString fileId = GetFileId(instance);
Q3DStudio::CString theName = GetName(instance);
SLong4 theGuid = m_Bridge.GetInstanceGUID(instance);
TInstanceHandle nextChild = m_AssetGraph.GetSibling(instance, true);
@@ -1913,6 +2009,9 @@ public:
m_Bridge.GetObjectDefinitions().m_Lightmaps.m_LightmapShadow,
theLightmapShadowValue, false);
+ m_DataCore.SetInstancePropertyValue(newMaterial,
+ m_Bridge.GetObjectDefinitions().m_Asset.m_FileId,
+ std::make_shared<CDataStr>(fileId.c_str()));
SetName(newMaterial, theName, false);
m_Bridge.SetInstanceGUID(newMaterial, theGuid);
// Copy all actions from old material instance to new material instance
@@ -2125,7 +2224,8 @@ public:
}
const QFileInfo fileInfo(file);
- writeProperty(file, QStringLiteral("path"), fileInfo.absoluteFilePath());
+ writeProperty(file, QStringLiteral("path"),
+ projDir.relativeFilePath(fileInfo.absoluteFilePath()));
QMapIterator<QString, Qt3DSDMInstanceHandle> i(textureHandles);
while (i.hasNext()) {
@@ -2498,6 +2598,16 @@ public:
void copyMaterialProperties(Qt3DSDMInstanceHandle src, Qt3DSDMInstanceHandle dst) override
{
+ const EStudioObjectType matType = m_Bridge.GetObjectType(src);
+ QString materialTypeString;
+ if (matType == OBJTYPE_CUSTOMMATERIAL)
+ materialTypeString = m_Bridge.GetSourcePath(src);
+ else if (matType == OBJTYPE_MATERIAL)
+ materialTypeString = QStringLiteral("Standard Material");
+ else
+ return;
+ SetMaterialType(dst, materialTypeString);
+
const auto srcSlide = m_SlideSystem.GetApplicableSlide(src);
const auto dstSlide = m_SlideSystem.GetApplicableSlide(dst);
const auto name = GetName(dst);
@@ -3044,11 +3154,13 @@ public:
bool inGenerateUniqueName,
DocumentEditorInsertType::Enum inInsertType,
const CPt &inPosition,
+ bool preserveFileIds,
bool notifyRename = true)
{
std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
TInstanceHandleList retval = theSerializer->SerializeSceneGraphObject(
- *inReader, m_Doc.GetDocumentDirectory(), inNewRoot, GetActiveSlide(inNewRoot));
+ *inReader, m_Doc.GetDocumentDirectory(), inNewRoot, GetActiveSlide(inNewRoot),
+ preserveFileIds);
for (size_t idx = 0, end = retval.size(); idx < end; ++idx) {
qt3dsdm::Qt3DSDMInstanceHandle theInstance(retval[idx]);
if (inInsertType == DocumentEditorInsertType::NextSibling)
@@ -3067,7 +3179,8 @@ public:
TInstanceHandle inNewRoot,
bool inGenerateUniqueName,
DocumentEditorInsertType::Enum inInsertType,
- const CPt &inPosition) override
+ const CPt &inPosition,
+ bool preserveFileIds) override
{
qt3ds::QT3DSI32 theVersion = 0;
std::shared_ptr<IDOMReader> theReader = m_Doc.CreateDOMReader(
@@ -3075,13 +3188,14 @@ public:
if (!theReader)
return TInstanceHandleList();
return DoPasteSceneGraphObject(theReader, inNewRoot, inGenerateUniqueName, inInsertType,
- inPosition, false);
+ inPosition, preserveFileIds, false);
}
virtual TInstanceHandleList
PasteSceneGraphObjectMaster(const CFilePath &inFilePath, TInstanceHandle inNewRoot,
bool inGenerateUniqueName,
- DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition) override
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition,
+ bool preserveFileIds) override
{
qt3ds::QT3DSI32 theVersion = 0;
std::shared_ptr<IDOMReader> theReader = m_Doc.CreateDOMReader(
@@ -3092,7 +3206,8 @@ public:
std::shared_ptr<IComposerSerializer> theSerializer = m_Doc.CreateSerializer();
TInstanceHandleList retval = theSerializer->SerializeSceneGraphObject(
*theReader, m_Doc.GetDocumentDirectory(), inNewRoot,
- m_Doc.GetStudioSystem()->GetSlideSystem()->GetMasterSlide(GetActiveSlide(inNewRoot)));
+ m_Doc.GetStudioSystem()->GetSlideSystem()->GetMasterSlide(GetActiveSlide(inNewRoot)),
+ preserveFileIds);
for (size_t idx = 0, end = retval.size(); idx < end; ++idx) {
qt3dsdm::Qt3DSDMInstanceHandle theInstance(retval[idx]);
if (inInsertType == DocumentEditorInsertType::NextSibling)
@@ -3297,7 +3412,7 @@ public:
// Paste into the master slide of the new component
TInstanceHandleList insertedHandles = theSerializer->SerializeSceneGraphObject(
*theReader,m_Doc.GetDocumentDirectory(), component,
- m_SlideSystem.GetMasterSlide(theComponentSlide));
+ m_SlideSystem.GetMasterSlide(theComponentSlide), true);
// Restore the original time range for all objects.
if (insertedHandles.size()) {
@@ -3322,19 +3437,10 @@ public:
if (oldType == "ReferencedMaterial") {
Qt3DSDMInstanceHandle refMaterial = m_Bridge.getMaterialReference(instance);
- if (refMaterial.Valid()) {
- const Q3DStudio::CString refType = GetObjectTypeName(refMaterial);
- QString v;
- if (refType == "CustomMaterial")
- v = m_Bridge.GetSourcePath(refMaterial);
- else
- v = QStringLiteral("Standard Material");
-
- SetMaterialType(instance, v);
+ if (refMaterial.Valid())
copyMaterialProperties(refMaterial, instance);
- } else {
+ else
SetMaterialType(instance, QStringLiteral("Standard Material"));
- }
const auto name = GetName(instance);
if (!name.toQString().endsWith(QLatin1String("_animatable")))
@@ -3380,7 +3486,7 @@ public:
theSerializer->SerializeSceneGraphObject(
*theReader, m_Doc.GetDocumentDirectory(),
targetComponent,
- m_SlideSystem.GetMasterSlide(theComponentSlide));
+ m_SlideSystem.GetMasterSlide(theComponentSlide), true);
if (insertedHandles.size()) {
// Restore the original time range for all objects.
@@ -3425,7 +3531,7 @@ public:
{
qt3dsdm::TInstanceHandleList theInstances(ToGraphOrdering(inInstances));
std::shared_ptr<IDOMReader> theReader(CopySceneGraphObjectsToMemory(theInstances));
- return DoPasteSceneGraphObject(theReader, inDest, true, inInsertType, CPt(), false);
+ return DoPasteSceneGraphObject(theReader, inDest, true, inInsertType, CPt(), false, false);
}
Qt3DSDMActionHandle AddAction(Qt3DSDMSlideHandle inSlide, Qt3DSDMInstanceHandle inOwner,
@@ -3559,6 +3665,8 @@ public:
int newSlideIndex = m_SlideSystem.GetSlideIndex(theNewSlide);
m_SlideSystem.SetActiveSlide(inMasterSlide, newSlideIndex);
m_Doc.NotifyActiveSlideChanged(theNewSlide, true);
+ // Make sure layer is reseted
+ m_Doc.SetActiveLayer(0);
CheckSlideGroupPlayThroughTo(theNewSlide);
Qt3DSDMInstanceHandle theInstance = m_Doc.GetSelectedInstance();
if (theInstance.Valid() && GetAssociatedSlide(theInstance) != inMasterSlide)
@@ -3622,6 +3730,18 @@ public:
m_Bridge.GetObjectDefinitions().m_Named.m_NameProp,
std::make_shared<CDataStr>(theNewName.c_str()));
+ // Change non-masterslide instance names to unique.
+ TInstanceHandleList slideInstances;
+ m_SlideSystem.GetAssociatedInstances(theNewSlide, slideInstances);
+ for (size_t idx = 0, end = slideInstances.size(); idx < end; ++idx) {
+ TInstanceHandle theInstance(slideInstances[idx]);
+ if (m_SlideSystem.GetApplicableSlide(theInstance)
+ != m_SlideSystem.GetMasterSlide(theInstance)
+ && !m_Bridge.GetName(theInstance).IsEmpty()) {
+ SetName(theInstance, m_Bridge.GetName(theInstance), true);
+ }
+ }
+
// Ensure the active slide change gets recorded in the transaction system so that
// undo will place us back at the old slide before things start reading from the object
// model.
@@ -3630,6 +3750,8 @@ public:
m_Doc.SetActiveSlideWithTransaction(theNewSlide);
m_Doc.NotifyActiveSlideChanged(theNewSlide, true);
+ // Make sure layer is reseted
+ m_Doc.SetActiveLayer(0);
CheckSlideGroupPlayThroughTo(theNewSlide);
return theNewSlide;
}
@@ -4054,18 +4176,6 @@ public:
inStartTime == -1);
}
- static void *l_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
- {
- Q_UNUSED(ud)
- Q_UNUSED(osize)
-
- if (nsize == 0) {
- free(ptr);
- return nullptr;
- } else
- return realloc(ptr, nsize);
- }
-
QString LoadScriptFile(const CFilePath &inFile)
{
QString retval;
@@ -4142,12 +4252,25 @@ public:
theHandler->DisplayImportFailed(inSrcPath, resultDialogStr, true);
}
+ template <typename T>
+ const wchar_t *MapEnum(T enumValue) {
+ SEnumNameMap *map = SEnumParseMap<T>::GetMap();
+ while (map->m_Enum != -1) {
+ if (map->m_Enum == enumValue)
+ return map->m_WideName;
+ map = map + 1;
+ }
+ return nullptr;
+ }
+
// Apply meta data to a new dynamic instance. This sets up the default properties to
// be what the meta data specifies.
void ApplyDynamicMetaData(Qt3DSDMInstanceHandle inDynamicInstance,
- Qt3DSDMInstanceHandle inDynamic)
+ Qt3DSDMInstanceHandle inDynamic,
+ const SMetaDataDynamicObject &dynObj)
{
std::vector<SMetaDataLoadWarning> theWarnings;
+
// For all of the object std::ref properties, check if they have an absolute path
// reference (path starts with "Scene". If they do, then attempt to resolve the reference.
vector<Qt3DSDMMetaDataPropertyHandle> theProperties;
@@ -4217,6 +4340,62 @@ public:
m_DataCore.SetInstancePropertyValue(inDynamic, theInfo.m_Property, theRef);
}
}
+ } else if (theInfo.m_CompleteType == CompleteMetaDataType::Texture
+ && GetValueType(theInfo.m_DefaultValue) == DataModelDataType::String) {
+ SValue value;
+ m_DataCore.GetInstancePropertyValue(inDynamic, theInfo.m_Property, value);
+ // Set default value to the instance
+ if (!value.empty()) {
+ TDataStrPtr theImageSourcePath = get<TDataStrPtr>(value);
+ bool hasValue = theImageSourcePath && theImageSourcePath->GetLength() > 0;
+ qt3dsdm::Qt3DSDMInstanceHandle theImageInstance =
+ GetImageInstanceForProperty(inDynamicInstance, theInfo.m_Property);
+ const dynamic::SPropertyDefinition *dynamicProperty
+ = findDynamicProperty(dynObj, m_StringTable.GetRenderStringTable().
+ RegisterStr(theInfo.m_Name.wide_str()));
+ if (hasValue || (dynamicProperty && dynamicProperty->m_ImagePath.IsValid())) {
+ if (!theImageInstance.Valid()) {
+ theImageInstance = CreateImageInstanceForMaterialOrLayer(
+ inDynamicInstance, theInfo.m_Property);
+ if (dynamicProperty) {
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_MinFilter,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_MinFilterOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_MagFilter,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_MagFilterOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TilingU,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_CoordOp))));
+ m_PropertySystem.SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetObjectDefinitions().m_Image.m_TilingV,
+ std::make_shared<CDataStr>(
+ Q3DStudio::CString(MapEnum(dynamicProperty->m_CoordOp))));
+ if (!hasValue) {
+ value = std::make_shared<CDataStr>(
+ Q3DStudio::CString(dynamicProperty->m_ImagePath.c_str()));
+ }
+ }
+ }
+ if (theImageInstance) {
+ SetInstancePropertyValue(theImageInstance, m_Bridge.GetNameProperty(),
+ std::make_shared<CDataStr>(Q3DStudio::CString(
+ m_PropertySystem.GetName(theInfo.m_Property).wide_str())));
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetSourcePathProperty(), value);
+ // Clear subpresentation value
+ SetInstancePropertyValue(theImageInstance,
+ m_Bridge.GetSceneImage().m_SubPresentation,
+ make_shared<CDataStr>(Q3DStudio::CString()));
+ }
+ } else {
+ m_DataCore.SetInstancePropertyValue(inDynamicInstance, theInfo.m_Property,
+ make_shared<CDataStr>(Q3DStudio::CString()));
+ }
+ }
}
}
}
@@ -4284,11 +4463,12 @@ public:
}
}
if (theParentInstance.Valid()) {
+ SMetaDataDynamicObject dynObj;
TInstanceHandle retval(IDocumentEditor::CreateSceneGraphInstance(
theParentInstance, inParent, inSlide, m_DataCore, m_SlideSystem,
m_Bridge.GetObjectDefinitions(), m_AssetGraph, m_MetaData));
- ApplyDynamicMetaData(retval, theParentInstance);
+ ApplyDynamicMetaData(retval, theParentInstance, dynObj);
if (inStartTime != -1)
SetStartTime(retval, inStartTime);
@@ -4483,7 +4663,6 @@ public:
if (theRelativePath.toCString() == GetSourcePath(existing[idx]))
theParentInstance = existing[idx];
}
-
if (theParentInstance.Valid() == false) {
if (theShaderFile.Exists()) {
theParentInstance = m_DataCore.CreateInstance();
@@ -4508,18 +4687,31 @@ public:
IDocumentEditor::fixDefaultTexturePaths(theParentInstance);
DisplayLoadWarnings(shaderFile, theWarnings, QString());
} else {
- if (theHandler)
+ if (theHandler) {
theHandler->DisplayImportFailed(theShaderFile.toQString(),
QObject::tr("Unable to load Shader File"),
false);
+ }
return 0;
}
}
+ const SMetaDataDynamicObject *dynObj;
+ dynObj = m_MetaData.GetDynamicObjectByInstance(theParentInstance);
+ if (!dynObj) {
+ if (theHandler) {
+ theHandler->DisplayImportFailed(theShaderFile.toQString(),
+ QObject::tr("Unable to load Shader File"),
+ false);
+ }
+ return 0;
+ }
TInstanceHandle retval(IDocumentEditor::CreateSceneGraphInstance(
theParentInstance, inParent, inSlide, m_DataCore, m_SlideSystem,
m_Bridge.GetObjectDefinitions(), m_AssetGraph, m_MetaData, inTargetId));
+ ApplyDynamicMetaData(retval, theParentInstance, *dynObj);
+
if (inStartTime != -1)
SetStartTime(retval, inStartTime);
@@ -5165,6 +5357,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()) {
@@ -5173,7 +5367,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);
}
}
}
@@ -5388,26 +5596,28 @@ public:
} else if (CDialogs::effectExtensions().contains(theExtension)
&& theRecord.m_ModificationType != FileModificationType::Created
&& !theInstances.empty()) {
- CString theNameStr = GetName(theInstances[0].second);
std::vector<SMetaDataLoadWarning> theWarnings;
NVScopedRefCounted<qt3ds::render::IRefCountedInputStream> theStream(
m_InputStreamFactory->GetStreamForFile(theRecord.m_File.toQString()));
if (theStream) {
- m_MetaData.LoadEffectInstance(m_StringTable.GetNarrowStr(theRelativePath.toCString()),
+ m_MetaData.LoadEffectInstance(m_StringTable.GetNarrowStr(
+ theRelativePath.toCString()),
theInstances[0].second,
- TCharStr(theNameStr),
+ theRelativePath.GetFileStem().c_str(),
theWarnings, *theStream);
IDocumentEditor::fixDefaultTexturePaths(theInstances[0].second);
}
+ QList<qt3dsdm::Qt3DSDMInstanceHandle> insts;
for (size_t i = 0; i < theInstances.size(); ++i) {
theDispatch.FireReloadEffectInstance(theInstances[i].second);
- theDispatch.FireImmediateRefreshInstance(theInstances[i].second);
+ insts.append(theInstances[i].second);
}
+ theDispatch.FireImmediateRefreshInstance(&insts[0], theInstances.size());
+
} else if (CDialogs::shaderExtensions().contains(theExtension)
&& theRecord.m_ModificationType != FileModificationType::Created
&& !theInstances.empty()) {
- CString theNameStr = GetName(theInstances[0].second);
std::vector<SMetaDataLoadWarning> theWarnings;
NVScopedRefCounted<qt3ds::render::IRefCountedInputStream> theStream(
m_InputStreamFactory->GetStreamForFile(theRecord.m_File.toQString()));
@@ -5415,7 +5625,7 @@ public:
m_MetaData.LoadMaterialInstance(m_StringTable.GetNarrowStr(
theRelativePath.toCString()),
theInstances[0].second,
- TCharStr(theNameStr),
+ theRelativePath.GetFileStem().c_str(),
theWarnings,
*theStream);
IDocumentEditor::fixDefaultTexturePaths(theInstances[0].second);
@@ -5435,17 +5645,22 @@ public:
}
- if (!imageLoadSet.isEmpty())
- m_Doc.GetBufferCache().reloadImageSet(imageLoadSet);
+ if (!imageLoadSet.isEmpty()) {
+ auto settings = m_Doc.GetCore()->GetStudioProjectSettings();
+ m_Doc.GetBufferCache().reloadImageSet(
+ IBufferManager::resolveImageSet(imageLoadSet,
+ settings->getPreferCompressedTextures()),
+ settings->getFlipCompressedTextures());
+ }
g_StudioApp.getRenderer().ReleaseContext();
if (hasProgressFired)
theDispatch.FireOnProgressEnd();
- if (requestRender && m_Doc.GetSceneGraph())
- m_Doc.GetSceneGraph()->RequestRender();
if (hasDispatchNotificationScope)
theDispatch.FireEndDataModelNotifications();
+ if (requestRender && m_Doc.GetSceneGraph())
+ m_Doc.GetSceneGraph()->RenderNow();
}
};
}
@@ -5542,16 +5757,17 @@ void IDocumentEditor::fixDefaultTexturePaths(Qt3DSDMInstanceHandle instance)
= propertySystem->GetAdditionalMetaDataType(instance, prop);
if (additionalMetaDataType == AdditionalMetaDataType::Texture) {
propertySystem->GetInstancePropertyValue(instance, prop, value);
- TDataStrPtr strPtr = get<TDataStrPtr>(value);
- const QString strValue = QString::fromWCharArray(strPtr->GetData());
- const QString docRelative = docDir.relativeFilePath(strValue);
- const QString projRelative = projDir.relativeFilePath(strValue);
- if (!QFileInfo(docRelative).exists() && !QFileInfo(projRelative).exists()) {
- // Convert path to presentation relative
- const QVariant newVarValue = QVariant::fromValue(
- docDir.relativeFilePath(projDir.absoluteFilePath(strValue)));
- const SValue newValue = newVarValue;
- propertySystem->SetInstancePropertyValue(instance, prop, newValue);
+ if (value.getType() == DataModelDataType::String) {
+ TDataStrPtr strPtr = get<TDataStrPtr>(value);
+ const QString strValue = QString::fromWCharArray(strPtr->GetData());
+ const QString docRelative = docDir.relativeFilePath(strValue);
+ if (!QFileInfo(docDir.filePath(docRelative)).exists()) {
+ // Convert path to presentation relative
+ const QVariant newVarValue = QVariant::fromValue(
+ docDir.relativeFilePath(projDir.absoluteFilePath(strValue)));
+ const SValue newValue = newVarValue;
+ propertySystem->SetInstancePropertyValue(instance, prop, newValue);
+ }
}
}
}
@@ -5595,6 +5811,11 @@ Qt3DSDMInstanceHandle IDocumentEditor::CreateSceneGraphInstance(
TInstanceHandle theDerivationParent(inMaster);
inDataCore.DeriveInstance(retval, theDerivationParent);
+ // Clear file id derived from the parent
+ // This happens for custom shaders and causes id conflicts (QT3DS-4018)
+ inDataCore.SetInstancePropertyValue(retval, inObjectDefs.m_Asset.m_FileId,
+ std::make_shared<CDataStr>(L""));
+
if (inParent.Valid())
inAssetGraph.AddChild(inParent, retval);
else
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
index c62d3fa1..d3355260 100644
--- a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.cpp
@@ -48,8 +48,11 @@
#include "Qt3DSRenderPathManager.h"
#include "Qt3DSDMGuides.h"
#include "foundation/Qt3DSLogging.h"
+#include "Qt3DSRenderDynamicObjectSystem.h"
+
#include <unordered_map>
#include <unordered_set>
+
#include <QtCore/qrandom.h>
#include <QtCore/qdatetime.h>
@@ -635,7 +638,6 @@ struct SComposerSerializerImpl : public IComposerSerializer
stem.toWCharArray(reinterpret_cast<wchar_t *>(warr.data()));
return m_StringTable.RegisterStr(reinterpret_cast<wchar_t *>(warr.data()));
}
- stem = stem.left(pos);
}
// Create an ID for this instance
@@ -976,9 +978,15 @@ struct SComposerSerializerImpl : public IComposerSerializer
} else {
m_TempBuffer.clear();
WCharTWriter theWriter(m_TempBuffer);
- WStrOps<SValue>().ToBuf(theValue, theWriter);
-
- if (GetValueType(theValue) == DataModelDataType::String || m_TempBuffer.size()) {
+ if (theValueType == DataModelDataType::String || !theValue.empty()) {
+ // QT3DS-3993: store line feeds as replacement chars in UIP
+ if (theValueType == DataModelDataType::String) {
+ TDataStrPtr strPtr = get<TDataStrPtr>(theValue);
+ auto strValue = QString::fromWCharArray(strPtr->GetData());
+ strValue.replace("\n", LINE_BREAK_SUBSTITUTE);
+ theValue = std::make_shared<CDataStr>(CString::fromQString(strValue));
+ }
+ WStrOps<SValue>().ToBuf(theValue, theWriter);
char buffer[] = { 0, 0, 0, 0 };
m_TempBuffer.write(buffer, 4);
theValueStr.assign((const wchar_t *)m_TempBuffer.begin());
@@ -1007,8 +1015,13 @@ struct SComposerSerializerImpl : public IComposerSerializer
return SStringOrInt(std::make_shared<CDataStr>(inValue));
}
- if (inType == DataModelDataType::String)
- return std::make_shared<CDataStr>(inValue);
+ if (inType == DataModelDataType::String) {
+ // QT3DS-3993: store line feeds as replacement chars in UIP
+ auto valueStr = std::make_shared<CDataStr>(inValue);
+ auto val = QString::fromStdWString(valueStr->GetData());
+ val.replace(LINE_BREAK_SUBSTITUTE, "\n");
+ return std::make_shared<CDataStr>(CString::fromQString(val));
+ }
qt3ds::foundation::ConvertUTF(
reinterpret_cast<const qt3ds::foundation::TWCharEASTLConverter::TCharType *>(inValue), 0,
@@ -1058,6 +1071,19 @@ struct SComposerSerializerImpl : public IComposerSerializer
}
}
+ SLong4 ParseGUID(TCharPtr inValue)
+ {
+ // One of two things, either an ID reference *or* pure string.
+ if (IsTrivial(inValue))
+ return SLong4();
+ if (inValue[0] == '#') {
+ // absolute reference.
+ Qt3DSDMInstanceHandle theInstance = GetInstanceById(inValue + 1);
+ return theInstance.Valid() ? GetInstanceGuid(theInstance) : SLong4();
+ }
+ return SLong4();
+ }
+
void SerializePropertyList(qt3dsdm::IDOMWriter &inWriter, TPropertyHandleValuePairList &inList)
{
sort(inList.begin(), inList.end(), SAttributeNameSorter(m_DataCore));
@@ -1624,7 +1650,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
}
void ParseInstanceProperties(IDOMReader &inReader, Qt3DSDMInstanceHandle inInstance,
- vector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
+ QVector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
TPropertyHandleValuePairList &outProperties)
{
bool hasNoLifetime =
@@ -1651,7 +1677,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
void ParseAndSetInstanceProperties(IDOMReader &inReader, Qt3DSDMSlideHandle inSlide,
Qt3DSDMInstanceHandle inInstance,
- vector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
+ QVector<pair<TCharPtr, TCharPtr>> &outExtraAttributes,
TPropertyHandleValuePairList &ioProperties)
{
outExtraAttributes.clear();
@@ -1665,13 +1691,28 @@ struct SComposerSerializerImpl : public IComposerSerializer
// is to preserve behavior on old presentations that relied on hardcoding.
bool hasMappingAsProbe = false;
bool hasTilingH = false;
+ bool isDynamicObjectInstance
+ = m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_CustomMaterial.m_Instance)
+ || m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Effect.m_Instance);
for (size_t idx = 0, end = ioProperties.size(); idx < end; ++idx) {
+ auto &prop = ioProperties[idx];
if (ioProperties[idx].first == m_ObjectDefinitions.m_Image.m_TilingU)
hasTilingH = true;
if (ioProperties[idx].first == m_ObjectDefinitions.m_Image.m_TextureMapping
&& ioProperties[idx].second.toQVariant() == QVariant("Light Probe")) {
hasMappingAsProbe = true;
}
+ if (prop.second.getType() == qt3dsdm::DataModelDataType::String
+ && isDynamicObjectInstance) {
+ qt3dsdm::TDataStrPtr value = qt3dsdm::get<qt3dsdm::TDataStrPtr>(prop.second);
+ QString string = QString::fromWCharArray(value->GetData());
+ if (string.startsWith(QLatin1Char('#'))) {
+ SLong4 guid = ParseGUID(value->GetData());
+ prop.second = SValue(guid);
+ }
+ }
}
if (!hasTilingH && hasMappingAsProbe) {
@@ -1791,6 +1832,34 @@ struct SComposerSerializerImpl : public IComposerSerializer
// Write out the properties for the active slide.
TPropertyHandleValuePairList theValues;
GetSpecificInstancePropertyValues(inInstance, theValues);
+ bool isDynamicObjectInstance
+ = m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_CustomMaterial.m_Instance)
+ || m_DataCore.IsInstanceOrDerivedFrom(inInstance,
+ m_ObjectDefinitions.m_Effect.m_Instance);
+
+ if (isDynamicObjectInstance) {
+ // Remove default string values from serialized values
+ TInstanceHandleList parents;
+ m_DataCore.GetInstanceParents(inInstance, parents);
+ SMetaDataDynamicObject *dynObj = m_MetaData.GetDynamicObjectByInstance(parents[0]);
+ if (!dynObj)
+ return false;
+ for (int i = 0; i < dynObj->m_Properties.size(); i++) {
+ auto &prop = dynObj->m_Properties[i];
+ for (auto iter = theValues.begin(); iter != theValues.end(); iter++) {
+ const pair<Qt3DSDMPropertyHandle, SValue> &theValue(*iter);
+ TCharStr theName(m_DataCore.GetProperty(theValue.first).m_Name);
+ CRegisteredString name = m_StringTable.GetRenderStringTable()
+ .RegisterStr(theName.c_str());
+ if (name == prop.m_Name && prop.m_DataType
+ == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ theValues.erase(iter);
+ break;
+ }
+ }
+ }
+ }
SerializePropertyList(inWriter, theValues);
if (theMasterRef.size())
@@ -1921,7 +1990,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
}
TPropertyHandleValuePairList theValues;
- vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ QVector<pair<TCharPtr, TCharPtr>> theExtraAtts;
ParseAndSetInstanceProperties(inReader, 0, theNewInstance, theExtraAtts, theValues);
ReadInstanceProperties(inReader);
@@ -2244,7 +2313,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
{
IDOMReader::Scope __stateScope(inReader);
TPropertyHandleValuePairList theValues;
- vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ QVector<pair<TCharPtr, TCharPtr>> theExtraAtts;
ParseAndSetInstanceProperties(inReader, 0, m_SlideCore.GetSlideInstance(inSlide),
theExtraAtts, theValues);
// Slides require a two-pass parsing system because slides can refer to each other via id.
@@ -2520,7 +2589,8 @@ struct SComposerSerializerImpl : public IComposerSerializer
}
void DoSerializeScene(IDOMWriter &inWriter, const Qt3DSDMInstanceHandle *inTopInstances,
- QT3DSU32 inCount, bool inWriteParentRefs = false)
+ QT3DSU32 inCount, bool inWriteParentRefs = false,
+ const Q3DStudio::CFilePath *inDocumentDirectory = nullptr)
{
GetAllInstanceGuids();
{
@@ -2546,15 +2616,27 @@ struct SComposerSerializerImpl : public IComposerSerializer
QT3DS_ASSERT(false);
continue;
}
- IDOMWriter::Scope instScope(inWriter, theType->wide_str());
- inWriter.Att(L"id", GetInstanceId(theMaster));
- // Write out all the properties that are on the instance but are not on *this*
- // instance in the meta data.
- TPropertyHandleValuePairList theProperties;
- GetSpecificInstancePropertyValues(theMaster, theProperties);
- erase_if(theProperties,
- SMetaDataPropertyEraser(theMaster, m_ObjectDefinitions));
- SerializePropertyList(inWriter, theProperties);
+ SValue value;
+ m_DataCore.GetInstancePropertyValue(theMaster,
+ m_ObjectDefinitions.m_Asset.m_SourcePath,
+ value);
+ if (!value.empty()) {
+ CFilePath sourcePath(value.getData<qt3dsdm::TDataStrPtr>()->GetData());
+ CFilePath theFullPath = CFilePath::CombineBaseAndRelative(
+ (inDocumentDirectory ? (*inDocumentDirectory) : CFilePath()),
+ sourcePath);
+ if (!inDocumentDirectory || theFullPath.Exists()) {
+ IDOMWriter::Scope instScope(inWriter, theType->wide_str());
+ inWriter.Att(L"id", GetInstanceId(theMaster));
+ // Write out all the properties that are on the instance but are not on *this*
+ // instance in the meta data.
+ TPropertyHandleValuePairList theProperties;
+ GetSpecificInstancePropertyValues(theMaster, theProperties);
+ erase_if(theProperties,
+ SMetaDataPropertyEraser(theMaster, m_ObjectDefinitions));
+ SerializePropertyList(inWriter, theProperties);
+ }
+ }
}
}
inWriter.MoveBefore(L"Classes", L"Graph");
@@ -2652,7 +2734,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
theMaster = m_DataCore.CreateInstance();
m_DataCore.DeriveInstance(theMaster, theCanonicalType);
TPropertyHandleValuePairList theValues;
- vector<pair<TCharPtr, TCharPtr>> theExtraAtts;
+ QVector<pair<TCharPtr, TCharPtr>> theExtraAtts;
m_SourcePathToMasterInstances.insert(
make_pair(m_StringTable.RegisterStr(theSourcePath), theMaster));
@@ -2811,7 +2893,8 @@ struct SComposerSerializerImpl : public IComposerSerializer
}
};
- void SerializeScene(IDOMWriter &inWriter) override
+ void SerializeScene(IDOMWriter &inWriter,
+ const Q3DStudio::CFilePath &inDocumentDirectory) override
{
reset();
ScopedPreserveFileIds __preserveFileIds(m_PreserveFileIds);
@@ -2825,7 +2908,7 @@ struct SComposerSerializerImpl : public IComposerSerializer
if (theGraphRoots.empty())
return;
QT3DS_ASSERT(theGraphRoots.size() == 1);
- DoSerializeScene(inWriter, &theGraphRoots[0], 1);
+ DoSerializeScene(inWriter, &theGraphRoots[0], 1, false, &inDocumentDirectory);
TGuideHandleList theGuides = m_GuideSystem.GetAllGuides();
// sort the guides by handle value to keep the file as stable as possible.
std::sort(theGuides.begin(), theGuides.end());
@@ -2870,26 +2953,28 @@ struct SComposerSerializerImpl : public IComposerSerializer
// new root.
virtual qt3dsdm::TInstanceHandleList
SerializeSceneGraphObject(IDOMReader &inReader, const CFilePath &inDocumentDirectory,
- Qt3DSDMInstanceHandle inNewRoot, Qt3DSDMSlideHandle inActiveSlide) override
+ Qt3DSDMInstanceHandle inNewRoot, Qt3DSDMSlideHandle inActiveSlide,
+ bool preserveFileIds) override
{
reset();
m_ActiveSlide = inActiveSlide;
- m_PreserveFileIds = false;
+ m_PreserveFileIds = preserveFileIds;
return DoSerializeScene(inReader, inDocumentDirectory, inNewRoot);
}
// Write this instance and its children (and possibly its slides) to a writer.
// Equivalent to the older partial serialization system
void SerializeSceneGraphObjects(IDOMWriter &inWriter,
- const TInstanceHandleList &inInstances,
- Qt3DSDMSlideHandle inActiveSlide) override
+ const TInstanceHandleList &inInstances,
+ Qt3DSDMSlideHandle inActiveSlide,
+ bool preserveFileIds) override
{
if (inInstances.empty())
return;
reset();
QT3DS_ASSERT(inActiveSlide.Valid());
m_ActiveSlide = inActiveSlide;
- m_PreserveFileIds = false;
+ m_PreserveFileIds = preserveFileIds;
// It is fine if the parent is invalid
m_ActiveSlideParent = m_SlideCore.GetParentSlide(m_ActiveSlide);
DoSerializeScene(inWriter, inInstances.data(), (QT3DSU32)inInstances.size());
diff --git a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h
index e2882cb8..b7e5ed96 100644
--- a/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h
+++ b/src/Authoring/Client/Code/Core/Doc/IComposerSerializer.h
@@ -65,7 +65,8 @@ protected:
virtual ~IComposerSerializer() {}
public:
// Empty graph roots means use the actual graph roots in the asset graph
- virtual void SerializeScene(qt3dsdm::IDOMWriter &inWriter) = 0;
+ virtual void SerializeScene(qt3dsdm::IDOMWriter &inWriter,
+ const Q3DStudio::CFilePath &inDocumentDirectory) = 0;
// Write properties into the active slide until we get to a slide owner, then create new slides.
// inActiveSlide may be zero if the top item we find happens to be a scene or a component.
// The graph roots hold the top items
@@ -77,13 +78,15 @@ public:
// Equivalent to the older partial serialization system
virtual void SerializeSceneGraphObjects(qt3dsdm::IDOMWriter &inWriter,
const qt3dsdm::TInstanceHandleList &inInstances,
- qt3dsdm::Qt3DSDMSlideHandle inActiveSlide) = 0;
+ qt3dsdm::Qt3DSDMSlideHandle inActiveSlide,
+ bool preserveFileIds) = 0;
// Read a partial serialization into this slide, attaching the instance as the last child of the
// new root.
virtual qt3dsdm::TInstanceHandleList SerializeSceneGraphObject(
qt3dsdm::IDOMReader &inReader, const Q3DStudio::CFilePath &inDocumentDirectory,
- qt3dsdm::Qt3DSDMInstanceHandle inNewRoot, qt3dsdm::Qt3DSDMSlideHandle inActiveSlide) = 0;
+ qt3dsdm::Qt3DSDMInstanceHandle inNewRoot, qt3dsdm::Qt3DSDMSlideHandle inActiveSlide,
+ bool preserveFileIds) = 0;
// Save and load just a single action
virtual void SerializeAction(qt3dsdm::IDOMWriter &inWriter, qt3dsdm::Qt3DSDMSlideHandle inSlide,
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h b/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h
index 4043e864..1bebfedf 100644
--- a/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h
+++ b/src/Authoring/Client/Code/Core/Doc/IDocSceneGraph.h
@@ -63,6 +63,7 @@ public:
// Request that this object renders. May be ignored if a transaction
// is ongoing so we don't get multiple rendering per transaction.
virtual void RequestRender() = 0;
+ virtual void RenderNow() = 0;
};
}
#endif
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h b/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h
index 54e320e9..13616aee 100644
--- a/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentBufferCache.h
@@ -96,7 +96,9 @@ public:
// Takes a *relative* path from the document
virtual void InvalidateBuffer(const CFilePath &inSourcePath) = 0;
- virtual void reloadImageSet(const QSet<QString> &imageSet) = 0;
+ virtual void reloadImageSet(const QSet<QString> &imageSet, bool flipCompressedTextures) = 0;
+
+ virtual void reloadAll(bool flipCompressedTextures) = 0;
// Don't send events but just clear everything out. Used on document::close
virtual void Clear() = 0;
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
index da11238e..14fcd5fb 100644
--- a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h
@@ -322,11 +322,13 @@ public:
virtual qt3dsdm::TInstanceHandleList
PasteSceneGraphObject(const CFilePath &inFilePath, Qt3DSDMInstanceHandle inNewRoot,
bool inGenerateUniqueName, DocumentEditorInsertType::Enum inInsertType,
- const CPt &inPosition) = 0;
+ const CPt &inPosition,
+ bool preserveFileIds) = 0;
virtual qt3dsdm::TInstanceHandleList PasteSceneGraphObjectMaster(
const CFilePath &inFilePath, Qt3DSDMInstanceHandle inNewRoot, bool inGenerateUniqueName,
- DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition) = 0;
+ DocumentEditorInsertType::Enum inInsertType, const CPt &inPosition,
+ bool preserveFileIds) = 0;
virtual void RearrangeObjects(const qt3dsdm::TInstanceHandleList &inInstances,
TInstanceHandle inDest,
diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h b/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h
index c455e802..be2f739a 100644
--- a/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h
+++ b/src/Authoring/Client/Code/Core/Doc/IDocumentReader.h
@@ -215,13 +215,14 @@ public:
// Given the active slide on the document (which we query) and an instance,
// produce a temporary file (Qt3DSFile::GetTemporaryFile) and serialize this object
// to that temporary file.
- virtual CFilePath CopySceneGraphObjects(qt3dsdm::TInstanceHandleList inInstances) = 0;
+ virtual CFilePath CopySceneGraphObjects(qt3dsdm::TInstanceHandleList inInstances,
+ bool preserveFileIds) = 0;
- CFilePath CopySceneGraphObject(Qt3DSDMInstanceHandle inInstance)
+ CFilePath CopySceneGraphObject(Qt3DSDMInstanceHandle inInstance, bool preserveFileIds)
{
qt3dsdm::TInstanceHandleList theInstances;
theInstances.push_back(inInstance);
- return CopySceneGraphObjects(theInstances);
+ return CopySceneGraphObjects(theInstances, preserveFileIds);
}
// Copy the object just to a DOM representation, don't serialize to file.
@@ -278,6 +279,8 @@ inline EStudioObjectType GetStudioObjectType(qt3dsdm::ComposerObjectTypes::Enum
return OBJTYPE_MODEL;
case ComposerObjectTypes::Group:
return OBJTYPE_GROUP;
+ case ComposerObjectTypes::Signal:
+ return OBJTYPE_SIGNAL;
case ComposerObjectTypes::Image:
return OBJTYPE_IMAGE;
case ComposerObjectTypes::Text:
diff --git a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp
index be88d448..3a2f625e 100644
--- a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp
+++ b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.cpp
@@ -72,6 +72,7 @@ void CStudioProjectSettings::reset()
m_maintainAspect = false;
m_rotatePresentation = false;
m_preferCompressedTextures = false;
+ m_flipCompressedTextures = false;
}
//==============================================================================
@@ -146,3 +147,11 @@ void CStudioProjectSettings::setPreferCompressedTextures(bool inFlag)
m_core->GetDoc()->SetModifiedFlag();
}
}
+
+void CStudioProjectSettings::setFlipCompressedTextures(bool inFlag)
+{
+ if (m_flipCompressedTextures != inFlag) {
+ m_flipCompressedTextures = inFlag;
+ m_core->GetDoc()->SetModifiedFlag();
+ }
+}
diff --git a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h
index 4fe476a9..2f86eac0 100644
--- a/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h
+++ b/src/Authoring/Client/Code/Core/Doc/StudioProjectSettings.h
@@ -61,6 +61,9 @@ public:
bool getPreferCompressedTextures() const { return m_preferCompressedTextures; }
void setPreferCompressedTextures(bool inFlag);
+ bool getFlipCompressedTextures() const { return m_flipCompressedTextures; }
+ void setFlipCompressedTextures(bool inFlag);
+
void reset();
protected:
@@ -71,6 +74,7 @@ protected:
bool m_maintainAspect;
bool m_rotatePresentation;
bool m_preferCompressedTextures;
+ bool m_flipCompressedTextures;
CCore *m_core;
};
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp
index 121bd747..c02d2e99 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp
+++ b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.cpp
@@ -58,6 +58,7 @@ bool CStudioObjectTypes::AcceptableParent(EStudioObjectType inChild, EStudioObje
case OBJTYPE_LIGHT:
case OBJTYPE_MODEL:
case OBJTYPE_GROUP:
+ case OBJTYPE_SIGNAL:
case OBJTYPE_PATH:
case OBJTYPE_COMPONENT:
theAcceptible = (inParent == OBJTYPE_LAYER) || (inParent == OBJTYPE_CAMERA)
@@ -132,6 +133,10 @@ const QString &CStudioObjectTypes::GetNormalIconName(EStudioObjectType inType)
static QString theString = QStringLiteral("Objects-Group-Normal.png");
return theString;
}
+ case OBJTYPE_SIGNAL: {
+ static QString theString = QStringLiteral("Objects-Signal-Normal.png");
+ return theString;
+ }
case OBJTYPE_ALIAS: {
static QString theString = QStringLiteral("Objects-Alias-Normal.png");
return theString;
@@ -234,6 +239,10 @@ const QString &CStudioObjectTypes::GetDisabledIconName(EStudioObjectType inType)
static QString theString = QStringLiteral("Objects-Group-Disabled.png");
return theString;
}
+ case OBJTYPE_SIGNAL: {
+ static QString theString = QStringLiteral("Objects-Signal-Disabled.png");
+ return theString;
+ }
case OBJTYPE_ALIAS: {
static QString theString = QStringLiteral("Objects-Alias-Disabled.png");
return theString;
@@ -335,6 +344,10 @@ const QString &CStudioObjectTypes::GetHighlightIconName(EStudioObjectType inType
static QString theString = QStringLiteral("Objects-Group-Normal.png");
return theString;
}
+ case OBJTYPE_SIGNAL: {
+ static QString theString = QStringLiteral("Objects-Signal-Normal.png");
+ return theString;
+ }
case OBJTYPE_PATH: {
static QString theString = QStringLiteral("Objects-Path-Normal.png");
return theString;
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h
index 79eafc19..dc57d4c8 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h
+++ b/src/Authoring/Client/Code/Core/Utility/StudioObjectTypes.h
@@ -67,6 +67,7 @@ enum EStudioObjectType {
OBJTYPE_PROJECT = 0x02000000,
OBJTYPE_QML_STREAM = 0x04000000,
OBJTYPE_MATERIALDATA = 0x08000000,
+ OBJTYPE_SIGNAL = 0x10000000,
// filters
OBJTYPE_IS_VARIANT = OBJTYPE_LAYER | OBJTYPE_TEXT | OBJTYPE_MODEL | OBJTYPE_GROUP
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
index bde1da0c..3fe5f377 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.cpp
@@ -84,6 +84,7 @@ static QColor s_timelineFilterButtonSelectedColor;
static QColor s_timelineFilterButtonHoveredColor;
static QColor s_timelineRowCommentBgColor;
static QColor s_timelinePressedKeyframeColor; // pressed keyframe from multiple selection
+static QColor s_timelineActionColor;
static QColor s_invalidDataIndicatorColor;
static int s_fontSize;
@@ -158,6 +159,7 @@ void CStudioPreferences::loadPreferences()
s_timelineRowSubpDescendantColor = QColor("#a263ff");
s_timelineRowCommentBgColor = QColor("#d0000000");
s_timelinePressedKeyframeColor = QColor("#ffff00");
+ s_timelineActionColor = QColor("#f4be04");
s_invalidDataIndicatorColor = QColor("#ff2121");
@@ -230,16 +232,6 @@ void CStudioPreferences::resetWindowState(int version)
// Viewing settings
//
-bool CStudioPreferences::isLegacyViewerActive()
-{
- return s_preferences.value(QStringLiteral("Viewing/LegacyViewerActive"), false).toBool();
-}
-
-void CStudioPreferences::setLegacyViewerActive(bool inActive)
-{
- s_preferences.setValue(QStringLiteral("Viewing/LegacyViewerActive"), inActive);
-}
-
bool CStudioPreferences::isEditViewFillMode()
{
return s_preferences.value(QStringLiteral("Viewing/EditViewFillMode"), true).toBool();
@@ -460,6 +452,16 @@ void CStudioPreferences::setHelperGridOn(bool showGrid)
s_preferences.setValue(QStringLiteral("VisualAids/ShowHelperGrid"), showGrid);
}
+bool CStudioPreferences::isAxisHelperOn()
+{
+ return s_preferences.value(QStringLiteral("VisualAids/ShowAxisHelper"), true).toBool();
+}
+
+void CStudioPreferences::setAxisHelperOn(bool showAxisHelper)
+{
+ s_preferences.setValue(QStringLiteral("VisualAids/ShowAxisHelper"), showAxisHelper);
+}
+
int CStudioPreferences::helperGridLines()
{
return s_preferences.value(QStringLiteral("VisualAids/HelperGridLines"), 10).toInt();
@@ -594,6 +596,20 @@ void CStudioPreferences::setRecentItem(int index, const QString &path)
}
//
+// Pop-up warning settings
+//
+void CStudioPreferences::setDoNotShowImportWarnings(bool inDoNotShowImportWarnings)
+{
+ s_preferences.setValue(QStringLiteral("PopUps/DoNotShowImportWarnings"),
+ inDoNotShowImportWarnings);
+}
+
+bool CStudioPreferences::doNotShowImportWarnings()
+{
+ return s_preferences.value(QStringLiteral("PopUps/DoNotShowImportWarnings")).toBool();
+}
+
+//
// Other settings
//
void CStudioPreferences::setQmlContextProperties(QQmlContext *qml)
@@ -912,6 +928,11 @@ QColor CStudioPreferences::timelinePressedKeyframeColor()
return s_timelinePressedKeyframeColor;
}
+QColor CStudioPreferences::timelineActionColor()
+{
+ return s_timelineActionColor;
+}
+
QColor CStudioPreferences::invalidDataIndicatorColor()
{
return s_invalidDataIndicatorColor;
diff --git a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
index 490a48cc..fb0b8fae 100644
--- a/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
+++ b/src/Authoring/Client/Code/Core/Utility/StudioPreferences.h
@@ -67,9 +67,6 @@ public:
// Viewing settings
//
- static bool isLegacyViewerActive();
- static void setLegacyViewerActive(bool inActive);
-
static bool isEditViewFillMode();
static void setEditViewFillMode(bool inRenderAsSolid);
@@ -138,6 +135,9 @@ public:
static int helperGridLines();
static void setHelperGridLines(int lines);
+ static void setAxisHelperOn(bool showAxisHelper);
+ static bool isAxisHelperOn();
+
static int helperGridSpacing();
static void setHelperGridSpacing(int spacing);
@@ -178,6 +178,12 @@ public:
static void setRecentItem(int index, const QString &path);
//
+ // Pop-up warnings
+ //
+ static bool doNotShowImportWarnings();
+ static void setDoNotShowImportWarnings(bool inDoNotShowImportWarnings);
+
+ //
// Other settings
//
static void setQmlContextProperties(QQmlContext *qml);
@@ -245,6 +251,7 @@ public:
static QColor timelineRowSubpDescendantColor();
static QColor timelineRowCommentBgColor();
static QColor timelinePressedKeyframeColor();
+ static QColor timelineActionColor();
static QColor invalidDataIndicatorColor();
diff --git a/src/Authoring/Common/Code/Qt3DSMessageBox.cpp b/src/Authoring/Common/Code/Qt3DSMessageBox.cpp
index b802ab1c..0f761355 100644
--- a/src/Authoring/Common/Code/Qt3DSMessageBox.cpp
+++ b/src/Authoring/Common/Code/Qt3DSMessageBox.cpp
@@ -35,6 +35,7 @@ using namespace Q3DStudio;
#include "Qt3DSMessageBox.h"
#include <QtWidgets/qmessagebox.h>
+#include <QtWidgets/qcheckbox.h>
//==============================================================================
/**
@@ -58,12 +59,14 @@ Qt3DSMessageBox::~Qt3DSMessageBox()
* @param inTitle Title of the message box
* @param inText Text to be displayed on the message box
* @param inIcon Icon to be displayed on the message box
+ * @param inDoNotShowAgainChoice Should we show checkbox for hiding subsequent messages?
* @param inParentWindow window to attach this dialog to.
*/
Qt3DSMessageBox::EMessageBoxReturn
Qt3DSMessageBox::Show(const QString &inTitle, const QString &inText, EMessageBoxIcon inIcon,
- bool inShowCancel /*false*/,
- Qt3DSMessageBox::TPlatformWindow inParentWindow /*NULL*/)
+ bool &doNotShowAgain, bool inShowCancel /*false*/,
+ bool inDoNotShowAgainChoice /*false*/,
+ Qt3DSMessageBox::TPlatformWindow inParentWindow /*nullptr*/)
{
QMessageBox box(inParentWindow);
box.setWindowTitle(inTitle);
@@ -88,6 +91,31 @@ Qt3DSMessageBox::Show(const QString &inTitle, const QString &inText, EMessageBox
buttons |= QMessageBox::Cancel;
box.setStandardButtons(buttons);
+ if (inDoNotShowAgainChoice) {
+ QCheckBox *noShowAgain = new QCheckBox(QObject::tr("Do not show again."));
+ box.setCheckBox(noShowAgain);
+ QObject::connect(noShowAgain, &QCheckBox::stateChanged, [&doNotShowAgain](int state) {
+ doNotShowAgain = static_cast<Qt::CheckState>(state) == Qt::CheckState::Checked;
+ });
+ }
+
auto theButtonPressed = box.exec();
return theButtonPressed == QMessageBox::Ok ? MSGBX_OK : MSGBX_CANCEL;
}
+
+//==============================================================================
+/**
+ * Displays the modal message box to the user.
+ * @param inTitle Title of the message box
+ * @param inText Text to be displayed on the message box
+ * @param inIcon Icon to be displayed on the message box
+ * @param inParentWindow window to attach this dialog to.
+ */
+Qt3DSMessageBox::EMessageBoxReturn
+Qt3DSMessageBox::Show(const QString &inTitle, const QString &inText, EMessageBoxIcon inIcon,
+ bool inShowCancel /*false*/,
+ Qt3DSMessageBox::TPlatformWindow inParentWindow /*nullptr*/)
+{
+ bool dummy;
+ return Show(inTitle, inText, inIcon, dummy, inShowCancel, false, inParentWindow);
+}
diff --git a/src/Authoring/Common/Code/Qt3DSMessageBox.h b/src/Authoring/Common/Code/Qt3DSMessageBox.h
index ab8b7747..4d8a3b3d 100644
--- a/src/Authoring/Common/Code/Qt3DSMessageBox.h
+++ b/src/Authoring/Common/Code/Qt3DSMessageBox.h
@@ -79,7 +79,12 @@ public:
virtual ~Qt3DSMessageBox();
static EMessageBoxReturn Show(const QString &inTitle, const QString &inText,
EMessageBoxIcon inIcon, bool inShowCancel = false,
- TPlatformWindow inParentWindow = NULL);
+ TPlatformWindow inParentWindow = nullptr);
+ static EMessageBoxReturn Show(const QString &inTitle, const QString &inText,
+ EMessageBoxIcon inIcon, bool &doNotShowAgain,
+ bool inShowCancel = false, bool inDoNotShowAgainChoice = false,
+ TPlatformWindow inParentWindow = nullptr);
+
protected:
};
diff --git a/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h b/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h
index acfa4712..fd8f3f17 100644
--- a/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h
+++ b/src/Authoring/Common/Code/Serialize/ProjectSettingsSerializer.h
@@ -121,6 +121,9 @@ public:
bool thePreferKtx = theProjectSettings->getPreferCompressedTextures();
ar.Att("preferKtx", thePreferKtx);
+ bool theFlipCompressedTextures = theProjectSettings->getFlipCompressedTextures();
+ ar.Att("flipCompressedTextures", theFlipCompressedTextures);
+
if (QColorDialog::customCount() > 0) {
CustomColorSerializer ccs;
ar.Serialize(L"CustomColors", ccs);
@@ -161,6 +164,10 @@ public:
if (ar.Att("preferKtx", thePreferKtx))
theProjectSettings->setPreferCompressedTextures(thePreferKtx);
+ bool theFlipCompressedTextures;
+ if (ar.Att("flipCompressedTextures", theFlipCompressedTextures))
+ theProjectSettings->setFlipCompressedTextures(theFlipCompressedTextures);
+
{
CustomColorSerializer ccs;
ar.Serialize(L"CustomColors", ccs);
diff --git a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.cpp b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.cpp
index 2bbab435..661f0a03 100644
--- a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.cpp
+++ b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.cpp
@@ -37,6 +37,7 @@
#include "Qt3DSImportComposerTypes.h"
#include "Qt3DSFileToolsSeekableMeshBufIOStream.h"
#include "foundation/StrConvertUTF.h"
+#include <QtCore/qurl.h>
using qt3dsdm::IStringTable;
@@ -342,14 +343,14 @@ public:
{
if (m_ValidInstances.contains(inst))
return fromHdl(inst);
- return NULL;
+ return nullptr;
}
Instance *GetInstance(TIMPHandle inst)
{
if (m_ValidInstances.contains(inst))
return fromHdl(inst);
- return NULL;
+ return nullptr;
}
Instance *GetInstance(TCharPtr id)
@@ -357,7 +358,7 @@ public:
ImportHashMap<TCharPtr, Instance *>::const_iterator entry = m_IdToInstMap.find(id);
if (entry != m_IdToInstMap.end())
return entry->second;
- return NULL;
+ return nullptr;
}
Instance *GetInstance(TCharPtr id) const
@@ -365,7 +366,7 @@ public:
ImportHashMap<TCharPtr, Instance *>::const_iterator entry = m_IdToInstMap.find(id);
if (entry != m_IdToInstMap.end())
return entry->second;
- return NULL;
+ return nullptr;
}
Option<InstanceDesc> GetInstanceByHandle(TIMPHandle inst) const override
@@ -434,7 +435,7 @@ public:
QT3DSU32 GetNumProperties(TIMPHandle instance) const override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -443,7 +444,7 @@ public:
QT3DSU32 GetProperties(TIMPHandle instance, NVDataRef<PropertyValue> outBuffer) const override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -460,7 +461,7 @@ public:
ComposerPropertyNames::Enum val) const override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return Empty();
}
@@ -475,7 +476,7 @@ public:
QT3DSU32 GetNumChildren(TIMPHandle instance) const override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -493,7 +494,7 @@ public:
QT3DSU32 GetChildren(TIMPHandle instance, NVDataRef<InstanceDesc> childBuffer) const override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -514,7 +515,7 @@ public:
void MarkInstanceInvalid(TIMPHandle instance) override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -579,7 +580,7 @@ public:
QT3DSIMP_FOREACH(idx, (QT3DSU32)inSource.m_Children.size())
{
Instance *oldChild = GetInstance(inSource.m_Children[idx]);
- if (oldChild == NULL) {
+ if (oldChild == nullptr) {
QT3DS_ASSERT(false);
return retval;
}
@@ -599,7 +600,7 @@ public:
return;
}
Instance *theCopy = GetInstance(theNewItemId->second);
- if (theCopy == NULL) {
+ if (theCopy == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -632,7 +633,7 @@ public:
QT3DSIMP_FOREACH(idx, (QT3DSU32)inSource.m_Children.size())
{
Instance *oldChild = GetInstance(inSource.m_Children[idx]);
- if (oldChild == NULL) {
+ if (oldChild == nullptr) {
QT3DS_ASSERT(false);
return;
}
@@ -643,7 +644,7 @@ public:
TIMPHandle CopyInstance(TIMPHandle inSource) override
{
Instance *inst = GetInstance(inSource);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -654,7 +655,7 @@ public:
Instance *retval = CopyInstanceHierarchy(*inst, idMap);
Instance *parent = fromHdl(inst->m_Parent);
- if (parent != NULL)
+ if (parent != nullptr)
parent->AddChild(retval, inst);
// Copy properties and animations
@@ -666,7 +667,7 @@ public:
bool SetInstanceProperties(TIMPHandle instance, NVConstDataRef<PropertyValue> inBuffer) override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return false;
}
@@ -677,7 +678,7 @@ public:
const TImportModelValue &val) override
{
Instance *inst = GetInstance(instance);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return false;
}
@@ -694,11 +695,11 @@ public:
{
Instance *inst = GetInstance(instance);
Instance *child = GetInstance(childHdl);
- if (inst == NULL) {
+ if (inst == nullptr) {
QT3DS_ASSERT(false);
return false;
}
- if (child == NULL) {
+ if (child == nullptr) {
QT3DS_ASSERT(false);
return false;
}
@@ -757,25 +758,36 @@ public:
if (!m_ImageDir.IsDirectory())
m_ImageDir.CreateDir(true);
- if (!m_ImageDir.IsDirectory())
- return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_ImageDir.toCString());
+ if (!m_ImageDir.IsDirectory()) {
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory,
+ m_ImageDir.toCString());
+ }
Q3DStudio::CString imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
- Q3DStudio::CString srcImgPath =
- CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
-
- Q3DStudio::SFileErrorCodeFileNameAndNumBytes copyResult =
- Q3DStudio::SFileTools::FindAndCopyDestFile(m_ImageDir, imgPath);
+ Q3DStudio::CString srcImgPath = CFilePath::GetRelativePathFromBase(m_FullSrcDirectory,
+ imgPath);
+
+ // Need to get rid of %20 and such in the path, or we won't find the image
+ Q3DStudio::CString cleanImgPath
+ = Q3DStudio::CString::fromQString(QUrl::fromPercentEncoding(
+ imgPath.toQString().toUtf8()));
+ Q3DStudio::CString cleanSrcImgPath
+ = Q3DStudio::CString::fromQString(QUrl::fromPercentEncoding(
+ srcImgPath.toQString().toUtf8()));
+
+ Q3DStudio::SFileErrorCodeFileNameAndNumBytes copyResult
+ = Q3DStudio::SFileTools::FindAndCopyDestFile(m_ImageDir, cleanImgPath);
// Get the actual return value relative do our destination directory
- Q3DStudio::CString _retval =
- CFilePath::GetRelativePathFromBase(m_DestDirectory, copyResult.m_DestFilename);
+ Q3DStudio::CString _retval = CFilePath::GetRelativePathFromBase(m_DestDirectory,
+ copyResult.m_DestFilename);
// Register the string, so we can hand retval back to clients
TCharPtr retval = m_StringTable.RegisterStr(_retval.c_str());
- m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(srcImgPath.c_str()), retval));
+ m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(cleanSrcImgPath.c_str()),
+ retval));
if (copyResult.m_Error != Q3DStudio::FileErrorCodes::NoError) {
- CharPtrOrError errorValue(
- ImportErrorData(FromFileErrorCode(copyResult.m_Error), RegisterStr(imgPath)));
+ CharPtrOrError errorValue(ImportErrorData(FromFileErrorCode(copyResult.m_Error),
+ RegisterStr(cleanImgPath)));
errorValue.m_Value = retval;
return errorValue;
}
@@ -786,23 +798,31 @@ public:
if (dstPath.hasValue()) {
if (!m_ImageDir.IsDirectory())
m_ImageDir.CreateDir(true);
- if (!m_ImageDir.IsDirectory())
- return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory, m_ImageDir.toCString());
- CFilePath fullDestPath =
- CFilePath::CombineBaseAndRelative(m_DestDirectory, CString(dstPath.getValue()));
+ if (!m_ImageDir.IsDirectory()) {
+ return ImportErrorData(ImportErrorCodes::UnableToCreateDirectory,
+ m_ImageDir.toCString());
+ }
+ CFilePath fullDestPath = CFilePath::CombineBaseAndRelative(m_DestDirectory,
+ CString(dstPath.getValue()));
Q3DStudio::SFileErrorCodeAndNumBytes copyResult = Q3DStudio::SFileTools::Copy(
fullDestPath, Q3DStudio::FileOpenFlags(Q3DStudio::FileOpenFlagValues::Truncate
| Q3DStudio::FileOpenFlagValues::Open
| Q3DStudio::FileOpenFlagValues::Create),
- CString(_imgPath));
+ CString(_imgPath));
// Regardless of if the copy operation succeeds or not, if the destination exists
- // already
- // Then we enter it into our dictionary
+ // already then we enter it into our dictionary.
if (fullDestPath.IsFile()) {
CFilePath imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
- CFilePath srcImgPath =
- CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
- m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(srcImgPath.toCString()),
+ CFilePath srcImgPath = CFilePath::GetRelativePathFromBase(m_FullSrcDirectory,
+ imgPath);
+ // Need to get rid of %20 and such in the path, or we won't find the image
+ Q3DStudio::CString cleanImgPath
+ = Q3DStudio::CString::fromQString(
+ QUrl::fromPercentEncoding(imgPath.toQString().toUtf8()));
+ Q3DStudio::CString cleanSrcImgPath
+ = Q3DStudio::CString::fromQString(
+ QUrl::fromPercentEncoding(srcImgPath.toQString().toUtf8()));
+ m_Images.insert(eastl::make_pair(m_StringTable.RegisterStr(cleanSrcImgPath),
m_StringTable.RegisterStr(dstPath.getValue())));
}
@@ -810,7 +830,7 @@ public:
if (copyResult.m_Error != Q3DStudio::FileErrorCodes::NoError) {
QT3DS_ASSERT(false);
- const wchar_t *extraData = NULL;
+ const wchar_t *extraData = nullptr;
ImportErrorCodes::Enum error = FromFileErrorCode(copyResult.m_Error);
if (error == ImportErrorCodes::ResourceNotWriteable)
extraData = dstPath.getValue();
@@ -827,9 +847,13 @@ public:
Option<TCharPtr> FindImageByPath(TCharPtr _imgPath) const override
{
Q3DStudio::CString imgPath = CFilePath::GetAbsolutePath(CString(_imgPath));
- Q3DStudio::CString srcImgPath =
- CFilePath::GetRelativePathFromBase(m_FullSrcDirectory, imgPath);
- return FindImageByRelativePath(srcImgPath.c_str());
+ Q3DStudio::CString srcImgPath = CFilePath::GetRelativePathFromBase(m_FullSrcDirectory,
+ imgPath);
+ // Need to get rid of %20 and such in the path, or we won't find the image
+ Q3DStudio::CString cleanPath
+ = Q3DStudio::CString::fromQString(QUrl::fromPercentEncoding(
+ srcImgPath.toQString().toUtf8()));
+ return FindImageByRelativePath(cleanPath.c_str());
}
Option<TCharPtr> FindImageByRelativePath(TCharPtr imgPath) const override
@@ -1146,7 +1170,7 @@ public:
MemoryBuffer<RawAllocator> &inTempBuf)
{
Instance *theInstance = GetInstance(inAnimation.m_InstanceId);
- if (theInstance == NULL || theInstance->m_Valid == false)
+ if (theInstance == nullptr || theInstance->m_Valid == false)
return;
IDOMWriter::Scope __animScope(writer, L"AnimationTrack");
TCharStr thePropName(inAnimation.m_PropertyName);
@@ -1395,7 +1419,7 @@ public:
std::shared_ptr<IDOMFactory> factory(IDOMFactory::CreateDOMFactory(m_StringTablePtr));
std::shared_ptr<IDOMWriter> theWriter;
- SDOMElement *theTopElement = NULL;
+ SDOMElement *theTopElement = nullptr;
bool exists = fullPath.Exists();
{
@@ -1413,7 +1437,7 @@ public:
theTopElement = CDOMSerializer::Read(*factory, stream);
- if (theTopElement == NULL) {
+ if (theTopElement == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
@@ -1480,7 +1504,7 @@ public:
{
using namespace Q3DStudio;
std::shared_ptr<IDOMFactory> factory(IDOMFactory::CreateDOMFactory(m_StringTablePtr));
- SDOMElement *topElement = NULL;
+ SDOMElement *topElement = nullptr;
{
Qt3DSFileToolsSeekableMeshBufIOStream stream(
SFile::Wrap(SFile::OpenForRead(fname), fname));
@@ -1492,7 +1516,7 @@ public:
topElement = CDOMSerializer::Read(*factory, stream);
}
- if (topElement == NULL) {
+ if (topElement == nullptr) {
QT3DS_ASSERT(false);
return false;
}
@@ -1945,7 +1969,7 @@ QT3DSU32 Import::GetHighestImportRevision(TCharPtr pathToFile)
std::shared_ptr<IDOMFactory> theFactory = IDOMFactory::CreateDOMFactory(theStringTable);
SDOMElement *theTopElement = CDOMSerializer::Read(*theFactory, stream);
- if (theTopElement == NULL) {
+ if (theTopElement == nullptr) {
QT3DS_ASSERT(false);
return 0;
}
diff --git a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.cpp b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.cpp
index 5c4cb11d..fdf332c5 100644
--- a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.cpp
+++ b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.cpp
@@ -225,6 +225,8 @@ SImportAsset &SImportComposerTypes::GetImportAssetForType(ComposerObjectTypes::E
return m_Asset;
case ComposerObjectTypes::Group:
return m_Group;
+ case ComposerObjectTypes::Signal:
+ return m_Signal;
case ComposerObjectTypes::Light:
return m_Light;
case ComposerObjectTypes::Camera:
diff --git a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.h b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.h
index 78df2a9b..0f069270 100644
--- a/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.h
+++ b/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImportComposerTypes.h
@@ -88,6 +88,11 @@ struct SImportGroup : public SImportNode
ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Group; }
};
+struct SImportSignal : public SImportNode
+{
+ ComposerObjectTypes::Enum GetObjectType() override { return ComposerObjectTypes::Signal; }
+};
+
struct SImportLight : public SImportNode
{
ITERATE_COMPOSER_LIGHT_PROPERTIES
@@ -205,6 +210,7 @@ struct SImportComposerTypes
{
SImportAsset m_Asset;
SImportGroup m_Group;
+ SImportSignal m_Signal;
SImportLight m_Light;
SImportCamera m_Camera;
SImportModel m_Model;
diff --git a/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportColladaSGTranslation.cpp b/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportColladaSGTranslation.cpp
index 20626c9c..0cadee7b 100644
--- a/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportColladaSGTranslation.cpp
+++ b/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportColladaSGTranslation.cpp
@@ -73,7 +73,7 @@ public:
public:
bool LoadDocument(const std::string &inFilePath);
- void ProcessScene();
+ bool ProcessScene();
void ProcessLibraryAnimations();
protected:
@@ -363,10 +363,13 @@ bool ColladaDOMWalker::LoadDocument(const std::string &inFilePath)
* This begins by looking at the active visual_scene node and starting import
* from that node.
*/
-void ColladaDOMWalker::ProcessScene()
+bool ColladaDOMWalker::ProcessScene()
{
if (m_ColladaRoot != nullptr) {
const domCOLLADA::domSceneRef theScene = m_ColladaRoot->getScene();
+ if (!theScene)
+ return false;
+
// Retrieve the active visual_scene
const domInstanceWithExtraRef theInstanceVisualScene = theScene->getInstance_visual_scene();
const xsAnyURI &theVisualSceneURI = theInstanceVisualScene->getUrl();
@@ -413,6 +416,8 @@ void ColladaDOMWalker::ProcessScene()
// Disable wrapping the visual scene in it's own group, since m_TopMostParent exists
// PopGroup( );
}
+
+ return true;
}
void ColladaDOMWalker::SetFColladaAuthoringTool(const char *inName)
@@ -1816,8 +1821,7 @@ bool CImportTranslation::ParseColladaFile(const std::string &fileName, Import &i
ColladaDOMWalker theDOMWalker(&transHelper);
if (theDOMWalker.LoadDocument(fileName)) {
theDOMWalker.ProcessLibraryAnimations();
- theDOMWalker.ProcessScene();
- return true;
+ return theDOMWalker.ProcessScene();
}
return false;
}
diff --git a/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportFbxSGTranslation.cpp b/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportFbxSGTranslation.cpp
index 86f22e56..8e0a0dc4 100644
--- a/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportFbxSGTranslation.cpp
+++ b/src/Authoring/QT3DSIMP/Qt3DSImportSGTranslation/Qt3DSImportFbxSGTranslation.cpp
@@ -159,6 +159,7 @@ protected:
TNodeSet m_importNodes;
EAuthoringToolType m_AuthoringToolType;
bool m_reportedUnknownMaterials = false;
+ FbxAxisSystem::EUpVector m_originalUpVector;
};
FbxDomWalker::FbxDomWalker(ISceneGraphTranslation *inTranslation)
@@ -363,7 +364,8 @@ void FbxDomWalker::ProcessScene(bool animations)
if (m_FbxScene != nullptr) {
FbxAxisSystem SceneAxisSystem = m_FbxScene->GetGlobalSettings().GetAxisSystem();
int sign;
- if (SceneAxisSystem.GetUpVector(sign) == FbxAxisSystem::eZAxis
+ m_originalUpVector = SceneAxisSystem.GetUpVector(sign);
+ if (m_originalUpVector == FbxAxisSystem::eZAxis
&& m_AuthoringToolType != EAuthoringToolType_FBX_Maya) {
// Do automatic axis system conversion from Z-up to Y-up
FbxAxisSystem::OpenGL.ConvertScene(m_FbxScene);
@@ -675,13 +677,24 @@ void FbxDomWalker::ProcessTransform(FbxNode *inFbxNode, bool ignoreScale)
theTransformMatrix.SetS(FbxVector4(1.0, 1.0, 1.0, 1.0));
// Do rotation corrections for cameras and lights if importing from Blender
- // Note: Blender must have "Y Forward" and "Z Up" export settings defined for these to work
- if (m_AuthoringToolType == EAuthoringToolType_FBX_Blender) {
- FbxDouble3 rot = inFbxNode->LclRotation.Get();
+ // Note: Blender and 3ds max must have "Y Forward" and "Z Up" export settings defined for
+ // these to work. For 3ds Max it is the default setting, but for Blender it is not.
+ if (m_originalUpVector == FbxAxisSystem::eZAxis) {
+ if (m_AuthoringToolType == EAuthoringToolType_FBX_Blender) {
+ FbxDouble3 rot = inFbxNode->LclRotation.Get();
+ if (inFbxNode->GetLight())
+ theTransformMatrix.SetR(FbxVector4(rot[0] - 90., rot[1], rot[2], 1.0));
+ else if (inFbxNode->GetCamera())
+ theTransformMatrix.SetR(FbxVector4(rot[0], rot[1] - 90., rot[2], 1.0));
+ }
+ } else if (m_originalUpVector == FbxAxisSystem::eYAxis
+ && m_AuthoringToolType == EAuthoringToolType_FBX_Max) {
+ // 3ds Max messes up the positions if FBX is exported with y-up axis system.
+ // Fix that by switching the positions between z and y axes.
+ FbxDouble3 pos = inFbxNode->LclTranslation.Get();
+ // Override the converted rotations with correct ones
if (inFbxNode->GetLight())
- theTransformMatrix.SetR(FbxVector4(rot[0] - 90., rot[1], rot[2], 1.0));
- else if (inFbxNode->GetCamera())
- theTransformMatrix.SetR(FbxVector4(rot[0], rot[1] - 90., rot[2], 1.0));
+ theTransformMatrix.SetT(FbxVector4(pos[0], pos[1], pos[2], 1.0));
}
theTransforms.push_back(new NodeTransform(ETransformType_Matrix4x4));
diff --git a/src/Authoring/Qt3DStudio/Application/DataInputDlg.cpp b/src/Authoring/Qt3DStudio/Application/DataInputDlg.cpp
index f6255395..127f6547 100644
--- a/src/Authoring/Qt3DStudio/Application/DataInputDlg.cpp
+++ b/src/Authoring/Qt3DStudio/Application/DataInputDlg.cpp
@@ -56,9 +56,6 @@ CDataInputDlg::CDataInputDlg(CDataInputDialogItem **datainput, QStandardItemMode
m_ui->comboBoxTypeList->setItemDelegate(itemDelegate);
m_ui->comboBoxTypeList->addItem(tr("Boolean"), QVariant(DataTypeBoolean));
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- m_ui->comboBoxTypeList->addItem(tr("Evaluator"), QVariant(DataTypeEvaluator));
-#endif
m_ui->comboBoxTypeList->addItem(tr("Float"), QVariant(DataTypeFloat));
m_ui->comboBoxTypeList->addItem(tr("Ranged Number"), QVariant(DataTypeRangedNumber));
m_ui->comboBoxTypeList->addItem(tr("String"), QVariant(DataTypeString));
@@ -127,11 +124,6 @@ void CDataInputDlg::initDialog()
m_min = m_dataInput->minValue;
m_max = m_dataInput->maxValue;
}
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- else if (m_type == DataTypeEvaluator) {
- m_ui->lineEditEvaluation->setText(m_dataInput->valueString);
- }
-#endif
} else {
m_name = getUniqueId(tr("newDataInput"));
if (m_dataInput->type == DataTypeRangedNumber) {
@@ -190,11 +182,6 @@ void CDataInputDlg::accept()
m_dataInput->minValue = m_min;
m_dataInput->maxValue = m_max;
}
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- else if (m_type == DataTypeEvaluator) {
- m_dataInput->valueString = m_text;
- }
-#endif
m_dataInput->metadata.clear();
for (auto const &it : qAsConst(m_orderedMetadata))
@@ -255,15 +242,7 @@ void CDataInputDlg::updateVisibility(int type)
m_ui->doubleSpinBoxMin->setVisible(false);
m_ui->doubleSpinBoxMax->setVisible(false);
}
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- if (type == DataTypeEvaluator) {
- m_ui->lineEditEvaluation->setVisible(true);
- m_ui->labelEvaluation->setVisible(true);
- } else {
- m_ui->lineEditEvaluation->setVisible(false);
- m_ui->labelEvaluation->setVisible(false);
- }
-#endif
+
// Adjust text label positioning according to the
// visibility of info text warning about allowed datatypes.
if (m_dataInput->ctrldElems.size()) {
@@ -293,11 +272,7 @@ bool CDataInputDlg::isEquivalentDataType(int dlgType, qt3dsdm::DataModelDataType
// Variant can be bound to any property type except timeline controller because only
// datainput of type Ranged Number has additional min/max information. For slide control,
// we can allow variant type in addition to String type.
- || (dlgType == EDataType::DataTypeVariant && dmType != DataModelDataType::RangedNumber)
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- || dlgType == EDataType::DataTypeEvaluator
-#endif
- ) {
+ || (dlgType == EDataType::DataTypeVariant && dmType != DataModelDataType::RangedNumber)) {
return true;
}
diff --git a/src/Authoring/Qt3DStudio/Application/DataInputDlg.h b/src/Authoring/Qt3DStudio/Application/DataInputDlg.h
index 9ae6bc6f..c859ccf6 100644
--- a/src/Authoring/Qt3DStudio/Application/DataInputDlg.h
+++ b/src/Authoring/Qt3DStudio/Application/DataInputDlg.h
@@ -52,9 +52,6 @@ QT_FORWARD_DECLARE_CLASS(QStandardItemModel)
enum EDataType {
DataTypeBoolean = 0,
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- DataTypeEvaluator,
-#endif
DataTypeFloat,
DataTypeRangedNumber,
DataTypeString,
@@ -73,9 +70,6 @@ static const QVector<EDataType> allDataTypes {
EDataType::DataTypeVector2,
EDataType::DataTypeRangedNumber,
EDataType::DataTypeBoolean,
- #ifdef DATAINPUT_EVALUATOR_ENABLED
- EDataType::DataTypeEvaluator,
- #endif
EDataType::DataTypeVariant
};
diff --git a/src/Authoring/Qt3DStudio/Application/DataInputListDlg.cpp b/src/Authoring/Qt3DStudio/Application/DataInputListDlg.cpp
index 5a053778..a6d9e932 100644
--- a/src/Authoring/Qt3DStudio/Application/DataInputListDlg.cpp
+++ b/src/Authoring/Qt3DStudio/Application/DataInputListDlg.cpp
@@ -216,12 +216,6 @@ void CDataInputListDlg::updateContents()
} else if (dataInputType == DataTypeFloat
&& (m_typeFilter == (int)DataTypeFloat || m_typeFilter == -1)) {
dataInput.append(new QStandardItem(tr("Float")));
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- } else if (dataInputType == DataTypeEvaluator
- && (m_typeFilter == (int)DataTypeEvaluator || m_typeFilter == -1)) {
- dataInput.append(new QStandardItem(tr("Evaluator")));
- dataInput.append(new QStandardItem(m_dataInputs.at(i)->valueString));
-#endif
} else if (dataInputType == DataTypeBoolean
&& (m_typeFilter == (int)DataTypeBoolean || m_typeFilter == -1)) {
dataInput.append(new QStandardItem(tr("Boolean")));
diff --git a/src/Authoring/Qt3DStudio/Application/DataInputSelectView.cpp b/src/Authoring/Qt3DStudio/Application/DataInputSelectView.cpp
index 6fab215a..878f779b 100644
--- a/src/Authoring/Qt3DStudio/Application/DataInputSelectView.cpp
+++ b/src/Authoring/Qt3DStudio/Application/DataInputSelectView.cpp
@@ -118,11 +118,6 @@ QString DataInputSelectView::getDiTypeStr(int type)
case EDataType::DataTypeBoolean:
return tr("Boolean");
break;
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- case EDataType::DataTypeEvaluator:
- return tr("Evaluator");
- break;
-#endif
case EDataType::DataTypeFloat:
return tr("Float");
break;
diff --git a/src/Authoring/Qt3DStudio/Application/ProjectFile.cpp b/src/Authoring/Qt3DStudio/Application/ProjectFile.cpp
index 279c1d65..1ad0b5c0 100644
--- a/src/Authoring/Qt3DStudio/Application/ProjectFile.cpp
+++ b/src/Authoring/Qt3DStudio/Application/ProjectFile.cpp
@@ -486,12 +486,6 @@ void ProjectFile::parseDataInputElem(const QDomElement &elem,
} else if (type == QLatin1String("Variant")) {
item->type = EDataType::DataTypeVariant;
}
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- else if (type == QLatin1String("Evaluator")) {
- item->type = EDataType::DataTypeEvaluator;
- item->valueString = elem.attribute(QStringLiteral("evaluator"));
- }
-#endif
auto metadata = elem.attribute(QStringLiteral("metadata"));
if (!metadata.isEmpty()) {
diff --git a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
index 5ca21921..ac9efb10 100644
--- a/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
+++ b/src/Authoring/Qt3DStudio/Application/StudioApp.cpp
@@ -1108,15 +1108,12 @@ QString CStudioApp::GetPasteType()
bool CStudioApp::CanChangeTimebarColor()
{
- bool theRetVal = true;
- qt3dsdm::Qt3DSDMInstanceHandle theSelectedInstance = m_core->GetDoc()->GetSelectedInstance();
- if (!theSelectedInstance.Valid()
- || m_core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsSceneInstance(
- theSelectedInstance)) {
- theRetVal = false;
+ auto theSelectedInstance = m_core->GetDoc()->GetSelectedInstance();
+ if (theSelectedInstance.Valid()) {
+ auto bridge = m_core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ return !bridge->IsActiveComponent(theSelectedInstance);
}
-
- return theRetVal;
+ return false;
}
/**
@@ -1571,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);
@@ -1631,12 +1635,6 @@ void CStudioApp::saveDataInputsToProjectFile()
} else if (item->type == EDataType::DataTypeVariant) {
diNode.setAttribute(QStringLiteral("type"), QStringLiteral("Variant"));
}
-#ifdef DATAINPUT_EVALUATOR_ENABLED
- else if (item->type == EDataType::DataTypeEvaluator) {
- diNode.setAttribute(QStringLiteral("type"), QStringLiteral("Evaluator"));
- diNode.setAttribute(QStringLiteral("evaluator"), item->valueString);
- }
-#endif
QHashIterator<QString, QString> it(item->metadata);
QString metadataStr;
@@ -2062,6 +2060,13 @@ void CStudioApp::showPresentationIdEmptyWarning()
Qt3DSMessageBox::ICON_WARNING, false);
}
+void CStudioApp::showShaderCompileError(const QString &error)
+{
+ m_dialogs->DisplayMessageBox(tr("Warning"),
+ tr("Shader compile error.\n") + error,
+ Qt3DSMessageBox::ICON_WARNING, false);
+}
+
void CStudioApp::showInvalidFilenameWarning()
{
m_dialogs->DisplayMessageBox(tr("Invalid filename"),
diff --git a/src/Authoring/Qt3DStudio/Application/StudioApp.h b/src/Authoring/Qt3DStudio/Application/StudioApp.h
index 8fccafcf..11e50138 100644
--- a/src/Authoring/Qt3DStudio/Application/StudioApp.h
+++ b/src/Authoring/Qt3DStudio/Application/StudioApp.h
@@ -219,6 +219,7 @@ public:
void showPresentationIdUniqueWarning();
void showPresentationIdEmptyWarning();
void showInvalidFilenameWarning();
+ void showShaderCompileError(const QString &error);
void checkDeletedDatainputs(bool askFromUser);
void saveDataInputsToProjectFile();
void verifyDatainputBindings();
@@ -250,8 +251,31 @@ public:
void OnNewPresentation() override;
void OnPresentationModifiedExternally() override;
+ void SetConvertingPresentationOn()
+ {
+ m_convertPresentation = true;
+ }
+ void SetConvertingPresentationOff()
+ {
+ m_convertPresentation = false;
+ }
+ bool IsConvertingPresentationOn()
+ {
+ return m_convertPresentation;
+ }
+ int getDocumentVersion() const
+ {
+ return m_docVersion;
+ }
+ void setDocumentVersion(int version)
+ {
+ m_docVersion = version;
+ }
+
QString m_helpFilePath;
QString m_gettingStartedFilePath;
+ bool m_convertPresentation = false;
+ int m_docVersion = 0;
QVector<SubPresentationRecord> m_subpresentations;
QMap<QString, CDataInputDialogItem *> m_dataInputDialogItems;
diff --git a/src/Authoring/Qt3DStudio/DragAndDrop/BasicObjectDropSource.cpp b/src/Authoring/Qt3DStudio/DragAndDrop/BasicObjectDropSource.cpp
index d99bd9a5..ecaae33a 100644
--- a/src/Authoring/Qt3DStudio/DragAndDrop/BasicObjectDropSource.cpp
+++ b/src/Authoring/Qt3DStudio/DragAndDrop/BasicObjectDropSource.cpp
@@ -163,6 +163,9 @@ CCmd *CBasicObjectDropSource::GenerateAssetCommand(qt3dsdm::Qt3DSDMInstanceHandl
case OBJTYPE_GROUP:
theComposerType = ComposerObjectTypes::Group;
break;
+ case OBJTYPE_SIGNAL:
+ theComposerType = ComposerObjectTypes::Signal;
+ break;
case OBJTYPE_IMAGE:
theComposerType = ComposerObjectTypes::Image;
break;
@@ -254,10 +257,17 @@ CCmd *CBasicObjectDropSource::GenerateAssetCommand(qt3dsdm::Qt3DSDMInstanceHandl
Q3DStudio::ImportUtils::GetInsertTypeForDropType(inDestType), thePoint,
theStartTime);
} else {
- SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Add Instance"))
- ->CreateSceneGraphInstance(theComposerType, inTarget, inSlide, theInsertType,
+ ScopedDocumentEditor editor(
+ SCOPED_DOCUMENT_EDITOR(*theDoc, QObject::tr("Add Instance")));
+ Qt3DSDMInstanceHandle newHandle =
+ editor->CreateSceneGraphInstance(theComposerType, inTarget, inSlide, theInsertType,
thePoint, (EPrimitiveType)m_PrimitiveType, theStartTime,
false);
+
+ if (theComposerType == ComposerObjectTypes::Signal) {
+ // When creating a signal, automatically create also onActivate action
+ editor->AddAction(inSlide, newHandle, L"onActivate", L"Emit Signal");
+ }
}
}
return nullptr;
diff --git a/src/Authoring/Qt3DStudio/Info.plist b/src/Authoring/Qt3DStudio/Info.plist
index 5dcc69d1..de9a9cac 100644
--- a/src/Authoring/Qt3DStudio/Info.plist
+++ b/src/Authoring/Qt3DStudio/Info.plist
@@ -2,78 +2,78 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>UTImportedTypeDeclarations</key>
- <array>
- <dict>
- <key>UTTypeDescription</key>
- <string>Qt 3D Studio Application File</string>
- <key>UTTypeConformsTo</key>
- <array>
- <string>public.source-code</string>
- </array>
- <key>UTTypeIdentifier</key>
- <string>org.qt-project.uia</string>
- <key>UTTypeTagSpecification</key>
- <dict>
- <key>public.filename-extension</key>
- <array>
- <string>uia</string>
- </array>
- </dict>
- </dict>
- <dict>
- <key>UTTypeDescription</key>
- <string>Qt 3D Studio Presentation File</string>
- <key>UTTypeConformsTo</key>
- <array>
- <string>public.source-code</string>
- </array>
- <key>UTTypeIdentifier</key>
- <string>org.qt-project.uip</string>
- <key>UTTypeTagSpecification</key>
- <dict>
- <key>public.filename-extension</key>
- <array>
- <string>uip</string>
- </array>
- </dict>
- </dict>
- </array>
- <key>CFBundleDocumentTypes</key>
- <array>
- <dict>
- <key>LSItemContentTypes</key>
- <array>
- <string>org.qt-project.uip</string>
- <string>org.qt-project.uia</string>
- </array>
- <key>CFBundleTypeRole</key>
- <string>Editor</string>
- <key>LSHandlerRank</key>
- <string>Default</string>
- </dict>
- </array>
- <key>NSHumanReadableCopyright</key>
- <string>(C) 2019 The Qt Company Ltd</string>
- <key>CFBundleExecutable</key>
- <string>Qt3DStudio</string>
- <key>CFBundleIconFile</key>
- <string>studio.icns</string>
- <key>CFBundleIdentifier</key>
- <string>org.qt-project.qt3dstudio</string>
- <key>CFBundleVersion</key>
- <string>2.4.0</string>
- <key>CFBundleShortVersionString</key>
- <string>2.4</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
- <key>CFBundleSignature</key>
- <string>????</string>
- <key>LSMinimumSystemVersion</key>
- <string>10.10</string>
- <key>NSPrincipalClass</key>
- <string>NSApplication</string>
- <key>NSSupportsAutomaticGraphicsSwitching</key>
- <true/>
+ <key>UTImportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeDescription</key>
+ <string>Qt 3D Studio Application File</string>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.source-code</string>
+ </array>
+ <key>UTTypeIdentifier</key>
+ <string>org.qt-project.uia</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>uia</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeDescription</key>
+ <string>Qt 3D Studio Presentation File</string>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.source-code</string>
+ </array>
+ <key>UTTypeIdentifier</key>
+ <string>org.qt-project.uip</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>uip</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.qt-project.uip</string>
+ <string>org.qt-project.uia</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Editor</string>
+ <key>LSHandlerRank</key>
+ <string>Default</string>
+ </dict>
+ </array>
+ <key>NSHumanReadableCopyright</key>
+ <string>(C) 2020 The Qt Company Ltd</string>
+ <key>CFBundleExecutable</key>
+ <string>Qt3DStudio</string>
+ <key>CFBundleIconFile</key>
+ <string>studio.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.qt-project.qt3dstudio</string>
+ <key>CFBundleVersion</key>
+ <string>2.8.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>2.8</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.10</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
+ <true/>
</dict>
</plist>
diff --git a/src/Authoring/Qt3DStudio/MainFrm.cpp b/src/Authoring/Qt3DStudio/MainFrm.cpp
index e59b7c1c..8a868d23 100644
--- a/src/Authoring/Qt3DStudio/MainFrm.cpp
+++ b/src/Authoring/Qt3DStudio/MainFrm.cpp
@@ -177,6 +177,7 @@ CMainFrame::CMainFrame()
connect(m_ui->actionTooltips, &QAction::triggered, this, &CMainFrame::OnViewTooltips);
connect(m_ui->actionHelper_Grid, &QAction::triggered, this, &CMainFrame::onHelperGrid);
+ connect(m_ui->actionAxis_Helper, &QAction::triggered, this, &CMainFrame::onAxisHelper);
m_ui->actionHelper_Grid->setToolTip(
m_ui->actionHelper_Grid->toolTip().arg(
m_ui->actionHelper_Grid->shortcut().toString(QKeySequence::NativeText)));
@@ -218,16 +219,6 @@ CMainFrame::CMainFrame()
connect(m_ui->actionRemote_Preview, &QAction::triggered,
this, &CMainFrame::OnPlaybackPreviewRemote);
- // Only show Qt3D runtime preview if we have appropriate viewer and it's enabled
- if (CStudioPreferences::isLegacyViewerActive()
- && QFileInfo(CPreviewHelper::getViewerFilePath(QStringLiteral("q3dsviewer"))).exists()) {
- connect(m_ui->actionPreviewQt3DRuntime, &QAction::triggered,
- this, &CMainFrame::OnPlaybackPreviewQt3DRuntime);
- m_ui->actionPreviewQt3DRuntime->setVisible(true);
- } else {
- m_ui->actionPreviewQt3DRuntime->setVisible(false);
- }
-
// Tool mode toolbar
connect(m_ui->actionPosition_Tool, &QAction::triggered, this,
std::bind(&CMainFrame::onTransformToolChanged, this, STUDIO_TOOLMODE_MOVE));
@@ -282,6 +273,7 @@ CMainFrame::CMainFrame()
OnUpdateViewWireframe();
OnUpdateViewTooltips();
onUpdateHelperGrid();
+ onUpdateAxisHelper();
OnUpdateViewTimeline();
onUpdateViewSceneCamera();
OnUpdateViewInspector();
@@ -896,7 +888,6 @@ void CMainFrame::EditPreferences(short inPageIndex)
CStudioPreferences::setDontShowGLVersionDialog(false);
CStudioPreferences::setDefaultClientSize(CStudioPreferences::DEFAULT_CLIENT_WIDTH,
CStudioPreferences::DEFAULT_CLIENT_HEIGHT);
- CStudioPreferences::setLegacyViewerActive(true);
CStudioPreferences::setEditViewFillMode(true);
CStudioPreferences::setPreferredStartupView(
CStudioPreferences::PREFERREDSTARTUP_DEFAULTINDEX);
@@ -908,6 +899,7 @@ void CMainFrame::EditPreferences(short inPageIndex)
CStudioPreferences::setWireframeModeOn(true);
CStudioPreferences::setTooltipsOn(true);
CStudioPreferences::setHelperGridOn(true);
+ CStudioPreferences::setAxisHelperOn(true);
CStudioPreferences::setHelperGridLines(10);
CStudioPreferences::setHelperGridSpacing(100);
CStudioPreferences::setSelectorLineWidth(
@@ -923,6 +915,9 @@ void CMainFrame::EditPreferences(short inPageIndex)
CStudioPreferences::setPreviewConfig({});
CStudioPreferences::setPreviewProperty({}, {});
+ // Pop-ups
+ CStudioPreferences::setDoNotShowImportWarnings(false);
+
RecheckSizingMode();
// Save preferences, to make sure we do not lose them on a possible crash
@@ -1032,11 +1027,6 @@ void CMainFrame::OnPlaybackPreview(const QString &viewerExeName, bool remote)
}
}
-void CMainFrame::OnPlaybackPreviewQt3DRuntime()
-{
- OnPlaybackPreview(QStringLiteral("q3dsviewer"));
-}
-
void CMainFrame::OnPlaybackPreviewOpenGLRuntime()
{
OnPlaybackPreview(QStringLiteral("Qt3DViewer"));
@@ -1689,11 +1679,21 @@ void CMainFrame::onUpdateHelperGrid()
}
}
+void CMainFrame::onUpdateAxisHelper()
+{
+ m_ui->actionAxis_Helper->setChecked(CStudioPreferences::isAxisHelperOn());
+}
+
void CMainFrame::onHelperGrid()
{
CStudioPreferences::setHelperGridOn(!CStudioPreferences::isHelperGridOn());
}
+void CMainFrame::onAxisHelper()
+{
+ CStudioPreferences::setAxisHelperOn(!CStudioPreferences::isAxisHelperOn());
+}
+
//==============================================================================
/**
* Called when the update message occurs for the Help->Help Topics menu item.
diff --git a/src/Authoring/Qt3DStudio/MainFrm.h b/src/Authoring/Qt3DStudio/MainFrm.h
index 52c23be4..f1d2fdeb 100644
--- a/src/Authoring/Qt3DStudio/MainFrm.h
+++ b/src/Authoring/Qt3DStudio/MainFrm.h
@@ -144,7 +144,6 @@ public:
void OnPlaybackRewind();
void OnPlaybackStop();
void OnPlaybackPreview(const QString &viewerExeName, bool remote = false);
- void OnPlaybackPreviewQt3DRuntime();
void OnPlaybackPreviewOpenGLRuntime();
void OnPlaybackPreviewRemote();
void onFilterVariants();
@@ -175,6 +174,8 @@ public:
void OnHelpIndex();
void OnHelpVisitQt();
void OnHelpOpenTutorial();
+ void onUpdateAxisHelper();
+ void onAxisHelper();
void onViewResetLayout();
void OnViewAction();
diff --git a/src/Authoring/Qt3DStudio/MainFrm.ui b/src/Authoring/Qt3DStudio/MainFrm.ui
index 26f9cff9..9473052f 100644
--- a/src/Authoring/Qt3DStudio/MainFrm.ui
+++ b/src/Authoring/Qt3DStudio/MainFrm.ui
@@ -132,6 +132,7 @@ Project palette using Import functionality.</string>
<addaction name="actionTooltips"/>
<addaction name="actionFind"/>
<addaction name="actionHelper_Grid"/>
+ <addaction name="actionAxis_Helper"/>
<addaction name="actionRulers_Guides"/>
<addaction name="actionLock_Guides"/>
<addaction name="actionClear_Guides"/>
@@ -275,7 +276,6 @@ Project palette using Import functionality.</string>
<addaction name="actionFilterVariants"/>
<addaction name="actionPreview"/>
<addaction name="actionRemote_Preview"/>
- <addaction name="actionPreviewQt3DRuntime"/>
</widget>
<action name="action_Reference_Manual">
<property name="text">
@@ -875,21 +875,6 @@ Project palette using Import functionality.</string>
<bool>false</bool>
</property>
</action>
- <action name="actionPreviewQt3DRuntime">
- <property name="icon">
- <iconset resource="images.qrc">
- <normaloff>:/images/playback_tools_play.png</normaloff>:/images/playback_tools_play.png</iconset>
- </property>
- <property name="text">
- <string>Preview with Qt3D Runtime Viewer</string>
- </property>
- <property name="iconText">
- <string>Preview with Qt3D Runtime Viewer</string>
- </property>
- <property name="toolTip">
- <string>Preview with Qt3D Runtime Viewer</string>
- </property>
- </action>
<action name="actionImportAssets">
<property name="text">
<string>Import...</string>
@@ -1120,6 +1105,20 @@ Project palette using Import functionality.</string>
<bool>false</bool>
</property>
</action>
+ <action name="actionAxis_Helper">
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Axis Helper</string>
+ </property>
+ <property name="toolTip">
+ <string>Show world axis helper</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
index e8a7f061..1c4fe0f2 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
@@ -183,6 +183,11 @@ bool ActionView::event(QEvent *event)
return QQuickWidget::event(event);
}
+void ActionView::setControlView(InspectorControlView *controlView)
+{
+ m_inspectorControlView = controlView;
+}
+
void ActionView::setItem(const qt3dsdm::Qt3DSDMInstanceHandle &handle)
{
if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()) {
@@ -324,6 +329,11 @@ bool ActionView::isPropertyValueInvalid() const
return m_propertyValueInvalid;
}
+QColor ActionView::showColorDialog(const QColor &color, int instance, int handle)
+{
+ return ActionView::m_inspectorControlView->showColorDialog(color, instance, handle);
+}
+
void ActionView::setCurrentActionIndex(int index)
{
if (index == m_currentActionIndex)
@@ -384,8 +394,17 @@ void ActionView::addAction()
// Query data model bridge to see the applicable events and actions for this instance.
CClientDataModelBridge *theBridge = GetBridge();
- std::wstring theEventName = theBridge->GetDefaultEvent(m_itemHandle);
- std::wstring theHandlerName = theBridge->GetDefaultHandler(m_itemHandle);
+ // For signals, default to onActivate and emitting signal
+ std::wstring preferredEvent = L"";
+ std::wstring preferredHandler = L"";
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ if (info.m_Type == OBJTYPE_SIGNAL) {
+ preferredEvent = L"onActivate";
+ preferredHandler = L"Emit Signal";
+ }
+
+ std::wstring theEventName = theBridge->GetDefaultEvent(m_itemHandle, preferredEvent);
+ std::wstring theHandlerName = theBridge->GetDefaultHandler(m_itemHandle, preferredHandler);
Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Add Action"))
->AddAction(GetDoc()->GetActiveSlide(), m_itemHandle, theEventName,
@@ -514,6 +533,22 @@ QObject *ActionView::showEventBrowser(const QPoint &point)
qt3dsdm::TEventHandleList eventList;
bridge->GetEvents(instanceHandle, eventList);
+
+ // Only show time events if the selected object is a signal
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ if (info.m_Type == OBJTYPE_SIGNAL) {
+ qt3dsdm::TEventHandleList filteredEventList;
+ auto thePos = eventList.begin();
+ for (; thePos != eventList.end(); ++thePos) {
+ qt3dsdm::SEventInfo theEvent = bridge->GetEventInfo(*thePos);
+ QString name = QString::fromWCharArray(theEvent.m_Category.wide_str());
+
+ if (name == QString("Time"))
+ filteredEventList.emplace_back(*thePos);
+ }
+ eventList = filteredEventList;
+ }
+
m_eventsModel->setEventList(eventList);
if (!m_eventsBrowser)
@@ -1034,6 +1069,8 @@ void ActionView::updateHandlerArguments()
m_currentPropertyValueHandle = 0;
m_currentPropertyNameHandle = 0;
m_handlerArguments.clear();
+ // Emit empty list, to force update even when arguments amount remain the same
+ Q_EMIT handlerArgumentsChanged();
const auto doc = GetDoc();
if (!doc->isValid() || !m_itemHandle.Valid())
return;
@@ -1059,6 +1096,7 @@ void ActionView::updateHandlerArguments()
argument.m_completeType = argMetaData->m_CompleteType;
m_handlerArguments.append(QVariant::fromValue(argument));
}
+ Q_EMIT handlerArgumentsChanged();
}
}
@@ -1106,6 +1144,8 @@ void ActionView::initialize()
{
CStudioPreferences::setQmlContextProperties(rootContext());
rootContext()->setContextProperty(QStringLiteral("_parentView"), this);
+ rootContext()->setContextProperty(QStringLiteral("_inspectorModel"),
+ m_inspectorControlView->inspectorControlModel());
rootContext()->setContextProperty(QStringLiteral("_resDir"), StudioUtils::resourceImageUrl());
rootContext()->setContextProperty(QStringLiteral("_tabOrderHandler"), tabOrderHandler());
rootContext()->setContextProperty(QStringLiteral("_mouseHelper"), &m_mouseHelper);
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.h b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.h
index ab2976f3..6e826448 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.h
@@ -48,6 +48,8 @@
#include "Qt3DSDMMetaDataTypes.h"
#include "TabOrderHandler.h"
#include "MouseHelper.h"
+#include "InspectorControlView.h"
+#include "InspectorControlModel.h"
class ActionModel;
class CClientDataModelBridge;
@@ -91,7 +93,7 @@ class ActionView : public QQuickWidget,
Q_PROPERTY(QString targetObjectName READ targetObjectName NOTIFY actionChanged FINAL)
Q_PROPERTY(QString eventName READ eventName NOTIFY actionChanged FINAL)
Q_PROPERTY(QString handlerName READ handlerName NOTIFY actionChanged FINAL)
- Q_PROPERTY(QVariantList handlerArguments READ handlerArguments NOTIFY actionChanged FINAL)
+ Q_PROPERTY(QVariantList handlerArguments READ handlerArguments NOTIFY handlerArgumentsChanged FINAL)
Q_PROPERTY(PropertyInfo property READ property NOTIFY propertyChanged FINAL)
Q_PROPERTY(QString firedEvent MEMBER m_firedEvent NOTIFY firedEventChanged FINAL)
Q_PROPERTY(bool propertyValueInvalid READ isPropertyValueInvalid NOTIFY propertyValueInvalidChanged FINAL)
@@ -103,6 +105,7 @@ public:
QSize sizeHint() const override;
void setItem(const qt3dsdm::Qt3DSDMInstanceHandle &handle);
+ void setControlView(InspectorControlView *controlView);
QString itemIcon() const;
QString itemText() const;
QColor itemColor() const;
@@ -116,6 +119,8 @@ public:
PropertyInfo property() const;
bool isPropertyValueInvalid() const;
+
+ Q_INVOKABLE QColor showColorDialog(const QColor &color, int instance = 0, int handle = 0);
Q_INVOKABLE void setCurrentActionIndex(int index);
Q_INVOKABLE void setCurrentPropertyIndex(int handle, int index);
Q_INVOKABLE void addAction();
@@ -166,6 +171,7 @@ Q_SIGNALS:
void hasItemChanged();
void propertyValueInvalidChanged();
void dialogCurrentColorChanged(const QColor &newColor);
+ void handlerArgumentsChanged();
private Q_SLOTS:
void copyAction();
@@ -226,6 +232,7 @@ private:
bool m_propertyValueInvalid = true;
QColor m_currentColor;
QPointer<QWidget> m_activeBrowser = nullptr;
+ QPointer<InspectorControlView> m_inspectorControlView;
};
#endif // ACTIONVIEW_H
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericBaseColor.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericBaseColor.qml
index 8c184409..5b77dbdf 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericBaseColor.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericBaseColor.qml
@@ -69,7 +69,7 @@ RowLayout {
onClicked: {
root.listenToColorChanges = true;
_inspectorModel.suspendMaterialRename(true);
- root.selectedColor = _parentView.showColorDialog(rect.color, instance, handle);
+ root.selectedColor = _parentView.showColorDialog(rect.color);
root.listenToColorChanges = false;
_inspectorModel.suspendMaterialRename(false);
root.colorSelected();
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericFloat.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericFloat.qml
index 11ac38a5..edc66c14 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericFloat.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerGenericFloat.qml
@@ -42,6 +42,8 @@ RowLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
onValueChanged: {
// FloatTextField can set its text internally, thus breaking the binding, so
@@ -59,5 +61,7 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXY.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXY.qml
index 4406703f..e22bda8c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXY.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXY.qml
@@ -44,6 +44,8 @@ RowLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
spacing: 0
@@ -59,6 +61,8 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
Item { width: 20 }
@@ -75,6 +79,8 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZ.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZ.qml
index 50440dba..2ffa84bb 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZ.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZ.qml
@@ -46,6 +46,9 @@ RowLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
+
transformOrigin: Item.Center
spacing: 0
@@ -61,6 +64,8 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
Item { width: 10 }
@@ -77,6 +82,8 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
Item { width: 10 }
@@ -93,6 +100,8 @@ RowLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZW.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZW.qml
index 53ee4c33..d5d2b483 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZW.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyBaseXYZW.qml
@@ -48,6 +48,9 @@ ColumnLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
+
transformOrigin: Item.Center
spacing: 0
@@ -67,6 +70,8 @@ ColumnLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
Item { width: 10 }
@@ -83,6 +88,8 @@ ColumnLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
Item { width: 10 }
@@ -99,6 +106,8 @@ ColumnLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
@@ -121,6 +130,8 @@ ColumnLayout {
decimalValue: numberOfDecimal
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZ.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZ.qml
index 6571f1d0..a123d7ad 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZ.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZ.qml
@@ -47,6 +47,8 @@ RowLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
StyledLabel {
id: labelItem
@@ -60,5 +62,7 @@ RowLayout {
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZW.qml b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZW.qml
index 0c098d53..82adb6aa 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZW.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/HandlerPropertyXYZW.qml
@@ -49,6 +49,8 @@ RowLayout {
signal editingFinished
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
StyledLabel {
id: labelItem
@@ -62,5 +64,7 @@ RowLayout {
onEditingFinished: root.editingFinished()
onPreviewValueChanged: root.previewValueChanged()
+ onTriggerUndo: root.triggerUndo()
+ onTriggerRedo: root.triggerRedo()
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/BasicObjects/BasicObjectsModel.cpp b/src/Authoring/Qt3DStudio/Palettes/BasicObjects/BasicObjectsModel.cpp
index 8694fda7..65274d7b 100644
--- a/src/Authoring/Qt3DStudio/Palettes/BasicObjects/BasicObjectsModel.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/BasicObjects/BasicObjectsModel.cpp
@@ -55,6 +55,7 @@ const QVector<BasicObjectItem> BasicObjectsModel::InitializeObjectModel()
{tr("Cone"), "Asset-Cone-Normal.png"_L1, OBJTYPE_MODEL, PRIMITIVETYPE_CONE},
{tr("Component"), "Asset-Component-Normal.png"_L1, OBJTYPE_COMPONENT, PRIMITIVETYPE_UNKNOWN},
{tr("Group"), "Asset-Group-Normal.png"_L1, OBJTYPE_GROUP, PRIMITIVETYPE_UNKNOWN},
+ {tr("Signal"), "Asset-Signal-Normal.png"_L1, OBJTYPE_SIGNAL, PRIMITIVETYPE_UNKNOWN},
{tr("Text"), "Asset-Text-Normal.png"_L1, OBJTYPE_TEXT, PRIMITIVETYPE_UNKNOWN},
{tr("Camera"), "Asset-Camera-Normal.png"_L1, OBJTYPE_CAMERA, PRIMITIVETYPE_UNKNOWN},
{tr("Light"), "Asset-Light-Normal.png"_L1, OBJTYPE_LIGHT, PRIMITIVETYPE_UNKNOWN},
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.cpp b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.cpp
index 17fbb468..4542f72d 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.cpp
@@ -28,6 +28,7 @@
#include "InspectorControlModel.h"
#include "StudioApp.h"
+#include "MainFrm.h"
#include "Core.h"
#include "Doc.h"
#include "InspectorGroup.h"
@@ -128,7 +129,7 @@ CInspectableBase *InspectorControlModel::inspectable() const
}
qt3dsdm::Qt3DSDMInstanceHandle InspectorControlModel::getReferenceMaterial(
- CInspectableBase *inspectable) const
+ CInspectableBase *inspectable) const
{
if (inspectable)
return getBridge()->getMaterialReference(inspectable->getInstance());
@@ -136,6 +137,23 @@ qt3dsdm::Qt3DSDMInstanceHandle InspectorControlModel::getReferenceMaterial(
return 0;
}
+qt3dsdm::Qt3DSDMInstanceHandle InspectorControlModel::getReferenceMaterialRecursively(
+ CInspectableBase *inspectable) const
+{
+ if (inspectable) {
+ auto bridge = getBridge();
+ auto refMaterial = bridge->getMaterialReference(inspectable->getInstance());
+ auto type = bridge->GetObjectType(refMaterial);
+ while (type == OBJTYPE_REFERENCEDMATERIAL) {
+ refMaterial = bridge->getMaterialReference(refMaterial);
+ type = bridge->GetObjectType(refMaterial);
+ }
+ return refMaterial;
+ }
+
+ return 0;
+}
+
void InspectorControlModel::notifyPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty)
{
@@ -164,6 +182,7 @@ void InspectorControlModel::notifyPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle
if (property->m_property == inProperty || imageInstance == inInstance) {
updatePropertyValue(property);
changed = true;
+ updateValidState(property);
}
}
}
@@ -258,6 +277,7 @@ void InspectorControlModel::addMaterial()
i++;
absPath = path + QString::number(i) + extension;
}
+ const auto relPath = doc->GetRelativePathToDoc(absPath);
qt3dsdm::Qt3DSDMInstanceHandle newMaterial;
{
@@ -278,15 +298,13 @@ void InspectorControlModel::addMaterial()
doc->SelectDataModelObject(newMaterial);
const auto type = getBridge()->GetObjectType(instance);
- if (type == OBJTYPE_REFERENCEDMATERIAL) {
- sceneEditor->setMaterialReferenceByPath(instance, absPath);
- const auto relPath = doc->GetRelativePathToDoc(absPath);
- sceneEditor->setMaterialSourcePath(instance, Q3DStudio::CString::fromQString(relPath));
- sceneEditor->SetName(instance, getBridge()->GetName(newMaterial, true));
-
- doc->GetStudioSystem()->GetFullSystemSignalSender()->SendInstancePropertyValue(
- instance, getBridge()->GetNameProperty());
- }
+ if (type != OBJTYPE_REFERENCEDMATERIAL)
+ sceneEditor->SetMaterialType(instance, QStringLiteral("Referenced Material"));
+ sceneEditor->setMaterialReferenceByPath(instance, absPath);
+ sceneEditor->SetName(instance, getBridge()->GetName(newMaterial, true));
+ sceneEditor->setMaterialSourcePath(instance, Q3DStudio::CString::fromQString(relPath));
+ doc->GetStudioSystem()->GetFullSystemSignalSender()->SendInstancePropertyValue(
+ instance, getBridge()->GetNameProperty());
}
void InspectorControlModel::duplicateMaterial()
@@ -303,7 +321,7 @@ void InspectorControlModel::duplicateMaterial()
auto material = instance;
if (type == OBJTYPE_REFERENCEDMATERIAL)
- material = getReferenceMaterial(m_inspectableBase);
+ material = getReferenceMaterialRecursively(m_inspectableBase);
if (material.Valid()) {
const auto sceneEditor = doc->getSceneEditor();
@@ -320,6 +338,7 @@ void InspectorControlModel::duplicateMaterial()
materialName = originalMaterialName + QString::number(i);
absPath = sceneEditor->getMaterialFilePath(materialName);
}
+ const auto relPath = doc->GetRelativePathToDoc(absPath);
qt3dsdm::Qt3DSDMInstanceHandle duplicate;
{
@@ -341,14 +360,29 @@ void InspectorControlModel::duplicateMaterial()
Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, tr("Set Material Type")));
doc->SelectDataModelObject(duplicate);
- if (type == OBJTYPE_REFERENCEDMATERIAL) {
- scopedEditor->setMaterialReferenceByPath(instance, absPath);
- const auto relPath = doc->GetRelativePathToDoc(absPath);
- scopedEditor->setMaterialSourcePath(instance, Q3DStudio::CString::fromQString(relPath));
- scopedEditor->SetName(instance, getBridge()->GetName(duplicate, true));
- doc->GetStudioSystem()->GetFullSystemSignalSender()->SendInstancePropertyValue(
- instance, getBridge()->GetNameProperty());
+ // Change all material that reference this material to basic materials too
+ Q3DStudio::CString relPathCString = Q3DStudio::CString::fromQString(relPath);
+ Q3DStudio::CString duplicateName = getBridge()->GetName(duplicate, true);
+ auto nameProperty = getBridge()->GetNameProperty();
+ QVector<qt3dsdm::Qt3DSDMInstanceHandle> refMats;
+ doc->getSceneReferencedMaterials(doc->GetSceneInstance(), refMats);
+ for (auto &refMat : qAsConst(refMats)) {
+ if (getBridge()->getMaterialReference(refMat) == instance) {
+ scopedEditor->setMaterialReferenceByPath(refMat, absPath);
+ scopedEditor->setMaterialSourcePath(refMat, relPathCString);
+ scopedEditor->SetName(refMat, duplicateName);
+ doc->GetStudioSystem()->GetFullSystemSignalSender()->SendInstancePropertyValue(
+ refMat, nameProperty);
+ }
}
+
+ if (type != OBJTYPE_REFERENCEDMATERIAL)
+ sceneEditor->SetMaterialType(instance, QStringLiteral("Referenced Material"));
+ scopedEditor->setMaterialReferenceByPath(instance, absPath);
+ scopedEditor->setMaterialSourcePath(instance, relPathCString);
+ scopedEditor->SetName(instance, duplicateName);
+ doc->GetStudioSystem()->GetFullSystemSignalSender()->SendInstancePropertyValue(
+ instance, nameProperty);
}
}
@@ -371,6 +405,7 @@ void InspectorControlModel::updateMaterialValues(const QStringList &values, int
Q_EMIT item->valuesChanged();
// Changing values resets the selected index, so pretend the value has also changed
Q_EMIT item->valueChanged();
+ updateValidState(item);
}
}
}
@@ -412,6 +447,7 @@ void InspectorControlModel::setMatDatas(const std::vector<Q3DStudio::CFilePath>
m_matDatas.clear();
const auto doc = g_StudioApp.GetCore()->GetDoc();
+ bool forceModified = false;
bool isDocModified = doc->isModified();
const auto sceneEditor = doc->getSceneEditor();
if (!sceneEditor)
@@ -430,6 +466,8 @@ void InspectorControlModel::setMatDatas(const std::vector<Q3DStudio::CFilePath>
const QString relativePath = path.toQString();
const Q3DStudio::CFilePath absolutePath
= Q3DStudio::CFilePath::CombineBaseAndRelative(doc->GetDocumentDirectory(), path);
+ const QDir projDir = QDir(g_StudioApp.GetCore()->getProjectFile().getProjectPath());
+ const QString projRelativePath = projDir.relativeFilePath(absolutePath.toQString());
QString name;
QMap<QString, QString> values;
@@ -442,19 +480,21 @@ void InspectorControlModel::setMatDatas(const std::vector<Q3DStudio::CFilePath>
bool needRewrite = false;
if (values.contains(QStringLiteral("path"))) {
const QString oldPath = values[QStringLiteral("path")];
- needRewrite = oldPath != absolutePath.toQString();
- if (!QFileInfo(oldPath).exists()) {
+ needRewrite = oldPath != projRelativePath;
+ const QString oldAbsolutePath = projDir.absoluteFilePath(oldPath);
+ if (!QFileInfo(oldAbsolutePath).exists()) {
const auto instance = sceneEditor->getMaterial(oldPath);
if (instance.Valid()) {
const QString oldName = sceneEditor->GetName(instance).toQString();
const QString newName = sceneEditor
- ->getMaterialNameFromFilePath(relativePath);
+ ->getMaterialNameFromFilePath(projRelativePath);
const QString actualPath = sceneEditor
->getFilePathFromMaterialName(oldName);
- if (actualPath == oldPath) {
+ if (projDir.relativeFilePath(actualPath) == oldPath) {
doc->queueMaterialRename(oldName, newName);
Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, tr("Set Name"))
- ->setMaterialNameByPath(instance, relativePath);
+ ->setMaterialNameByPath(instance, projRelativePath);
+ forceModified = true;
}
}
}
@@ -491,7 +531,10 @@ void InspectorControlModel::setMatDatas(const std::vector<Q3DStudio::CFilePath>
sceneEditor->removeDeletedFromMaterialContainer();
// Modified flag has to be restored because of the hidden transaction
- doc->SetModifiedFlag(isDocModified);
+ if (!forceModified)
+ doc->SetModifiedFlag(isDocModified);
+ else
+ doc->SetModifiedFlag(true);
m_cachedMatDatas = matDatas;
}
@@ -683,7 +726,7 @@ InspectorControlBase *InspectorControlModel::createShaderItem(
break;
}
}
-
+ updateValidState(item);
return item;
}
@@ -739,6 +782,10 @@ InspectorControlBase* InspectorControlModel::createItem(Qt3DSDMInspectable *insp
if (title == "Name" && isBasicMaterial())
return nullptr;
+ // Hide everything else than name for signals
+ if (title != "Name" && getBridge()->IsSignalInstance(inspectable->getInstance()))
+ return nullptr;
+
InspectorControlBase *item = new InspectorControlBase;
item->m_property = metaProperty.m_Property;
item->m_instance = inspectable->GetGroupInstance(groupIndex);
@@ -792,11 +839,6 @@ InspectorControlBase* InspectorControlModel::createItem(Qt3DSDMInspectable *insp
std::bind(&InspectorControlModel::updateControlledToggleState, this, item)));
}
- if (item->m_propertyType == qt3dsdm::AdditionalMetaDataType::Import) {
- item->m_connections.push_back(signalProvider->ConnectControlledToggled(
- std::bind(&InspectorControlModel::updateValidState, this, item)));
- }
-
// synchronize the value itself
updatePropertyValue(item);
updateValidState(item);
@@ -880,7 +922,7 @@ void InspectorControlModel::updateAnimateToggleState(InspectorControlBase* inIte
}
}
-void InspectorControlModel::updateValidState(InspectorControlBase *inItem)
+void InspectorControlModel::updateValidState(InspectorControlBase *inItem) const
{
const auto bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()
->GetClientDataModelBridge();
@@ -892,6 +934,23 @@ void InspectorControlModel::updateValidState(InspectorControlBase *inItem)
Q_EMIT inItem->validDataChanged();
}
}
+
+ // Check the validity of shader.
+ if (inItem->m_title == tr("Shader")) {
+ QString err;
+ g_StudioApp.getRenderer().getObjectError(inItem->m_instance, err);
+ if (!err.isEmpty()) {
+ inItem->m_tooltip = err;
+ inItem->m_valid = false;
+ Q_EMIT inItem->validDataChanged();
+ Q_EMIT inItem->tooltipChanged();
+ } else {
+ inItem->m_tooltip = tr("Shader being used");
+ inItem->m_valid = true;
+ Q_EMIT inItem->validDataChanged();
+ Q_EMIT inItem->tooltipChanged();
+ }
+ }
}
bool InspectorControlModel::isTreeRebuildRequired(CInspectableBase* inspectBase)
@@ -1156,25 +1215,44 @@ void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) c
return;
propertySystem->GetInstancePropertyValue(instance, element->m_property, value);
- if (value.getType() == qt3dsdm::DataModelDataType::None)
+ if (value.getType() == qt3dsdm::DataModelDataType::None) {
+ updateValidState(element); // Shader property has type none, still need to update valid
return;
+ }
const auto metaDataProvider = doc->GetStudioSystem()->GetActionMetaData();
info = metaDataProvider->GetMetaDataPropertyInfo(
metaDataProvider->GetMetaDataProperty(instance, element->m_property));
}
-
+ bool isTexture = info.hasValue()
+ && info->GetAdditionalType() == qt3dsdm::AdditionalMetaDataType::Texture;
bool skipEmits = false;
switch (element->m_dataType) {
case qt3dsdm::DataModelDataType::String: {
- QString stringValue = qt3dsdm::get<QString>(value);
- if (getBridge()->isInsideMaterialContainer(element->m_instance)) {
- int index = stringValue.lastIndexOf(QLatin1Char('/'));
- if (index != -1)
- stringValue = stringValue.mid(index + 1);
- }
+ if (value.getType() == qt3dsdm::DataModelDataType::Long4) {
+ qt3dsdm::Option<qt3dsdm::SLong4> guid = qt3dsdm::get<qt3dsdm::SLong4>(value);
+ qt3dsdm::Qt3DSDMInstanceHandle imageInstance = doc->GetDocumentReader()
+ .GetInstanceForGuid(guid);
+ if (imageInstance.Valid()) {
+ Q3DStudio::CString path = doc->GetDocumentReader().GetSourcePath(imageInstance);
+ Q3DStudio::CFilePath relPath(path);
+ element->m_value = QVariant(relPath.GetFileName().toQString());
+ } else {
+ element->m_value = QVariant(QString());
+ }
+ } else {
+ QString stringValue = qt3dsdm::get<QString>(value);
+ if (getBridge()->isInsideMaterialContainer(element->m_instance)) {
+ int index = stringValue.lastIndexOf(QLatin1Char('/'));
+ if (index != -1)
+ stringValue = stringValue.mid(index + 1);
+ }
- element->m_value = stringValue;
+ if (!isTexture)
+ element->m_value = stringValue;
+ else
+ element->m_value = {};
+ }
}
Q_FALLTHROUGH(); // fall-through for other String-derived datatypes
@@ -1263,8 +1341,20 @@ void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) c
QString meshValue = QFileInfo(qt3dsdm::get<QString>(value)).fileName();
element->m_value = meshValue.startsWith('#'_L1) ? meshValue.mid(1) : meshValue;
} else if (element->m_propertyType == qt3dsdm::AdditionalMetaDataType::Texture) {
- QFileInfo fileInfo(qt3dsdm::get<QString>(value));
- element->m_value = fileInfo.fileName();
+ if (value.getType() == qt3dsdm::DataModelDataType::Long4) {
+ qt3dsdm::Option<qt3dsdm::SLong4> guid = qt3dsdm::get<qt3dsdm::SLong4>(value);
+ qt3dsdm::Qt3DSDMInstanceHandle imageInstance = doc->GetDocumentReader()
+ .GetInstanceForGuid(guid);
+ if (imageInstance.Valid()) {
+ Q3DStudio::CString path = doc->GetDocumentReader().GetSourcePath(imageInstance);
+ Q3DStudio::CFilePath relPath(path);
+ element->m_value = QVariant(relPath.GetFileName().toQString());
+ } else {
+ element->m_value = QVariant(QString());
+ }
+ } else {
+ element->m_value = {};
+ }
} else if (element->m_propertyType == qt3dsdm::AdditionalMetaDataType::PathBuffer) {
element->m_value = qt3dsdm::get<QString>(value);
} else if (element->m_propertyType == qt3dsdm::AdditionalMetaDataType::String) {
@@ -1413,6 +1503,8 @@ void InspectorControlModel::updatePropertyValue(InspectorControlBase *element) c
// not the controlled flag nor the tooltip
if (element->m_controllable)
updateControlledToggleState(element);
+
+ updateValidState(element);
}
void InspectorControlModel::refreshRenderables()
@@ -1460,10 +1552,9 @@ void InspectorControlModel::refresh()
for (int p = 0; p < group.controlElements.count(); ++p) {
QVariant& element = group.controlElements[p];
InspectorControlBase *property = element.value<InspectorControlBase *>();
- if (property->m_property.Valid()) {
+ if (property->m_property.Valid() || property->m_title == tr("Shader")) {
updatePropertyValue(property);
updateControlledToggleState(property);
- updateValidState(property);
}
}
}
@@ -1609,6 +1700,10 @@ void InspectorControlModel::setShaderValue(long instance, int handle, const QVar
}
saveIfMaterial(instance);
+
+ // Make sure that inspector panel is up-to-date with regards to result of shader compilation
+ // errors.
+ rebuildTree();
}
void InspectorControlModel::setMatDataValue(long instance, int handle, const QVariant &value)
@@ -1730,7 +1825,8 @@ void InspectorControlModel::setPropertyValue(long instance, int handle, const QV
&& ((newName.Find('/') != Q3DStudio::CString::ENDOFSTRING
|| newName.Find('#') != Q3DStudio::CString::ENDOFSTRING
|| newName.Find(':') != Q3DStudio::CString::ENDOFSTRING)
- || m_suspendMaterialRename)) {
+ || m_suspendMaterialRename)
+ || newName.toQString().contains(QChar('.'))) {
return;
}
qt3dsdm::Qt3DSDMInstanceHandle parentInstance = getBridge()
@@ -2023,6 +2119,16 @@ QHash<int, QByteArray> InspectorControlModel::roleNames() const
return names;
}
+void InspectorControlModel::undo()
+{
+ g_StudioApp.m_pMainWnd->OnEditUndo();
+}
+
+void InspectorControlModel::redo()
+{
+ g_StudioApp.m_pMainWnd->OnEditRedo();
+}
+
InspectorControlBase::~InspectorControlBase()
{
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.h b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.h
index b1c13240..bcd4ce22 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlModel.h
@@ -143,7 +143,6 @@ public:
bool controlled);
void notifyPropertyChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty);
- void updateValidState(InspectorControlBase *inItem);
Q_INVOKABLE void setMaterialTypeValue(long instance, int handle, const QVariant &value);
Q_INVOKABLE void setShaderValue(long instance, int handle, const QVariant &value);
@@ -163,6 +162,8 @@ public:
Q_INVOKABLE void duplicateMaterial();
Q_INVOKABLE bool isGroupCollapsed(int groupIdx) const;
Q_INVOKABLE void updateGroupCollapseState(int groupIdx, bool state);
+ Q_INVOKABLE void undo();
+ Q_INVOKABLE void redo();
private:
struct GroupInspectorControl
@@ -204,6 +205,8 @@ private:
void updateMaterialValues(const QStringList &values, int elementIndex,
bool updatingShaders = false);
qt3dsdm::Qt3DSDMInstanceHandle getReferenceMaterial(CInspectableBase *inspectable) const;
+ qt3dsdm::Qt3DSDMInstanceHandle getReferenceMaterialRecursively(
+ CInspectableBase *inspectable) const;
void updateShaderValues();
void updateMatDataValues();
void updatePropertyValue(InspectorControlBase *element) const;
@@ -211,6 +214,7 @@ private:
void refreshTree();
void updateAnimateToggleState(InspectorControlBase *inItem);
void updateControlledToggleState(InspectorControlBase *inItem) const;
+ void updateValidState(InspectorControlBase *inItem) const;
QStringList materialTypeValues() const;
QStringList shaderValues() const;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.cpp b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.cpp
index f956021e..f991f467 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.cpp
@@ -88,6 +88,13 @@ InspectorControlView::InspectorControlView(const QSize &preferredSize, QWidget *
dispatch->AddPresentationChangeListener(this);
dispatch->AddDataModelListener(this);
+ m_shaderStatusUpdateTimer.setSingleShot(true);
+ m_shaderStatusUpdateTimer.setInterval(3000);
+
+ connect(&m_shaderStatusUpdateTimer, &QTimer::timeout, [&](){
+ m_inspectorControlModel->refresh();
+ });
+
connect(m_meshChooserView, &MeshChooserView::meshSelected, this,
[this] (int handle, int instance, const QString &name) {
if (name.startsWith(QLatin1Char('#'))) {
@@ -170,6 +177,9 @@ void InspectorControlView::onFilesChanged(
L"material", L"shader", L"materialdef",
nullptr
};
+ static const wchar_t *effectExtensions[] = {
+ L"effect", nullptr
+ };
static const wchar_t *fontExtensions[] = {
L"ttf", L"otf",
nullptr
@@ -189,6 +199,8 @@ void InspectorControlView::onFilesChanged(
qt3dsdm::binary_sort_insert_unique(m_fileList, relativePath);
else if (record.m_ModificationType == Q3DStudio::FileModificationType::Destroyed)
qt3dsdm::binary_sort_erase(m_fileList, relativePath);
+ else
+ m_shaderStatusUpdateTimer.start();
} else if (isInList(fontExtensions, record.m_File.GetExtension())) {
if (record.m_ModificationType == Q3DStudio::FileModificationType::Created
|| record.m_ModificationType == Q3DStudio::FileModificationType::Destroyed) {
@@ -200,6 +212,8 @@ void InspectorControlView::onFilesChanged(
g_StudioApp.GetCore()->getProjectFile().loadSubpresentationsAndDatainputs(
g_StudioApp.m_subpresentations, g_StudioApp.m_dataInputDialogItems);
m_inspectorControlModel->refreshRenderables();
+ } else if (isInList(effectExtensions, record.m_File.GetExtension())) {
+ m_shaderStatusUpdateTimer.start();
}
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.h b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.h
index ff969c03..6bc7d6fb 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.h
@@ -133,6 +133,7 @@ private:
std::vector<std::shared_ptr<qt3dsdm::ISignalConnection>> m_connections;
QColor m_backgroundColor;
+ QTimer m_shaderStatusUpdateTimer;
VariantsGroupModel *m_variantsGroupModel = nullptr;
InspectorControlModel *m_inspectorControlModel = nullptr;
CInspectableBase *m_inspectableBase = nullptr;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.qml b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.qml
index d6e89ba3..d5570fc7 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/InspectorControlView.qml
@@ -192,7 +192,7 @@ Rectangle {
property int indexOfThisDelegate: index
- width: parent.width
+ width: groupElements.width
height: items.height
color: "transparent";
ListView.delayRemove: true
@@ -394,11 +394,13 @@ Rectangle {
readonly property var modelData: model.modelData
text: model.modelData.title
- // Color picked from DataInput icon
- color: model.modelData.controlled?
- _dataInputColor
- : _parentView.titleColor(modelData.instance,
- modelData.handle)
+ // Label is showing "controlled", "invalid data" or
+ // ordinary text color.
+ color: model.modelData.controlled
+ ? _dataInputColor : model.modelData.validData
+ ? _parentView.titleColor(modelData.instance,
+ modelData.handle)
+ : _invalidDataIndicatorColor
Layout.alignment: Qt.AlignTop
@@ -479,7 +481,7 @@ Rectangle {
if (modelData.propertyType === AdditionalMetaDataType.Font)
return fontDropDown;
if (modelData.propertyType === AdditionalMetaDataType.Texture)
- return textureChooser;
+ return imageChooser;
if (modelData.propertyType === AdditionalMetaDataType.String)
return editLine;
if (modelData.propertyType === AdditionalMetaDataType.None)
@@ -701,6 +703,12 @@ Rectangle {
Qt.vector4d(valueX, valueY, valueZ, valueW),
false);
}
+ onTriggerUndo: {
+ _inspectorModel.undo();
+ }
+ onTriggerRedo: {
+ _inspectorModel.redo();
+ }
}
}
}
@@ -738,6 +746,12 @@ Rectangle {
_inspectorModel.setPropertyValue(parent.instance, parent.handle,
Qt.vector3d(valueX, valueY, valueZ), false);
}
+ onTriggerUndo: {
+ _inspectorModel.undo();
+ }
+ onTriggerRedo: {
+ _inspectorModel.redo();
+ }
}
}
}
@@ -772,6 +786,12 @@ Rectangle {
_inspectorModel.setPropertyValue(parent.instance, parent.handle,
Qt.vector2d(valueX, valueY), false);
}
+ onTriggerUndo: {
+ _inspectorModel.undo();
+ }
+ onTriggerRedo: {
+ _inspectorModel.redo();
+ }
}
}
}
@@ -808,6 +828,12 @@ Rectangle {
_inspectorModel.setPropertyValue(parent.instance, parent.handle,
Number(text), true);
}
+ onTriggerUndo: {
+ _inspectorModel.undo();
+ }
+ onTriggerRedo: {
+ _inspectorModel.redo();
+ }
}
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/TextureChooserView.cpp b/src/Authoring/Qt3DStudio/Palettes/Inspector/TextureChooserView.cpp
index 8804e675..8b20b950 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Inspector/TextureChooserView.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/TextureChooserView.cpp
@@ -91,8 +91,20 @@ QString TextureChooserView::currentDataModelPath() const
qt3dsdm::SValue value;
propertySystem->GetInstancePropertyValue(m_instance, m_handle, value);
-
- const QString path = qt3dsdm::get<QString>(value);
+ QString path;
+ if (value.getType() == qt3dsdm::DataModelDataType::Long4) {
+ qt3dsdm::Option<qt3dsdm::SLong4> guid = qt3dsdm::get<qt3dsdm::SLong4>(value);
+ qt3dsdm::Qt3DSDMInstanceHandle imageInstance = doc->GetDocumentReader()
+ .GetInstanceForGuid(guid);
+ if (imageInstance.Valid()) {
+ Q3DStudio::CFilePath relPath(doc->GetDocumentReader().GetSourcePath(imageInstance));
+ path = relPath.GetFileName().toQString();
+ } else {
+ path = QString();
+ }
+ } else {
+ path = qt3dsdm::get<QString>(value);
+ }
// An empty value can sometimes be represented by a relative path either to project root or the
// presentation file, such as"./" or "../", so let's just consider all directory paths as empty
diff --git a/src/Authoring/Qt3DStudio/Palettes/PaletteManager.cpp b/src/Authoring/Qt3DStudio/Palettes/PaletteManager.cpp
index 3f1a8c52..e30512e9 100644
--- a/src/Authoring/Qt3DStudio/Palettes/PaletteManager.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/PaletteManager.cpp
@@ -158,6 +158,7 @@ CPaletteManager::CPaletteManager(CMainFrame *inMainFrame, QObject *parent)
QSize(defaultRightDockWidth, inMainFrame->height() - defaultProjectHeight),
m_inspectorDock);
inspectorView->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ actionView->setControlView(inspectorView);
m_inspectorDock->setWidget(inspectorView);
inMainFrame->addDockWidget(Qt::RightDockWidgetArea, m_inspectorDock);
inMainFrame->tabifyDockWidget(m_inspectorDock, m_actionDock);
diff --git a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.cpp b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.cpp
index ab7d3e45..9d608276 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.cpp
@@ -50,6 +50,7 @@
#include "IDragable.h"
#include "IObjectReferenceHelper.h"
#include "IDirectoryWatchingSystem.h"
+#include "IStudioRenderer.h"
ProjectFileSystemModel::ProjectFileSystemModel(QObject *parent) : QAbstractListModel(parent)
, m_model(new QFileSystemModel(this))
@@ -65,8 +66,15 @@ ProjectFileSystemModel::ProjectFileSystemModel(QObject *parent) : QAbstractListM
m_projectReferencesUpdateTimer.setSingleShot(true);
m_projectReferencesUpdateTimer.setInterval(0);
+ m_shaderCheckTimer.setSingleShot(true);
+ m_shaderCheckTimer.setInterval(3000);
+
connect(&m_projectReferencesUpdateTimer, &QTimer::timeout,
this, &ProjectFileSystemModel::updateProjectReferences);
+ connect(&m_shaderCheckTimer, &QTimer::timeout, [&](){
+ checkShaders();
+ updateRoles({IsProjectReferencedRole, HasWarningRole, ExtraIconRole});
+ });
}
QHash<int, QByteArray> ProjectFileSystemModel::roleNames() const
@@ -80,6 +88,7 @@ QHash<int, QByteArray> ProjectFileSystemModel::roleNames() const
modelRoleNames.insert(ExpandedRole, "_expanded");
modelRoleNames.insert(FileIdRole, "_fileId");
modelRoleNames.insert(ExtraIconRole, "_extraIcon");
+ modelRoleNames.insert(HasWarningRole, "_hasWarning");
return modelRoleNames;
}
@@ -137,10 +146,16 @@ QVariant ProjectFileSystemModel::data(const QModelIndex &index, int role) const
if (getIconType(path) & (OBJTYPE_PRESENTATION | OBJTYPE_QML_STREAM)) {
if (presentationId(path).isEmpty())
return QStringLiteral("warning.png");
+ } else if (!item.error.isEmpty()) {
+ return QStringLiteral("warning.png");
}
return {};
}
+ case HasWarningRole: {
+ return !item.error.isEmpty();
+ }
+
default:
return m_model->data(item.index, role);
}
@@ -168,6 +183,12 @@ bool ProjectFileSystemModel::isRefreshable(int row) const
return path.endsWith(QLatin1String(".import"));
}
+bool ProjectFileSystemModel::isCollapsable(int row) const
+{
+ auto &item = m_items[row];
+ return item.expanded;
+}
+
void ProjectFileSystemModel::updateReferences()
{
m_references.clear();
@@ -208,8 +229,38 @@ void ProjectFileSystemModel::updateReferences()
std::for_each(renderableList.begin(), renderableList.end(), addReferencesRenderable);
m_references.insert(projectPath);
+ updateRoles({IsReferencedRole, Qt::DecorationRole, HasWarningRole, ExtraIconRole});
+}
+
+void ProjectFileSystemModel::showItemError(const QModelIndex index)
+{
+ const auto &item = m_items.at(index.row());
+ // Currently we only show shader compilation errors.
+ g_StudioApp.showShaderCompileError(item.error);
+}
+
+void ProjectFileSystemModel::checkShaders(const int startRow, const int endRow)
+{
+ auto bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ qt3dsdm::TInstanceHandleList theShaderInstances(bridge->GetShaderInstances());
+
+ for (const auto &instance : theShaderInstances) {
+ auto sourcepath = bridge->GetSourcePath(instance);
+ const QString relativePath = g_StudioApp.GetCore()->GetDoc()
+ ->GetResolvedPathToDoc(sourcepath);
+ auto currRow = rowForPath(relativePath);
- updateRoles({IsReferencedRole, Qt::DecorationRole});
+ if (currRow >= startRow && startRow == -1 && currRow <= endRow)
+ continue;
+
+ QString err;
+ auto res = g_StudioApp.getRenderer().getObjectError(instance, err);
+
+ if (!err.isEmpty() && currRow != -1)
+ m_items[currRow].error = bridge->GetSourcePath(instance) + QStringLiteral("\n\n") + err;
+ else if (currRow != -1 && res)
+ m_items[currRow].error = QString();
+ }
}
/**
@@ -370,7 +421,7 @@ void ProjectFileSystemModel::updateProjectReferences()
}
m_projectReferencesUpdateMap.clear();
- updateRoles({IsProjectReferencedRole});
+ updateRoles({IsProjectReferencedRole, HasWarningRole, ExtraIconRole});
}
void ProjectFileSystemModel::getQmlAssets(const QObject *qmlNode,
@@ -570,6 +621,9 @@ void ProjectFileSystemModel::showModelChildItems(const QModelIndex &parentIndex,
endInsertRows();
+ checkShaders(startRow, startRow + insertCount - 1);
+ updateRoles({HasWarningRole, ExtraIconRole});
+
// also fetch children so we're notified when files are added or removed in immediate subdirs
for (const auto &childIndex : rowsToInsert) {
if (m_model->hasChildren(childIndex) && m_model->canFetchMore(childIndex))
@@ -669,6 +723,9 @@ void ProjectFileSystemModel::importUrls(const QList<QUrl> &urls, int row, bool a
// Batch update all imported presentation nodes
g_StudioApp.GetCore()->getProjectFile().addPresentationNodes(presentationNodes);
+ checkShaders(row, row);
+ updateRoles({HasWarningRole, ExtraIconRole});
+
// Add new data inputs that are missing from project's data inputs. Duplicates are ignored,
// even if they are different type.
QMapIterator<QString, CDataInputDialogItem *> diIt(importedDataInputs);
@@ -1299,6 +1356,7 @@ void ProjectFileSystemModel::onFilesChanged(
m_projectReferencesUpdateMap.insert(filePath, false);
}
m_projectReferencesUpdateTimer.start();
+ m_shaderCheckTimer.start();
}
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.h b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.h
index 46ad2d12..8fb63805 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectFileSystemModel.h
@@ -59,7 +59,8 @@ public:
DepthRole,
ExpandedRole,
FileIdRole,
- ExtraIconRole
+ ExtraIconRole,
+ HasWarningRole
};
void setRootPath(const QString &path);
@@ -72,6 +73,7 @@ public:
QString filePath(int row) const;
bool isRefreshable(int row) const;
+ bool isCollapsable(int row) const;
bool isCurrentPresentation(const QString &path) const;
bool isInitialPresentation(const QString &path) const;
QString presentationId(const QString &path) const;
@@ -89,6 +91,8 @@ public:
void asyncUpdateReferences();
void onFilesChanged(const Q3DStudio::TFileModificationList &inFileModificationList);
void clearModelData();
+ void checkShaders(const int startRow = -1, const int endRow = -1);
+ void showItemError(const QModelIndex index);
Q_SIGNALS:
void modelChanged(QAbstractItemModel *model);
@@ -140,6 +144,7 @@ private:
bool expanded;
TreeItem *parent;
int childCount;
+ QString error;
};
QFileSystemModel *m_model = nullptr;
@@ -160,6 +165,7 @@ private:
// Value: if true, uip was modified or created. If false, it was removed.
QHash<QString, bool> m_projectReferencesUpdateMap;
QTimer m_projectReferencesUpdateTimer;
+ QTimer m_shaderCheckTimer;
std::shared_ptr<qt3dsdm::ISignalConnection> m_directoryConnection;
QString m_selectFile; // file to be selected on next layout change
};
diff --git a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.cpp b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.cpp
index 7946e8a2..203952bc 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.cpp
@@ -266,6 +266,22 @@ void ProjectView::mousePressEvent(QMouseEvent *event)
QQuickWidget::mousePressEvent(event);
}
+void ProjectView::keyReleaseEvent(QKeyEvent *event)
+{
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ if (m_selected >= 0) {
+ auto key = ke->key();
+ if (key == Qt::Key_Delete)
+ deleteFile(m_selected);
+ else if (key == Qt::Key_Right)
+ m_ProjectModel->expand(m_selected);
+ else if (key == Qt::Key_Left && m_ProjectModel->isCollapsable(m_selected))
+ m_ProjectModel->collapse(m_selected);
+ } else {
+ QQuickWidget::keyReleaseEvent(event);
+ }
+}
+
void ProjectView::startDrag(QQuickItem *item, int row)
{
item->grabMouse(); // Grab to make sure we can ungrab after the drag
@@ -302,6 +318,11 @@ void ProjectView::editPresentationId(int row, bool qmlStream)
dlg.exec();
}
+void ProjectView::showSpecificShaderError(const int row)
+{
+ m_ProjectModel->showItemError(m_ProjectModel->index(row));
+}
+
void ProjectView::renamePresentation(int row, bool qmlStream)
{
QString relativePresPath = QDir(g_StudioApp.GetCore()->getProjectFile().getProjectPath())
@@ -453,6 +474,11 @@ void ProjectView::openFile(int row)
});
}
+void ProjectView::setSelected(int row)
+{
+ m_selected = row;
+}
+
void ProjectView::refreshImport(int row) const
{
if (row == -1)
@@ -589,5 +615,6 @@ void ProjectView::deleteFile(int row) const
void ProjectView::rebuild()
{
+ m_selected = -1;
m_ProjectModel->setRootPath(g_StudioApp.GetCore()->getProjectFile().getProjectPath());
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.h b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.h
index 8ed10a49..217aff1c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.h
@@ -71,6 +71,7 @@ public:
Q_INVOKABLE void showContextMenu(int x, int y, int index);
Q_INVOKABLE bool toolTipsEnabled();
Q_INVOKABLE void openFile(int row);
+ Q_INVOKABLE void setSelected(int row);
void showContainingFolder(int row) const;
void copyPath(int row) const;
@@ -97,6 +98,7 @@ public:
QString presentationId(int row) const;
void setInitialPresentation(int row);
Q_INVOKABLE void editPresentationId(int row, bool qmlStream);
+ Q_INVOKABLE void showSpecificShaderError(const int row);
void renamePresentation(int row, bool qmlStream);
// CPresentationChangeListener
@@ -121,6 +123,7 @@ Q_SIGNALS:
protected:
void mousePressEvent(QMouseEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
private:
void initialize();
@@ -146,6 +149,7 @@ private:
QString m_qmlStreamDir;
QString m_assetImportDir;
QSize m_preferredSize;
+ int m_selected = -1;
};
#endif // PROJECTVIEW_H
diff --git a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.qml b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.qml
index 73c9481c..c72be3cc 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Project/ProjectView.qml
@@ -63,8 +63,10 @@ Rectangle {
anchors.fill: parent
clip: true
+ focus: true
ScrollBar.vertical: ScrollBar {}
+ keyNavigationEnabled: true
model: _parentView.projectModel
@@ -72,6 +74,7 @@ Rectangle {
// Try to keep something selected always
if ((currentIndex < 0 || currentIndex >= count) && count > 0)
currentIndex = 0;
+ _parentView.setSelected(currentIndex);
}
delegate: Rectangle {
@@ -79,12 +82,13 @@ Rectangle {
property bool dragging: false
property bool dragStarted: false
property point pressPoint
- width: parent.width
+ width: projectTree.width
height: 20
color: (index == projectTree.currentIndex || dragging) ? _selectionColor
: "transparent"
function handlePress(mouse, tryDrag) {
projectTree.currentIndex = model.index;
+ _parentView.setSelected(model.index);
if (mouse.button === Qt.LeftButton && tryDrag && _isDraggable) {
pressPoint = Qt.point(mouse.x, mouse.y);
@@ -102,6 +106,7 @@ Rectangle {
}
function handleClick(mouse) {
+ _parentView.setSelected(projectTree.currentIndex)
if (mouse.button === Qt.RightButton) {
var rootPoint = mapToItem(root, mouse.x, mouse.y);
_parentView.showContextMenu(rootPoint.x, rootPoint.y,
@@ -145,6 +150,7 @@ Rectangle {
acceptedButtons: Qt.LeftButton
onPressed: delegateItem.handlePress(mouse, false)
onClicked: {
+ _parentView.setSelected(index);
if (_expanded)
projectTree.model.collapse(index)
else
@@ -171,9 +177,11 @@ Rectangle {
id: fileNameLabel
text: _fileId ? fileName + " <" + _fileId + ">" : fileName;
color: {
- _isReferenced ? _textColor
- : _isProjectReferenced ? _projectReferencedColor
- : _disabledColor
+ _hasWarning ? _invalidDataIndicatorColor :
+ _isReferenced ? _textColor :
+ _isProjectReferenced ?
+ _projectReferencedColor
+ : _disabledColor
}
leftPadding: 2
@@ -205,13 +213,16 @@ Rectangle {
hoverEnabled: true
onPressed: delegateItem.handlePress(mouse, false)
onClicked: delegateItem.handleClick(mouse)
- onDoubleClicked: _parentView.editPresentationId(
- index, _parentView.isQmlStream(index))
+ onDoubleClicked:
+ _hasWarning ? _parentView.showSpecificShaderError(index)
+ : _parentView.editPresentationId(
+ index, _parentView.isQmlStream(index))
}
StyledTooltip {
- text: _parentView.isPresentation(index)
- ? qsTr("No presentation Id")
- : qsTr("No Qml stream Id")
+ text: _hasWarning ? qsTr("Shader error")
+ : _parentView.isPresentation(index)
+ ? qsTr("No presentation Id")
+ : qsTr("No Qml stream Id")
enabled: warningMouseArea.containsMouse
}
}
diff --git a/src/Authoring/Qt3DStudio/Palettes/Slide/SlideView.qml b/src/Authoring/Qt3DStudio/Palettes/Slide/SlideView.qml
index 7100ed8a..c3393702 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Slide/SlideView.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/Slide/SlideView.qml
@@ -198,9 +198,8 @@ Rectangle {
property int dragIndex
property bool held : false
- anchors.horizontalCenter: parent.horizontalCenter
height: delegateItem.height
- width: parent.width
+ width: slideList.width
acceptedButtons: Qt.RightButton | Qt.LeftButton
drag.target: held ? delegateItem : null
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItem.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItem.h
index 4308fb2b..2c8b6ecc 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItem.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/ITimelineItem.h
@@ -47,6 +47,13 @@ class ITimelineTimebar;
class ITimelineItem : public INamable
{
public:
+ enum class ActivateAction {
+ None = 0,
+ Activate = 1,
+ Deactivate = 2
+ };
+ Q_DECLARE_FLAGS(ActivateActions, ActivateAction)
+
virtual ~ITimelineItem() {}
virtual EStudioObjectType GetObjectType() const = 0;
@@ -65,6 +72,7 @@ public:
virtual bool HasAction(bool inMaster) = 0;
virtual bool ChildrenHasAction(bool inMaster) = 0;
virtual bool ComponentHasAction(bool inMaster) = 0;
+ virtual ActivateActions getActivateActions() = 0;
// subpresentations
virtual bool hasSubpresentation() const = 0;
@@ -72,4 +80,6 @@ public:
virtual ITimelineTimebar *GetTimebar() = 0;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ITimelineItem::ActivateActions)
+
#endif // INCLUDED_ITIMELINE_ITEM_H
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp
index e3483969..283f98e5 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.cpp
@@ -48,8 +48,8 @@
using namespace qt3dsdm;
-CMaterialTimelineItemBinding::CMaterialTimelineItemBinding(CTimelineTranslationManager *inMgr,
- Qt3DSDMInstanceHandle inDataHandle)
+CMaterialEffectTimelineItemBinding::CMaterialEffectTimelineItemBinding(
+ CTimelineTranslationManager *inMgr, Qt3DSDMInstanceHandle inDataHandle)
: Qt3DSDMTimelineItemBinding(inMgr, inDataHandle)
{
qt3dsdm::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
@@ -63,7 +63,8 @@ CMaterialTimelineItemBinding::CMaterialTimelineItemBinding(CTimelineTranslationM
AdditionalMetaDataType::Value theAdditionalMetaDataType =
thePropertySystem->GetAdditionalMetaDataType(inDataHandle, theProperty);
- if (theAdditionalMetaDataType == AdditionalMetaDataType::Image) {
+ if (theAdditionalMetaDataType == AdditionalMetaDataType::Image
+ || theAdditionalMetaDataType == AdditionalMetaDataType::Texture) {
TCharStr theName(thePropertySystem->GetName(theProperty));
TCharStr theFormalName(thePropertySystem->GetFormalName(inDataHandle, theProperty));
TNameFormalNamePair thePair = std::make_tuple(theName, theFormalName);
@@ -72,16 +73,16 @@ CMaterialTimelineItemBinding::CMaterialTimelineItemBinding(CTimelineTranslationM
}
}
-CMaterialTimelineItemBinding::~CMaterialTimelineItemBinding()
+CMaterialEffectTimelineItemBinding::~CMaterialEffectTimelineItemBinding()
{
}
-ITimelineTimebar *CMaterialTimelineItemBinding::GetTimebar()
+ITimelineTimebar *CMaterialEffectTimelineItemBinding::GetTimebar()
{ // No timebars on materials
return new CEmptyTimelineTimebar();
}
-bool CMaterialTimelineItemBinding::ShowToggleControls() const
+bool CMaterialEffectTimelineItemBinding::ShowToggleControls() const
{
// Materials have no toggle controls, by design
return false;
@@ -96,7 +97,7 @@ bool ImageSlotIsFilled(qt3dsdm::IPropertySystem *inPropertySystem, Qt3DSDMInstan
inPropertySystem->GetInstancePropertyValue(inInstance, theProperty, theValue);
// Prevent assertion down the path when changing from edited standard material to reference material
- if (qt3dsdm::GetValueType(theValue) == DataModelDataType::None)
+ if (qt3dsdm::GetValueType(theValue) != DataModelDataType::Long4)
return false;
SLong4 theLong4 = qt3dsdm::get<SLong4>(theValue);
@@ -106,7 +107,7 @@ bool ImageSlotIsFilled(qt3dsdm::IPropertySystem *inPropertySystem, Qt3DSDMInstan
return theReturn;
}
-long CMaterialTimelineItemBinding::GetChildrenCount()
+long CMaterialEffectTimelineItemBinding::GetChildrenCount()
{
long theReturnCount = 0;
if (m_TransMgr->GetStudioSystem()->IsInstance(m_DataHandle)) {
@@ -124,7 +125,7 @@ long CMaterialTimelineItemBinding::GetChildrenCount()
return theReturnCount;
}
-ITimelineItemBinding *CMaterialTimelineItemBinding::GetChild(long inIndex)
+ITimelineItemBinding *CMaterialEffectTimelineItemBinding::GetChild(long inIndex)
{
qt3dsdm::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
@@ -147,7 +148,7 @@ ITimelineItemBinding *CMaterialTimelineItemBinding::GetChild(long inIndex)
theImageProperty, std::get<1>(m_ImageNameFormalNamePairs[theSlotCursor]).wide_str());
}
-QList<ITimelineItemBinding *> CMaterialTimelineItemBinding::GetChildren()
+QList<ITimelineItemBinding *> CMaterialEffectTimelineItemBinding::GetChildren()
{
int childCount = GetChildrenCount();
QList<ITimelineItemBinding *> retlist;
@@ -158,7 +159,7 @@ QList<ITimelineItemBinding *> CMaterialTimelineItemBinding::GetChildren()
return retlist;
}
-void CMaterialTimelineItemBinding::OnAddChild(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
+void CMaterialEffectTimelineItemBinding::OnAddChild(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
{
using namespace qt3dsdm;
CClientDataModelBridge *theBridge = m_TransMgr->GetStudioSystem()->GetClientDataModelBridge();
@@ -169,18 +170,18 @@ void CMaterialTimelineItemBinding::OnAddChild(qt3dsdm::Qt3DSDMInstanceHandle inI
Qt3DSDMTimelineItemBinding::OnAddChild(inInstance);
}
-void CMaterialTimelineItemBinding::OnPropertyChanged(Qt3DSDMPropertyHandle inPropertyHandle)
+void CMaterialEffectTimelineItemBinding::OnPropertyChanged(Qt3DSDMPropertyHandle inPropertyHandle)
{
Qt3DSDMTimelineItemBinding::OnPropertyChanged(inPropertyHandle);
}
-void CMaterialTimelineItemBinding::OnPropertyLinked(Qt3DSDMPropertyHandle inPropertyHandle)
+void CMaterialEffectTimelineItemBinding::OnPropertyLinked(Qt3DSDMPropertyHandle inPropertyHandle)
{
Qt3DSDMTimelineItemBinding::OnPropertyLinked(inPropertyHandle);
}
qt3dsdm::Qt3DSDMInstanceHandle
-CMaterialTimelineItemBinding::GetImage(qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle)
+CMaterialEffectTimelineItemBinding::GetImage(qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle)
{
qt3dsdm::IPropertySystem *thePropertySystem = m_TransMgr->GetStudioSystem()->GetPropertySystem();
SValue theImageValue;
@@ -191,8 +192,8 @@ CMaterialTimelineItemBinding::GetImage(qt3dsdm::Qt3DSDMPropertyHandle inProperty
}
ITimelineItemBinding *
-CMaterialTimelineItemBinding::GetOrCreateImageBinding(qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle,
- const wchar_t *inName)
+CMaterialEffectTimelineItemBinding::GetOrCreateImageBinding(
+ qt3dsdm::Qt3DSDMPropertyHandle inPropertyHandle, const wchar_t *inName)
{
qt3dsdm::Qt3DSDMInstanceHandle theImageInstance = GetImage(inPropertyHandle);
ITimelineItemBinding *theImageTimelineRow = m_TransMgr->GetBinding(theImageInstance);
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h
index 8e188a52..0ecbcb54 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/MaterialTimelineItemBinding.h
@@ -47,7 +47,7 @@ class CTimelineTranslationManager;
/**
* Binding to a DataModel object of Material type
*/
-class CMaterialTimelineItemBinding : public Qt3DSDMTimelineItemBinding
+class CMaterialEffectTimelineItemBinding : public Qt3DSDMTimelineItemBinding
{
public: // Types
typedef std::tuple<qt3dsdm::TCharStr, qt3dsdm::TCharStr> TNameFormalNamePair;
@@ -57,9 +57,9 @@ protected: // Members
TNameFormalNamePairList m_ImageNameFormalNamePairs;
public: // Construction
- CMaterialTimelineItemBinding(CTimelineTranslationManager *inMgr,
- qt3dsdm::Qt3DSDMInstanceHandle inDataHandle);
- virtual ~CMaterialTimelineItemBinding();
+ CMaterialEffectTimelineItemBinding(CTimelineTranslationManager *inMgr,
+ qt3dsdm::Qt3DSDMInstanceHandle inDataHandle);
+ virtual ~CMaterialEffectTimelineItemBinding();
public: // Qt3DSDMTimelineItemBinding
ITimelineTimebar *GetTimebar() override;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp
index d71ef582..58529ad4 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp
@@ -234,6 +234,34 @@ bool Qt3DSDMTimelineItemBinding::HasAction(bool inMaster)
return theActions.size() > 0;
}
+ITimelineItem::ActivateActions Qt3DSDMTimelineItemBinding::getActivateActions()
+{
+ TActionHandleList theActions;
+ CDoc *theDoc = g_StudioApp.GetCore()->GetDoc();
+
+ Qt3DSDMSlideHandle theSlide = theDoc->GetActiveSlide();
+ qt3dsdm::ISlideCore &theSlideCore(*m_StudioSystem->GetSlideCore());
+ if (theSlideCore.IsSlide(theSlide)) {
+ m_StudioSystem->GetActionCore()->GetActions(theSlide, m_DataHandle, theActions);
+ // Check also master slide, to get actions inside component
+ TActionHandleList masterActions;
+ Qt3DSDMSlideHandle masterSlide = m_StudioSystem->GetSlideSystem()->GetMasterSlide(theSlide);
+ m_StudioSystem->GetActionCore()->GetActions(masterSlide, m_DataHandle, masterActions);
+ theActions.insert(theActions.end(), masterActions.begin(), masterActions.end());
+ }
+
+ ITimelineItem::ActivateActions activateActions = ITimelineItem::ActivateAction::None;
+ for (auto theIter = theActions.begin(); theIter != theActions.end(); ++theIter) {
+ auto info = m_StudioSystem->GetActionCore()->GetActionInfo(*theIter);
+ if (info.m_Event == L"onActivate")
+ activateActions |= ITimelineItem::ActivateAction::Activate;
+ else if (info.m_Event == L"onDeactivate")
+ activateActions |= ITimelineItem::ActivateAction::Deactivate;
+ }
+
+ return activateActions;
+}
+
bool Qt3DSDMTimelineItemBinding::ChildrenHasAction(bool inMaster)
{
// Get all the instances in this slidegraph
@@ -353,18 +381,17 @@ void Qt3DSDMTimelineItemBinding::SetName(const Q3DStudio::CString &inName)
return;
// Display warning dialog if user tried to enter an empty string
- if (inName.IsEmpty()) {
+ if (inName.IsEmpty() || inName.toQString().contains(QChar('.'))) {
QString theTitle = QObject::tr("Rename Object Error");
- QString theString = QObject::tr("Object name cannot be an empty string.");
+ QString theString = inName.IsEmpty() ? QObject::tr("Object name cannot be an empty string.")
+ : QObject::tr("Object name cannot contain a dot.");
g_StudioApp.GetDialogs()->DisplayMessageBox(theTitle, theString,
Qt3DSMessageBox::ICON_ERROR, false);
-
return;
}
CClientDataModelBridge *theBridge = m_StudioSystem->GetClientDataModelBridge();
const auto doc = g_StudioApp.GetCore()->GetDoc();
-
// Display warning if the name and path are the same as the material container
if (theBridge->GetParentInstance(m_DataHandle) == doc->GetSceneInstance()
&& inName.toQString() == theBridge->getMaterialContainerName()) {
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.h b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.h
index 3980c0e1..4f7084d2 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.h
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.h
@@ -107,6 +107,7 @@ public:
bool IsVisible() const override;
void SetVisible(bool) override;
bool HasAction(bool inMaster) override;
+ ITimelineItem::ActivateActions getActivateActions() override;
bool IsVisibilityControlled() const override;
bool ChildrenHasAction(bool inMaster) override;
bool ComponentHasAction(bool inMaster) override;
diff --git a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp
index c03867a7..9a1e9eab 100644
--- a/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/Timeline/Bindings/TimelineTranslationManager.cpp
@@ -64,8 +64,8 @@ ITimelineItemBinding *CTimelineTranslationManager::GetOrCreate(Qt3DSDMInstanceHa
EStudioObjectType objType = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()
->GetClientDataModelBridge()->GetObjectType(inInstance);
- if (objType & OBJTYPE_IS_MATERIAL) {
- theReturn = new CMaterialTimelineItemBinding(this, inInstance);
+ if (objType & (OBJTYPE_IS_MATERIAL | OBJTYPE_EFFECT)) {
+ theReturn = new CMaterialEffectTimelineItemBinding(this, inInstance);
} else if (objType == OBJTYPE_IMAGE) {
theReturn = new CImageTimelineItemBinding(this, inInstance);
} else if (objType & (OBJTYPE_GROUP | OBJTYPE_COMPONENT)) {
@@ -80,9 +80,9 @@ ITimelineItemBinding *CTimelineTranslationManager::GetOrCreate(Qt3DSDMInstanceHa
theReturn = new CPathTimelineItemBinding(this, inInstance);
} else if (objType == OBJTYPE_LAYER) {
theReturn = new CLayerTimelineItemBinding(this, inInstance);
- } else if (objType & (OBJTYPE_MODEL | OBJTYPE_TEXT | OBJTYPE_CAMERA | OBJTYPE_EFFECT
+ } else if (objType & (OBJTYPE_MODEL | OBJTYPE_TEXT | OBJTYPE_CAMERA
| OBJTYPE_LIGHT | OBJTYPE_RENDERPLUGIN | OBJTYPE_ALIAS
- | OBJTYPE_SUBPATH))
+ | OBJTYPE_SUBPATH | OBJTYPE_SIGNAL))
theReturn = new Qt3DSDMTimelineItemBinding(this, inInstance);
else {
// Add support for additional DataModel types here.
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
index 02d08141..365bb88b 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h
@@ -62,6 +62,7 @@ namespace TimelineConstants
const int DURATION_HANDLE_W = 14; // width of duration end handles in a timeline row
const int NAVIGATION_BAR_H = 30; // height of navigation/breadcrumb bar
const int TIMEBAR_TOOLTIP_OFFSET_V = 10;
+ const int ACTION_W = 4;
// Other
const int EXPAND_ANIMATION_DURATION = 200;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
index d05fe12d..4b599cbf 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp
@@ -385,6 +385,9 @@ void TimelineWidget::OnNewPresentation()
m_connections.push_back(theSignalProvider->ConnectActionDeleted(
std::bind(&TimelineWidget::onActionEvent, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
+ m_connections.push_back(theSignalProvider->ConnectEventSet(
+ std::bind(&TimelineWidget::onActionModifiedEvent, this,
+ std::placeholders::_1)));
// connect property linked/unlinked
m_connections.push_back(theSignalProvider->ConnectPropertyLinked(
@@ -741,6 +744,7 @@ void TimelineWidget::updateActionStates(const QSet<RowTree *> &rows)
states |= RowTree::ActionState::ComponentAction;
}
row->setActionStates(states);
+ row->setActivateActions(binding->getActivateActions());
}
}
@@ -994,6 +998,15 @@ void TimelineWidget::onAsyncUpdate()
m_graphicsScene->rowManager()->finalizeRowDeletions();
}
+void TimelineWidget::onActionModifiedEvent(qt3dsdm::Qt3DSDMActionHandle inAction)
+{
+ // We don't have action owner here, so just do full reconstruct as action
+ // event types are anyway rarely changed.
+ m_fullReconstruct = true;
+ if (!m_asyncUpdateTimer.isActive())
+ m_asyncUpdateTimer.start();
+}
+
void TimelineWidget::onActionEvent(qt3dsdm::Qt3DSDMActionHandle inAction,
qt3dsdm::Qt3DSDMSlideHandle inSlide,
qt3dsdm::Qt3DSDMInstanceHandle inOwner)
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.h
index ed27f924..9804a03e 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.h
@@ -117,6 +117,7 @@ protected:
qt3dsdm::Qt3DSDMPropertyHandle property);
void onActionEvent(qt3dsdm::Qt3DSDMActionHandle inAction, qt3dsdm::Qt3DSDMSlideHandle inSlide,
qt3dsdm::Qt3DSDMInstanceHandle inOwner);
+ void onActionModifiedEvent(qt3dsdm::Qt3DSDMActionHandle inAction);
void onPropertyLinked(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3dsdm::Qt3DSDMPropertyHandle inProperty);
void onPropertyUnlinked(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
index bca36b7a..b2a8f6dc 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp
@@ -130,21 +130,23 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
const double edgeOffset = TimelineConstants::RULER_EDGE_OFFSET;
// Duration. Draw duration bar (for scene/component root) also if it has
- // datainput controller
+ // datainput controller.
if (m_rowTree->hasDurationBar() || m_controllerDataInput.size()) {
painter->save();
+ // do not draw anything beyond bar area left end
+ auto startXActual = edgeOffset + qMax(0.0, m_startX);
// fully outside ancestors' limits, draw fully hashed
if (m_minStartX > m_endX || m_maxEndX < m_startX) {
painter->setBrush(QBrush(CStudioPreferences::timelineRowColorDurationOff1(),
Qt::BDiagPattern));
painter->setPen(Qt::NoPen);
- painter->fillRect(QRect(edgeOffset + m_startX, 0, m_endX - m_startX, currHeight),
+ painter->fillRect(startXActual, 0, edgeOffset + m_endX - startXActual, currHeight,
CStudioPreferences::timelineRowColorDurationOff2());
- painter->drawRect(QRect(edgeOffset + m_startX, 0, m_endX - m_startX, currHeight));
+ painter->drawRect(startXActual, 0, edgeOffset + m_endX - startXActual, currHeight);
painter->setPen(QPen(CStudioPreferences::timelineRowColorDurationEdge(), 2));
- painter->drawLine(edgeOffset + m_startX, 0, edgeOffset + m_startX, currHeight);
+ painter->drawLine(startXActual, 0, startXActual, currHeight);
painter->drawLine(edgeOffset + m_endX, 0, edgeOffset + m_endX, currHeight);
} else {
// draw main duration part
@@ -193,14 +195,13 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
Qt::BDiagPattern));
if (m_startX < m_minStartX) {
painter->setPen(Qt::NoPen);
- painter->fillRect(QRect(edgeOffset + m_startX, 0, m_minStartX - m_startX,
+ painter->fillRect(QRect(startXActual, 0, qMin(m_minStartX - m_startX, m_minStartX),
currHeight),
CStudioPreferences::timelineRowColorDurationOff2());
- painter->drawRect(QRect(edgeOffset + m_startX, 0, m_minStartX - m_startX,
+ painter->drawRect(QRect(startXActual, 0, qMin(m_minStartX - m_startX, m_minStartX),
currHeight));
painter->setPen(CStudioPreferences::timelineRowColorDurationEdge());
- painter->drawLine(edgeOffset + m_minStartX, 0, edgeOffset + m_minStartX,
- currHeight);
+ painter->drawLine(startXActual, 0, startXActual, currHeight);
}
// draw hashed part after
@@ -215,9 +216,21 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
if (m_rowTree->indexInLayout() != 1) {
painter->setPen(QPen(CStudioPreferences::timelineRowColorDurationEdge(), 2));
- painter->drawLine(edgeOffset + m_startX, 0, edgeOffset + m_startX, currHeight);
+ painter->drawLine(startXActual, 0, startXActual, currHeight);
painter->drawLine(edgeOffset + m_endX, 0, edgeOffset + m_endX, currHeight);
}
+
+ // Paint possible timeline actions
+ auto actions = m_rowTree->m_activateActions;
+ bool paintActivate = actions.testFlag(ITimelineItem::ActivateAction::Activate);
+ bool paintDeactivate = actions.testFlag(ITimelineItem::ActivateAction::Deactivate);
+ int aw = TimelineConstants::ACTION_W;
+ QColor aColor = CStudioPreferences::timelineActionColor();
+ if (paintActivate)
+ painter->fillRect(QRect(x - aw/2, 0, aw, currHeight), aColor);
+ if (paintDeactivate)
+ painter->fillRect(QRect(x + w - aw/2, 0, aw, currHeight), aColor);
+
}
painter->restore();
@@ -623,9 +636,6 @@ void RowTimeline::clearBoundChildren()
// move the duration area (start/end x)
void RowTimeline::moveDurationBy(double dx)
{
- if (m_startX + dx < 0)
- dx = -m_startX;
-
m_startX += dx;
m_endX += dx;
@@ -641,8 +651,10 @@ void RowTimeline::moveDurationBy(double dx)
// move keyframes with the row
if (!m_rowTree->isProperty()) { // make sure we don't move the keyframes twice
- for (Keyframe *keyframe : qAsConst(m_keyframes))
- keyframe->time += rowTree()->m_scene->ruler()->distanceToTime(dx);
+ for (Keyframe *keyframe : qAsConst(m_keyframes)) {
+ keyframe->time += rowTree()->m_scene->ruler()->distanceToTime(
+ (m_startX + dx < 0) ? 0 : dx);
+ }
}
update();
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
index bc9f7a63..aca0ef3c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.cpp
@@ -424,6 +424,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixTextNormal(":/images/Objects-Text-Normal.png");
static const QPixmap pixAliasNormal(":/images/Objects-Alias-Normal.png");
static const QPixmap pixGroupNormal(":/images/Objects-Group-Normal.png");
+ static const QPixmap pixSignalNormal(":/images/Objects-Signal-Normal.png");
static const QPixmap pixComponentNormal(":/images/Objects-Component-Normal.png");
static const QPixmap pixMaterialNormal(":/images/Objects-Material-Normal.png");
static const QPixmap pixPropertyNormal(":/images/Objects-Property-Normal.png");
@@ -438,6 +439,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixTextNormal2x(":/images/Objects-Text-Normal@2x.png");
static const QPixmap pixAliasNormal2x(":/images/Objects-Alias-Normal@2x.png");
static const QPixmap pixGroupNormal2x(":/images/Objects-Group-Normal@2x.png");
+ static const QPixmap pixSignalNormal2x(":/images/Objects-Signal-Normal@2x.png");
static const QPixmap pixComponentNormal2x(":/images/Objects-Component-Normal@2x.png");
static const QPixmap pixMaterialNormal2x(":/images/Objects-Material-Normal@2x.png");
static const QPixmap pixPropertyNormal2x(":/images/Objects-Property-Normal@2x.png");
@@ -453,6 +455,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixTextDisabled(":/images/Objects-Text-Disabled.png");
static const QPixmap pixAliasDisabled(":/images/Objects-Alias-Disabled.png");
static const QPixmap pixGroupDisabled(":/images/Objects-Group-Disabled.png");
+ static const QPixmap pixSignalDisabled(":/images/Objects-Signal-Disabled.png");
static const QPixmap pixComponentDisabled(":/images/Objects-Component-Disabled.png");
static const QPixmap pixMaterialDisabled(":/images/Objects-Material-Disabled.png");
static const QPixmap pixPropertyDisabled(":/images/Objects-Property-Disabled.png");
@@ -467,6 +470,7 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
static const QPixmap pixTextDisabled2x(":/images/Objects-Text-Disabled@2x.png");
static const QPixmap pixAliasDisabled2x(":/images/Objects-Alias-Disabled@2x.png");
static const QPixmap pixGroupDisabled2x(":/images/Objects-Group-Disabled@2x.png");
+ static const QPixmap pixSignalDisabled2x(":/images/Objects-Signal-Disabled@2x.png");
static const QPixmap pixComponentDisabled2x(":/images/Objects-Component-Disabled@2x.png");
static const QPixmap pixMaterialDisabled2x(":/images/Objects-Material-Disabled@2x.png");
static const QPixmap pixPropertyDisabled2x(":/images/Objects-Property-Disabled@2x.png");
@@ -512,6 +516,10 @@ void RowTree::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q
pixRowType = hiResIcons ? (m_locked ? pixGroupDisabled2x : pixGroupNormal2x)
: (m_locked ? pixGroupDisabled : pixGroupNormal);
break;
+ case OBJTYPE_SIGNAL:
+ pixRowType = hiResIcons ? (m_locked ? pixSignalDisabled2x : pixSignalNormal2x)
+ : (m_locked ? pixSignalDisabled : pixSignalNormal);
+ break;
case OBJTYPE_COMPONENT:
pixRowType = hiResIcons ? (m_locked ? pixComponentDisabled2x : pixComponentNormal2x)
: (m_locked ? pixComponentDisabled : pixComponentNormal);
@@ -1336,6 +1344,14 @@ void RowTree::setActionStates(ActionStates states)
}
}
+void RowTree::setActivateActions(ITimelineItem::ActivateActions activateActions)
+{
+ if (activateActions != m_activateActions) {
+ m_activateActions = activateActions;
+ update();
+ }
+}
+
bool RowTree::isContainer() const
{
return !m_isProperty && m_objectType & OBJTYPE_IS_CONTAINER;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
index 34a851b7..179292c9 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTree.h
@@ -35,6 +35,7 @@
#include "StudioObjectTypes.h"
#include "RowTreeLabel.h"
#include "Qt3DSDMHandles.h"
+#include "Bindings/ITimelineItem.h"
#include <QtCore/qpropertyanimation.h>
#include <QtCore/qparallelanimationgroup.h>
@@ -93,6 +94,7 @@ public:
void removeChild(RowTree *child);
void setDnDState(DnDState state, DnDState onlyIfState = DnDState::Any, bool recursive = false);
void setActionStates(ActionStates states);
+ void setActivateActions(ITimelineItem::ActivateActions activateActions);
void setTreeWidth(double w);
void setBinding(ITimelineItemBinding *binding);
void setPropBinding(ITimelineItemProperty *binding); // for property rows
@@ -196,6 +198,7 @@ private:
bool m_onMasterSlide = false;
DnDState m_dndState = DnDState::None;
ActionStates m_actionStates = ActionState::None;
+ ITimelineItem::ActivateActions m_activateActions = ITimelineItem::ActivateAction::None;
bool m_hasSubpresentation = false;
int m_numDescendantSubpresentations = 0;
ExpandState m_expandState = ExpandState::HiddenCollapsed;
diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTreeLabel.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTreeLabel.cpp
index a5431b14..7428c47c 100644
--- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTreeLabel.cpp
+++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTreeLabel.cpp
@@ -168,6 +168,10 @@ void RowTreeLabel::validateLabel()
emit labelChanged("");
setLabel(m_label);
return;
+ } else if (text.contains(QChar('.'))) {
+ emit labelChanged(".");
+ setLabel(m_label);
+ return;
}
setLabel(text);
diff --git a/src/Authoring/Qt3DStudio/Palettes/controls/FloatTextField.qml b/src/Authoring/Qt3DStudio/Palettes/controls/FloatTextField.qml
index 95458889..dbeb81ea 100644
--- a/src/Authoring/Qt3DStudio/Palettes/controls/FloatTextField.qml
+++ b/src/Authoring/Qt3DStudio/Palettes/controls/FloatTextField.qml
@@ -38,6 +38,8 @@ TextField {
property bool ignoreHotkeys: true
signal previewValueChanged
+ signal triggerUndo
+ signal triggerRedo
selectByMouse: true
text: "0.000"
@@ -198,6 +200,13 @@ TextField {
if (!rateLimiter.running)
rateLimiter.start();
+ } else if ((event.modifiers & Qt.ControlModifier)
+ && !(event.modifiers & Qt.ShiftModifier)) {
+ // Undo & redo handling (QT3DS-4000)
+ if (event.key === Qt.Key_Z)
+ floatTextFieldId.triggerUndo();
+ else if (event.key === Qt.Key_Y)
+ floatTextFieldId.triggerRedo();
}
}
}
diff --git a/src/Authoring/Qt3DStudio/PreviewHelper.cpp b/src/Authoring/Qt3DStudio/PreviewHelper.cpp
index 1e87201b..24d7ee91 100644
--- a/src/Authoring/Qt3DStudio/PreviewHelper.cpp
+++ b/src/Authoring/Qt3DStudio/PreviewHelper.cpp
@@ -118,21 +118,14 @@ QString CPreviewHelper::getViewerFilePath(const QString &exeName)
viewerFile = QStringLiteral("%1.exe").arg(exeName);
QString viewer = viewerDir.filePath() + QStringLiteral("/") + viewerFile;
- if (!QFileInfo(viewer).exists()) {
- if (exeName == QLatin1String("q3dsviewer")) {
- viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/qt3d-runtime/bin/")
- + viewerFile;
- } else if (exeName == QLatin1String("Qt3DViewer")) {
- viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/ogl-runtime/bin/")
- + viewerFile;
- }
+ if (!QFileInfo(viewer).exists() && exeName == QLatin1String("Qt3DViewer")) {
+ viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/ogl-runtime/bin/")
+ + viewerFile;
}
#else
#ifdef Q_OS_MACOS
QString viewerDevPath;
- if (exeName == QLatin1String("q3dsviewer"))
- viewerDevPath = QStringLiteral("../src/Runtime/qt3d-runtime/bin/");
- else if (exeName == QLatin1String("Qt3DViewer"))
+ if (exeName == QLatin1String("Qt3DViewer"))
viewerDevPath = QStringLiteral("../src/Runtime/ogl-runtime/bin/");
// Name of the executable file on macOS
@@ -155,14 +148,9 @@ QString CPreviewHelper::getViewerFilePath(const QString &exeName)
viewerFile = exeName;
QString viewer = viewerDir.filePath() + QStringLiteral("/") + viewerFile;
- if (!QFileInfo(viewer).exists()) {
- if (exeName == QLatin1String("q3dsviewer")) {
- viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/qt3d-runtime/bin/")
- + viewerFile;
- } else if (exeName == QLatin1String("Qt3DViewer")) {
- viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/ogl-runtime/bin/")
- + viewerFile;
- }
+ if (!QFileInfo(viewer).exists() && exeName == QLatin1String("Qt3DViewer")) {
+ viewer = viewerDir.filePath() + QStringLiteral("/../src/Runtime/ogl-runtime/bin/")
+ + viewerFile;
}
#endif
#endif
diff --git a/src/Authoring/Qt3DStudio/Qt3DStudio.pro b/src/Authoring/Qt3DStudio/Qt3DStudio.pro
index 4043d027..ddece619 100644
--- a/src/Authoring/Qt3DStudio/Qt3DStudio.pro
+++ b/src/Authoring/Qt3DStudio/Qt3DStudio.pro
@@ -113,7 +113,7 @@ STATICRUNTIME = \
-lQT3DSDM$$qtPlatformTargetSuffix() \
-lCommonLib$$qtPlatformTargetSuffix() \
-lCoreLib$$qtPlatformTargetSuffix() \
- -lqt3dsruntimestatic$$qtPlatformTargetSuffix() \
+ -lqt3dsruntimestatic$$qtPlatformTargetSuffix()
} else {
LIBS += $$STATICRUNTIME
QMAKE_LFLAGS += /NODEFAULTLIB:tinyxml.lib
@@ -499,19 +499,19 @@ ABS_PRJ_ROOT = $$absolute_path($$PWD/../../..)
macos:ABS_DEST_DIR = $$absolute_path($$BINDIR)/$${TARGET}.app/Contents/Resources
!macos:ABS_DEST_DIR = $$absolute_path($$BINDIR)
-copy_content.files = $$PWD/../../Runtime/ogl-runtime/Studio/*
+copy_content.files = $$files($$PWD/../../Runtime/ogl-runtime/Studio/*)
copy_content.path = $$ABS_DEST_DIR
COPIES += copy_content
-install_content.files = $$PWD/../../Runtime/ogl-runtime/Studio/*
+install_content.files = $$files($$PWD/../../Runtime/ogl-runtime/Studio/*)
install_content.path = $$[QT_INSTALL_BINS]
INSTALLS += install_content
-copy_buildconfig.files = $$PWD/../../../Studio/*
+copy_buildconfig.files = $$files($$PWD/../../../Studio/*)
copy_buildconfig.path = $$ABS_DEST_DIR
COPIES += copy_buildconfig
-install_buildconfig.files = $$PWD/../../../Studio/*
+install_buildconfig.files = $$files($$PWD/../../../Studio/*)
install_buildconfig.path = $$[QT_INSTALL_BINS]
INSTALLS += install_buildconfig
diff --git a/src/Authoring/Qt3DStudio/Render/IStudioRenderer.h b/src/Authoring/Qt3DStudio/Render/IStudioRenderer.h
index fc543a89..6adaafbf 100644
--- a/src/Authoring/Qt3DStudio/Render/IStudioRenderer.h
+++ b/src/Authoring/Qt3DStudio/Render/IStudioRenderer.h
@@ -67,6 +67,8 @@ public:
virtual void SetGuidesEnabled(bool val) = 0;
virtual bool AreGuidesEditable() const = 0;
virtual void SetGuidesEditable(bool val) = 0;
+ virtual bool getObjectError(qt3dsdm::Qt3DSDMInstanceHandle theInstance,
+ QString &error) const = 0;
// Setting the camera to -1 disables the edit cameras
// So setting the camera to 0- (numcameras - 1) will set change the active
// edit camera.
diff --git a/src/Authoring/Qt3DStudio/Render/StudioRenderer.cpp b/src/Authoring/Qt3DStudio/Render/StudioRenderer.cpp
index 320bca23..e2af9606 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioRenderer.cpp
+++ b/src/Authoring/Qt3DStudio/Render/StudioRenderer.cpp
@@ -93,7 +93,7 @@ struct SRendererImpl : public IStudioRenderer,
public CToolbarChangeListener,
public IOffscreenRenderer::IOffscreenRendererCallback
{
- typedef eastl::vector<Option<SEditCameraPersistentInformation>> TEditCameraInfoList;
+ typedef eastl::vector<Option<SEditorCameraInformation>> TEditCameraInfoList;
std::shared_ptr<CWGLRenderContext> m_RenderContext;
NVScopedRefCounted<IQt3DSRenderContext> m_Context;
QRect m_Rect;
@@ -109,7 +109,7 @@ struct SRendererImpl : public IStudioRenderer,
bool m_MaybeDragStart;
TEditCameraInfoList m_EditCameraInformation;
QT3DSI32 m_EditCameraIndex;
- SEditCameraPersistentInformation m_MouseDownCameraInformation;
+ SEditorCameraInformation m_MouseDownCameraInformation;
SStudioPickValue m_PickResult;
bool m_RenderRequested;
int m_LastToolMode;
@@ -343,7 +343,7 @@ struct SRendererImpl : public IStudioRenderer,
m_Context = theCore->CreateRenderContext(
m_RenderContext->GetRenderContext(),
m_RenderContext->GetRenderContext().GetStringTable().RegisterStr(
- theResourcePath.c_str()), false);
+ theResourcePath.c_str()), false, nullptr);
// Allow the artist to interact with the top level objects alone.
m_Context->GetRenderer().PickRenderPlugins(false);
@@ -378,12 +378,7 @@ struct SRendererImpl : public IStudioRenderer,
m_Rect = inRect;
if (IsInitialized()) {
m_pixelRatio = StudioUtils::devicePixelRatio();
- m_RenderContext->BeginRender();
- NVRenderContext &theContext = m_RenderContext->GetRenderContext();
- theContext.SetViewport(qt3ds::render::NVRenderRect(0, 0, inRect.width(),
- inRect.height()));
SetTranslationViewport();
- m_RenderContext->EndRender();
}
}
@@ -417,6 +412,17 @@ struct SRendererImpl : public IStudioRenderer,
Render();
}
+ bool getObjectError(qt3dsdm::Qt3DSDMInstanceHandle theInstance, QString &error) const
+ {
+ auto translator = m_Translation->GetOrCreateTranslator(theInstance);
+ if (translator) {
+ error = static_cast<SGraphObjectTranslator *>(translator)->GetError();
+ return true;
+ }
+ error = QString();
+ return false;
+ }
+
void getPreviewFbo(QSize &outFboDim, qt3ds::QT3DSU32 &outFboTexture) override
{
if (m_Translation) {
@@ -684,11 +690,11 @@ struct SRendererImpl : public IStudioRenderer,
while ((size_t)m_EditCameraIndex >= m_EditCameraInformation.size())
m_EditCameraInformation.push_back(Empty());
- Option<SEditCameraPersistentInformation> &theCameraInfo =
+ Option<SEditorCameraInformation> &theCameraInfo =
m_EditCameraInformation[m_EditCameraIndex];
if (!theCameraInfo.hasValue()) {
- theCameraInfo = SEditCameraPersistentInformation();
+ theCameraInfo = SEditorCameraInformation();
// TODO - consider resizing clip planes to scene so we use the depth buffer more
// accurately
// or consider requesting a larger depth buffer from the windowing system.
diff --git a/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.cpp b/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.cpp
index f0209d89..d24f1061 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.cpp
+++ b/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.cpp
@@ -345,6 +345,7 @@ struct STranslatorDataModelParser
#define Node_LocalOpacity m_Node.m_Opacity
#define Node_RotationOrder m_Node.m_RotationOrder
#define Node_LeftHanded m_Node.m_Orientation
+#define Group_ordered m_Node.m_ordered
#define Layer_TemporalAAEnabled m_Layer.m_TemporalAA
#define Layer_LayerEnableDepthTest m_Layer.m_DisableDepthTest
#define Layer_LayerEnableDepthPrePass m_Layer.m_DisableDepthPrepass
@@ -355,6 +356,10 @@ struct STranslatorDataModelParser
#define Layer_Location m_Layer.m_Location
#define Layer_ProgressiveAAMode m_Layer.m_ProgressiveAA
#define Layer_MultisampleAAMode m_Layer.m_MultisampleAA
+#define Layer_DynamicResize m_Layer.m_DynamicResize
+#define Layer_DynamicPaddingUnits m_Layer.m_DynamicPaddingUnits
+#define Layer_DynamicPadding m_Layer.m_DynamicPadding
+#define Layer_DynamicCombine m_Layer.m_DynamicCombine
#define Layer_HorizontalFieldValues m_Layer.m_HorizontalFieldValues
#define Layer_Left m_Layer.m_Left
#define Layer_LeftUnits m_Layer.m_LeftUnits
@@ -369,6 +374,7 @@ struct STranslatorDataModelParser
#define Layer_HeightUnits m_Layer.m_HeightUnits
#define Layer_Bottom m_Layer.m_Bottom
#define Layer_BottomUnits m_Layer.m_BottomUnits
+#define Layer_AoEnabled m_Layer.m_AoEnabled
#define Layer_AoStrength m_Layer.m_AoStrength
#define Layer_AoDistance m_Layer.m_AoDistance
#define Layer_AoSoftness m_Layer.m_AoSoftness
@@ -454,6 +460,8 @@ struct STranslatorDataModelParser
#define Material_DiffuseLightWrap m_Material.m_DiffuseLightWrap
#define Material_ReferencedMaterial m_ReferencedMaterial.m_ReferencedMaterial
#define Material_VertexColors m_Material.m_VertexColors
+#define Material_TransparencyMode m_Material.m_TransparencyMode
+#define Material_CullMode m_Material.m_CullMode
#define Image_ImagePath m_Asset.m_SourcePath
#define Image_OffscreenRendererId m_Image.m_SubPresentation
#define Image_Scale_X m_Image.m_RepeatU
@@ -466,6 +474,8 @@ struct STranslatorDataModelParser
#define Image_MappingMode m_Image.m_TextureMapping
#define Image_HorizontalTilingMode m_Image.m_TilingU
#define Image_VerticalTilingMode m_Image.m_TilingV
+#define Image_MinFilter m_Image.m_MinFilter
+#define Image_MagFilter m_Image.m_MagFilter
#define Text_Text m_Text.m_TextString
#define Text_Font m_Text.m_Font
#define Text_FontSize m_Text.m_Size
@@ -635,6 +645,8 @@ struct SNodeTranslator : public SGraphObjectTranslator
ITERATE_QT3DS_RENDER_NODE_PROPERTIES
theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_BoneId,
theItem.m_SkeletonId);
+ theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Group.m_ordered,
+ theItem.m_ordered);
bool ignoresParent = false;
if (theParser.ParseProperty(inContext.m_ObjectDefinitions.m_Node.m_IgnoresParent,
ignoresParent))
@@ -1022,19 +1034,20 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
TIdxToPropertyMap m_PropertyMap;
SDynamicObjectTranslator(qt3dsdm::Qt3DSDMInstanceHandle inInstance, qt3ds::NVAllocatorCallback &,
- SDynamicObject &inObject)
+ SDynamicGraphObject &inObject)
: SGraphObjectTranslator(inInstance, inObject)
{
}
void PushTranslation(STranslation &inContext) override
{
- SDynamicObject &theItem = static_cast<SDynamicObject &>(GetGraphObject());
+ SDynamicGraphObject &theItem = static_cast<SDynamicGraphObject &>(GetGraphObject());
+ SDynamicObject &dynObj = *theItem.m_dynamicObject;
IDynamicObjectSystem &theSystem = inContext.m_Context.GetDynamicObjectSystem();
using namespace qt3ds::render::dynamic;
using qt3ds::foundation::NVConstDataRef;
- NVConstDataRef<SPropertyDefinition> theProperties =
- theSystem.GetProperties(theItem.m_ClassName);
+ NVConstDataRef<SPropertyDefinition> theProperties
+ = theSystem.GetProperties(dynObj.m_ClassName);
if (m_PropertyMap.size() == 0) {
for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
const SPropertyDefinition &theDefinition(theProperties[idx]);
@@ -1065,7 +1078,7 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Long:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSI32) {
- theItem.SetPropertyValue(theDefinition,
+ dynObj.SetPropertyValue(theDefinition,
qt3dsdm::get<qt3ds::QT3DSI32>(theValue));
} else {
QT3DS_ASSERT(false);
@@ -1074,7 +1087,7 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Bool:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool) {
- theItem.SetPropertyValue(theDefinition, qt3dsdm::get<bool>(theValue));
+ dynObj.SetPropertyValue(theDefinition, qt3dsdm::get<bool>(theValue));
} else {
QT3DS_ASSERT(false);
}
@@ -1082,7 +1095,7 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Float:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSF32) {
- theItem.SetPropertyValue(theDefinition, qt3dsdm::get<float>(theValue));
+ dynObj.SetPropertyValue(theDefinition, qt3dsdm::get<float>(theValue));
} else {
QT3DS_ASSERT(false);
}
@@ -1090,7 +1103,7 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Float2:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2) {
- theItem.SetPropertyValue(
+ dynObj.SetPropertyValue(
theDefinition, ToRenderType(qt3dsdm::get<qt3dsdm::SFloat2>(theValue)));
} else {
QT3DS_ASSERT(false);
@@ -1099,7 +1112,7 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Float3:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3) {
- theItem.SetPropertyValue(
+ dynObj.SetPropertyValue(
theDefinition, ToRenderType(qt3dsdm::get<qt3dsdm::SFloat3>(theValue)));
} else {
QT3DS_ASSERT(false);
@@ -1108,12 +1121,40 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
case qt3dsdm::DataModelDataType::Float4:
if (theDefinition.m_DataType
== qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4) {
- theItem.SetPropertyValue(
+ dynObj.SetPropertyValue(
theDefinition, ToRenderType(qt3dsdm::get<qt3dsdm::SFloat4>(theValue)));
} else {
QT3DS_ASSERT(false);
}
break;
+ case qt3dsdm::DataModelDataType::Long4: {
+ // Image
+ qt3dsdm::SLong4 theData = qt3dsdm::get<qt3dsdm::SLong4>(theValue);
+ qt3dsdm::Qt3DSDMInstanceHandle imageInstance
+ = inContext.m_Reader.GetInstanceForObjectRef(
+ GetInstanceHandle(), theData);
+ if (imageInstance.Valid()) {
+ SGraphObjectTranslator *imageTranslator
+ = inContext.GetOrCreateTranslator(imageInstance);
+ if (imageTranslator) {
+ SImage *img = static_cast<SImage *>(&imageTranslator->GetGraphObject());
+ theItem.setImage(theDefinition.m_Name, img);
+ eastl::string theWorkspace;
+ dynObj.SetPropertyValue(
+ theDefinition, theDefinition.m_Name.c_str(),
+ inContext.m_Doc.GetCore()->getProjectFile()
+ .getProjectPath().toLocal8Bit().constData(),
+ theWorkspace, inContext.m_Context.GetStringTable());
+ }
+ } else {
+ eastl::string theWorkspace;
+ dynObj.SetPropertyValue(
+ theDefinition, nullptr,
+ inContext.m_Doc.GetCore()->getProjectFile()
+ .getProjectPath().toLocal8Bit().constData(),
+ theWorkspace, inContext.m_Context.GetStringTable());
+ }
+ } break;
// Could be either an enum or a texture.
case qt3dsdm::DataModelDataType::String: {
qt3dsdm::TDataStrPtr theData = qt3dsdm::get<qt3dsdm::TDataStrPtr>(theValue);
@@ -1121,11 +1162,31 @@ struct SDynamicObjectTranslator : public SGraphObjectTranslator
eastl::string theStr;
qt3ds::render::ConvertWideUTF(theData->GetData(), 0, theStr);
eastl::string theWorkspace;
- theItem.SetPropertyValue(
- theDefinition, theStr.c_str(),
- inContext.m_Doc.GetCore()->getProjectFile()
- .getProjectPath().toLocal8Bit().constData(),
- theWorkspace, inContext.m_Context.GetStringTable());
+ if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
+ if (g_StudioApp.getDocumentVersion() < 7) {
+ // Old style texture. This needs to be run trough document editor
+ Qt3DSDMInstanceHandle instance = GetInstanceHandle();
+ Qt3DSDMPropertyHandle property = theProperty;
+ SValue value = theValue;
+ CDoc &doc = inContext.m_Doc;
+ QTimer::singleShot(10, [instance, property, value, &doc](){
+ Q3DStudio::CUpdateableDocumentEditor updatableEditor(doc);
+ updatableEditor.EnsureEditor("Set Property", __FILE__,
+ __LINE__)
+ .SetInstancePropertyValue(instance, property,
+ value);
+ });
+ g_StudioApp.SetConvertingPresentationOn();
+ } else {
+ // Ignore the value
+ }
+ } else {
+ dynObj.SetPropertyValue(
+ theDefinition, theStr.c_str(),
+ inContext.m_Doc.GetCore()->getProjectFile()
+ .getProjectPath().toLocal8Bit().constData(),
+ theWorkspace, inContext.m_Context.GetStringTable());
+ }
}
} break;
default:
@@ -1160,10 +1221,13 @@ struct SEffectTranslator : public SDynamicObjectTranslator
void SetActive(bool inActive) override
{
SEffect &theItem = static_cast<SEffect &>(GetGraphObject());
- if (m_EffectSystem)
+ if (m_EffectSystem) {
theItem.SetActive(inActive, *m_EffectSystem);
- else
+ if (inActive && inActive != theItem.m_Flags.IsActive())
+ m_EffectSystem->SetEffectRequiresCompilation(theItem.m_ClassName, true);
+ } else {
theItem.m_Flags.SetActive(inActive);
+ }
}
void ResetEffect() override
@@ -1172,6 +1236,19 @@ struct SEffectTranslator : public SDynamicObjectTranslator
if (m_EffectSystem)
theItem.Reset(*m_EffectSystem);
}
+
+ const QString GetError() override
+ {
+ SEffect &theItem = static_cast<SEffect &>(GetGraphObject());
+ return QString::fromUtf8(theItem.GetError().c_str());
+ }
+
+ void SetError(const QString &error) override
+ {
+ SEffect &theItem = static_cast<SEffect &>(GetGraphObject());
+ theItem.SetError(m_EffectSystem->GetResourceManager().GetRenderContext()
+ .GetStringTable().RegisterStr(error));
+ }
};
struct SCustomMaterialTranslator : public SDynamicObjectTranslator
{
@@ -1205,10 +1282,27 @@ struct SCustomMaterialTranslator : public SDynamicObjectTranslator
SCustomMaterial &theItem = static_cast<SCustomMaterial &>(GetGraphObject());
if (inActive != theItem.m_Flags.IsActive()) {
theItem.m_Flags.SetActive(inActive);
+ // Force compilation in Studio if custom shader became active, so we know
+ // if it has any compilation errors.
+ if (inActive)
+ m_MaterialSystem->setRequiresCompilation(theItem.m_ClassName, true);
+
m_MaterialSystem->OnMaterialActivationChange(theItem, inActive);
}
}
}
+
+ const QString GetError() override
+ {
+ SCustomMaterial &theItem = static_cast<SCustomMaterial &>(GetGraphObject());
+ return QString::fromUtf8(theItem.GetError().c_str());
+ }
+
+ void SetError(const QString &error) override
+ {
+ SCustomMaterial &theItem = static_cast<SCustomMaterial &>(GetGraphObject());
+ theItem.SetError(m_MaterialSystem->getContext()->GetStringTable().RegisterStr(error));
+ }
};
struct SReferencedMaterialTranslator : public SGraphObjectTranslator
{
@@ -1675,6 +1769,7 @@ SGraphObjectTranslator *STranslation::CreateTranslator(qt3dsdm::Qt3DSDMInstanceH
// For the subset of possible instances, pick out the valid translators.
switch (theType) {
case qt3dsdm::ComposerObjectTypes::Group:
+ case qt3dsdm::ComposerObjectTypes::Signal:
case qt3dsdm::ComposerObjectTypes::Component:
case qt3dsdm::ComposerObjectTypes::Node:
theNewTranslator = QT3DS_NEW(m_Allocator, SNodeTranslator)(inInstance, m_Allocator);
@@ -1923,6 +2018,11 @@ void STranslation::updateHelperGridFromSettings()
}
}
+void STranslation::updateAxisHelperFromSettings()
+{
+ m_axisHelperEnabled = CStudioPreferences::isAxisHelperOn();
+}
+
qt3dsdm::Qt3DSDMInstanceHandle STranslation::GetAnchorPoint(SPathPick &inPick)
{
return GetAnchorPoint(inPick.m_AnchorIndex);
@@ -1930,9 +2030,9 @@ qt3dsdm::Qt3DSDMInstanceHandle STranslation::GetAnchorPoint(SPathPick &inPick)
namespace qt3ds {
namespace studio {
- struct SEditCameraLayerTranslator : public SLayerTranslator
+ struct SEditorLayerTranslator : public SLayerTranslator
{
- SEditCameraLayerTranslator(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
+ SEditorLayerTranslator(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
qt3ds::NVAllocatorCallback &inAlloc)
: SLayerTranslator(inInstance, inAlloc)
{
@@ -1973,6 +2073,7 @@ STranslation::STranslation(IStudioRenderer &inRenderer, IQt3DSRenderContext &inC
, m_EditLightEnabled(false)
, m_Viewport(0, 0)
, m_EditCameraLayerTranslator(nullptr)
+ , m_AxisHelperLayerTranslator(nullptr)
, m_PixelBuffer(inContext.GetAllocator(), "STranslation::m_PixelBuffer")
, m_editModeCamerasAndLights(inContext.GetAllocator(),
"STranslation::m_editModeCamerasAndLights")
@@ -2047,6 +2148,52 @@ void STranslation::BuildRenderGraph(SGraphObjectTranslator &inParent, bool scene
{
SGraphObjectTranslator &theParentTranslator(inParent);
theParentTranslator.ClearChildren();
+
+ updateAxisHelperFromSettings();
+ if (theParentTranslator.GetGraphObject().m_Type == GraphObjectTypes::Scene &&
+ m_axisHelperEnabled && !scenePreviewPass) {
+ if (m_AxisHelperLayerTranslator && m_AxisHelperLayerTranslator->GetInstanceHandle()
+ != inParent.GetInstanceHandle()) {
+ QT3DS_FREE(m_Allocator, m_AxisHelperLayerTranslator);
+ m_AxisHelperLayerTranslator = nullptr;
+ }
+ if (!m_AxisHelperLayerTranslator) {
+ m_AxisHelperLayerTranslator =
+ QT3DS_NEW(m_Allocator, SEditorLayerTranslator)(inParent.GetInstanceHandle(), m_Allocator);
+ SLayer &layer = static_cast<SLayer &>(m_AxisHelperLayerTranslator->GetGraphObject());
+ layer.m_Background = LayerBackground::Color;
+ static const QT3DSVec4 matteColor(CStudioPreferences::matteColor().redF(),
+ CStudioPreferences::matteColor().greenF(),
+ CStudioPreferences::matteColor().blueF(), 0.5f);
+ layer.m_ClearColor = m_EditCameraEnabled ? QT3DSVec4(0, 0, 0, 0.5) : matteColor;
+ layer.m_LeftUnits = LayerUnitTypes::Pixels;
+ layer.m_RightUnits = LayerUnitTypes::Pixels;
+ layer.m_HeightUnits = LayerUnitTypes::Pixels;
+ layer.m_WidthUnits = LayerUnitTypes::Pixels;
+ layer.m_TopUnits = LayerUnitTypes::Pixels;
+ layer.m_BottomUnits = LayerUnitTypes::Pixels;
+ layer.m_HorizontalFieldValues = HorizontalFieldValues::LeftWidth;
+ layer.m_VerticalFieldValues = VerticalFieldValues::HeightBottom;
+ float pixelRatio = float(StudioUtils::devicePixelRatio());
+ layer.m_Top = 10 * pixelRatio;
+ layer.m_Left = 10 * pixelRatio;
+ layer.m_Right = 10 * pixelRatio;
+ layer.m_Bottom = 10 * pixelRatio;
+ layer.m_Width = 120 * pixelRatio;
+ layer.m_Height = 120 * pixelRatio;
+ layer.m_Flags.SetDirty(true);
+ m_AxisCamera.m_Id = m_Context.GetStringTable().RegisterStr("AxisCamera");
+ }
+ theParentTranslator.AppendChild(m_AxisHelperLayerTranslator->GetGraphObject());
+ SLayer &layer = static_cast<SLayer &>(m_AxisHelperLayerTranslator->GetGraphObject());
+ layer.m_NextSibling = layer.m_PreviousSibling = nullptr;
+ m_AxisHelperLayerTranslator->SetActive(true);
+ m_AxisHelperLayerTranslator->AppendChild(m_AxisCamera);
+ m_AxisCamera.m_Flags.SetActive(true);
+ // Make sure axis helper layer children gets updated
+ m_Context.GetRenderer().ChildrenUpdated(layer);
+ }
+
if (m_EditCameraEnabled && !scenePreviewPass) {
const auto objectType = theParentTranslator.GetGraphObject().m_Type;
if (objectType == GraphObjectTypes::Layer) {
@@ -2089,7 +2236,7 @@ void STranslation::BuildRenderGraph(SGraphObjectTranslator &inParent, bool scene
}
if (!m_EditCameraLayerTranslator) {
m_EditCameraLayerTranslator =
- QT3DS_NEW(m_Allocator, SEditCameraLayerTranslator)(theChild,
+ QT3DS_NEW(m_Allocator, SEditorLayerTranslator)(theChild,
m_Allocator);
}
theTranslator = m_EditCameraLayerTranslator;
@@ -2224,6 +2371,26 @@ void STranslation::PreRender(bool scenePreviewPass)
m_EditLight.MarkDirty(qt3ds::render::NodeTransformDirtyFlag::TransformIsDirty);
updateHelperGridFromSettings();
}
+ if (m_axisHelperEnabled && !scenePreviewPass) {
+ if (m_EditCameraEnabled) {
+ m_EditCameraInfo.ApplyToCamera(m_AxisCamera, theViewportDims, true);
+ } else {
+ // Get scene camera
+ SLayerTranslator *layerTranslator = static_cast<SLayerTranslator *>(GetOrCreateTranslator(m_Doc.GetActiveLayer()));
+ SNode *layerNode = static_cast<SNode *>(layerTranslator->m_GraphObject);
+ for (SNode *child = layerNode->m_FirstChild; child; child = child->m_NextSibling) {
+ if (child->m_Type == GraphObjectTypes::Enum::Camera) {
+ m_AxisCamera = *(SCamera *)child;
+ m_AxisCamera.m_Parent = (SNode *)&m_AxisHelperLayerTranslator->GetGraphObject();
+ m_AxisCamera.m_NextSibling = nullptr;
+ m_AxisCamera.m_PreviousSibling = nullptr;
+ m_AxisCamera.m_FirstChild = nullptr;
+ m_AxisCamera.m_PreviousSibling = nullptr;
+ break;
+ }
+ }
+ }
+ }
if (m_Scene) {
CStudioProjectSettings *theSettings = m_Doc.GetCore()->GetStudioProjectSettings();
@@ -2265,6 +2432,8 @@ void STranslation::PreRender(bool scenePreviewPass)
}
}
}
+ m_Presentation.m_preferKTX = theSettings->getPreferCompressedTextures();
+ m_Presentation.m_flipCompressedTextures = theSettings->getFlipCompressedTextures();
}
if (m_EditCameraEnabled == false && g_StudioApp.IsAuthorZoom()) {
if (m_Presentation.m_PresentationDimensions.x > theViewportDims.x
@@ -2697,14 +2866,35 @@ void STranslation::Render(int inWidgetId, bool inDrawGuides, bool scenePreviewPa
}
}
}
- Option<NVRenderRect> viewport = m_Context.GetRenderContext().GetViewport();
+
+ if (!m_AxisHelperWidget ) {
+ m_AxisHelperWidget
+ = qt3ds::widgets::IStudioWidget::CreateTranslationWidget(
+ m_Context.GetAllocator());
+ m_AxisHelperWidget->setAsAxisHelper(true);
+ }
+
+ auto layer = GetAxisHelperLayer();
+ if (layer != nullptr) {
+ updateAxisHelperFromSettings();
+ m_AxisHelperWidget->SetNode(*layer);
+ if (m_axisHelperEnabled)
+ m_Context.GetRenderer().AddRenderWidget(*m_AxisHelperWidget);
+ }
+ QVector<bool> layerDepthPrepasses = {};
if (scenePreviewPass) {
m_Context.GetRenderContext().SetViewport(GetPreviewViewport());
m_Context.SetSceneColor(Option<QT3DSVec4>());
+ } else {
+ SLayer *child = m_Scene->m_FirstChild;
+ do {
+ layerDepthPrepasses.append(child->m_Flags.IsLayerEnableDepthPrepass());
+ child->m_Flags.SetLayerEnableDepthPrepass(true);
+ child = (SLayer *)child->m_NextSibling;
+ } while (child);
}
- m_Scene->PrepareForRender(scenePreviewPass ? GetPreviewViewportDimensions()
- : GetViewportDimensions(), m_Context);
+ m_Scene->PrepareForRender(m_Context);
m_Context.RunRenderTasks();
@@ -2850,14 +3040,6 @@ void STranslation::Render(int inWidgetId, bool inDrawGuides, bool scenePreviewPa
m_Context.GetRenderContext().SetRenderTarget(nullptr);
m_Context.EndFrame();
- m_Context.GetRenderContext().SetViewport(viewport);
- QT3DSVec2 theViewportDims(GetViewportDimensions());
- m_Context.SetWindowDimensions(QSize((QT3DSU32)theViewportDims.x,
- (QT3DSU32)theViewportDims.y));
- CStudioProjectSettings *theSettings = m_Doc.GetCore()->GetStudioProjectSettings();
- QSize thePresSize = theSettings->getPresentationSize();
- m_Presentation.m_PresentationDimensions =
- QT3DSVec2((QT3DSF32)thePresSize.width(), (QT3DSF32)thePresSize.height());
if (m_ZoomRender.hasValue()) {
RenderZoomRender(*m_ZoomRender);
@@ -2886,6 +3068,15 @@ void STranslation::Render(int inWidgetId, bool inDrawGuides, bool scenePreviewPa
theRenderContext.SetDepthWriteEnabled( false );
m_Context.GetRenderer().RenderQuad( theDimensions, theVP, *m_PickBuffer );
}*/
+ if (!scenePreviewPass) {
+ SLayer *child = m_Scene->m_FirstChild;
+ int childIndex = 0;
+ do {
+ child->m_Flags.SetLayerEnableDepthPrepass(layerDepthPrepasses.at(childIndex));
+ child = (SLayer *)child->m_NextSibling;
+ ++childIndex;
+ } while (child);
+ }
}
}
@@ -3929,6 +4120,13 @@ void STranslation::PerformWidgetDrag(int inWidgetSubComponent, CPt inOriginalCoo
TORAD(theRad);
theRad = MakeNiceRotation(theRad);
QT3DSQuat theRotation(theRad, thePlaneNormal);
+
+ // Call SetRotationEdges also here so rotation angle text gets drawn.
+ // Here just draw it in the middle of rotation circle for simplicity.
+ m_CumulativeRotation = ShortestAngleDifference(m_CumulativeRotation, theRad);
+ m_LastRenderedWidget->SetRotationEdges(QT3DSVec3(0.0f), thePlaneNormal,
+ m_CumulativeRotation, 0.0f);
+
ApplyRotationToSelectedInstance(theRotation, *theNode, inEditor, false);
}
} break;
@@ -4125,6 +4323,13 @@ SNode *STranslation::GetEditCameraLayer()
return nullptr;
}
+SNode *STranslation::GetAxisHelperLayer()
+{
+ if (m_AxisHelperLayerTranslator)
+ return static_cast<SNode *>(&m_AxisHelperLayerTranslator->GetGraphObject());
+ return nullptr;
+}
+
PickTargetAreas::Enum STranslation::GetPickArea(CPt inPoint)
{
qt3ds::render::NVRenderRectF displayViewport = m_Context.GetDisplayViewport();
diff --git a/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.h b/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.h
index 3dd9134f..ed7ea70d 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.h
+++ b/src/Authoring/Qt3DStudio/Render/StudioRendererTranslation.h
@@ -96,6 +96,8 @@ namespace studio {
virtual void ClearChildren() = 0;
virtual void AppendChild(SGraphObject &inChild) = 0;
virtual void ResetEffect() {}
+ virtual const QString GetError() { return {}; }
+ virtual void SetError(const QString &error) { Q_UNUSED(error); }
virtual SGraphObject &GetGraphObject() { return *m_GraphObject; }
virtual SGraphObject &GetNonAliasedGraphObject() { return *m_GraphObject; }
virtual qt3dsdm::Qt3DSDMInstanceHandle GetInstanceHandle() { return m_InstanceHandle; }
@@ -151,7 +153,7 @@ namespace studio {
const QT3DSF32 g_EditCameraFOV = 45.0f;
const QT3DSF32 g_RotationScaleFactor = 2.0f * QT3DSF32(M_PI) / 180.0f;
- struct SEditCameraPersistentInformation
+ struct SEditorCameraInformation
{
QT3DSVec3 m_Position;
QT3DSVec3 m_Direction;
@@ -159,7 +161,7 @@ namespace studio {
EditCameraTypes::Enum m_CameraType;
NVReal m_xRotation = 0.0f;
NVReal m_yRotation = 0.0f;
- SEditCameraPersistentInformation()
+ SEditorCameraInformation()
: m_Position(0, 0, 0)
, m_Direction(0, 0, 0)
, m_ViewRadius(600)
@@ -167,7 +169,7 @@ namespace studio {
{
}
- void ApplyToCamera(SCamera &inCamera, QT3DSVec2 inViewport)
+ void ApplyToCamera(SCamera &inCamera, QT3DSVec2 inViewport, bool noScale = false)
{
// Setup shared default values.
inCamera.m_ClipFar = 2000000.0f;
@@ -210,6 +212,7 @@ namespace studio {
if (m_CameraType != EditCameraTypes::Directional) {
theRotationTransform.rotate(-m_xRotation, QT3DSVec3(0.0f, 1.0f, 0.0f));
theRotationTransform.rotate(m_yRotation, QT3DSVec3(1.0f, 0.0f, 0.0f));
+ inCamera.m_Rotation = inCamera.GetRotationVectorFromRotationMatrix(theRotationTransform.getUpper3x3());
}
// The view radius dictates the zoom.
@@ -228,7 +231,8 @@ namespace studio {
thePositionMatrix.column3.y = m_Position.y;
thePositionMatrix.column3.z = m_Position.z + 600;
theGlobalTransform = theGlobalTransform * theRotationTransform;
- theGlobalTransform = theGlobalTransform * theScaleMatrix;
+ if (!noScale)
+ theGlobalTransform = theGlobalTransform * theScaleMatrix;
theGlobalTransform = theGlobalTransform * thePivotMatrix.getInverse();
theGlobalTransform = theGlobalTransform * thePositionMatrix;
// This works because the camera has no hierarchy.
@@ -254,7 +258,7 @@ namespace studio {
};
};
- struct SEditCameraLayerTranslator;
+ struct SEditorLayerTranslator;
struct SZoomRender
{
CPt m_Point;
@@ -385,13 +389,17 @@ namespace studio {
bool m_EditCameraEnabled;
bool m_EditLightEnabled;
bool m_helperGridEnabled = true;
- SEditCameraPersistentInformation m_EditCameraInfo;
+ bool m_axisHelperEnabled = true;
+ SEditorCameraInformation m_EditCameraInfo;
SCamera m_EditCamera;
+ SCamera m_AxisCamera;
SLight m_EditLight;
QT3DSVec2 m_Viewport;
- SEditCameraLayerTranslator *m_EditCameraLayerTranslator;
+ SEditorLayerTranslator *m_EditCameraLayerTranslator;
+ SEditorLayerTranslator *m_AxisHelperLayerTranslator;
Option<SZoomRender> m_ZoomRender;
NVScopedRefCounted<qt3ds::widgets::IStudioWidget> m_TranslationWidget;
+ NVScopedRefCounted<qt3ds::widgets::IStudioWidget> m_AxisHelperWidget;
NVScopedRefCounted<qt3ds::widgets::IStudioWidget> m_RotationWidget;
NVScopedRefCounted<qt3ds::widgets::IStudioWidget> m_ScaleWidget;
NVScopedRefCounted<qt3ds::widgets::IStudioWidget> m_LastRenderedWidget;
@@ -660,6 +668,7 @@ namespace studio {
PickTargetAreas::Enum GetPickArea(CPt inPoint);
SNode *GetEditCameraLayer();
+ SNode *GetAxisHelperLayer();
void ReleaseEffect(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
void releaseMaterial(qt3dsdm::Qt3DSDMInstanceHandle inInstance);
@@ -677,6 +686,7 @@ namespace studio {
qt3dsdm::Qt3DSDMInstanceHandle GetAnchorPoint(QT3DSU32 inAnchorIndex);
void updateHelperGridFromSettings();
+ void updateAxisHelperFromSettings();
};
struct SDisableUseClearColor
diff --git a/src/Authoring/Qt3DStudio/Render/StudioSubPresentationRenderer.cpp b/src/Authoring/Qt3DStudio/Render/StudioSubPresentationRenderer.cpp
index b04233cd..e76f9ba4 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioSubPresentationRenderer.cpp
+++ b/src/Authoring/Qt3DStudio/Render/StudioSubPresentationRenderer.cpp
@@ -200,12 +200,9 @@ SOffscreenRendererEnvironment
StudioSubpresentationRenderer::GetDesiredEnvironment(QT3DSVec2 inPresentationScaleFactor)
{
// If we aren't using a clear color, then we are expected to blend with the background
- if (!m_thread->m_initialized) {
+ if (!m_thread->m_initialized)
initialize();
- }
- bool hasTransparency = true;
- NVRenderTextureFormats::Enum format =
- hasTransparency ? NVRenderTextureFormats::RGBA8 : NVRenderTextureFormats::RGB8;
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::RGBA8;
return SOffscreenRendererEnvironment(
QT3DSU32(m_thread->m_size.width() * inPresentationScaleFactor.x),
QT3DSU32(m_thread->m_size.height() * inPresentationScaleFactor.y),
@@ -257,7 +254,7 @@ void StudioSubpresentationRenderer::Render(const SOffscreenRendererEnvironment &
else
func->glEnable(GL_BLEND);
func->glBlendEquation(GL_FUNC_ADD);
- func->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ func->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (!m_program)
initializeFboCopy();
diff --git a/src/Authoring/Qt3DStudio/Render/StudioTranslationWidget.cpp b/src/Authoring/Qt3DStudio/Render/StudioTranslationWidget.cpp
index 8f426b3c..1ff7bd48 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioTranslationWidget.cpp
+++ b/src/Authoring/Qt3DStudio/Render/StudioTranslationWidget.cpp
@@ -46,7 +46,9 @@ struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translat
NVRenderInputAssembler *m_XAxis;
NVRenderInputAssembler *m_YAxis;
NVRenderInputAssembler *m_ZAxis;
-
+ NVRenderInputAssembler *m_wideXAxis;
+ NVRenderInputAssembler *m_wideYAxis;
+ NVRenderInputAssembler *m_wideZAxis;
NVRenderInputAssembler *m_XPlane;
NVRenderInputAssembler *m_YPlane;
NVRenderInputAssembler *m_ZPlane;
@@ -58,6 +60,9 @@ struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translat
, m_XAxis(nullptr)
, m_YAxis(nullptr)
, m_ZAxis(nullptr)
+ , m_wideXAxis(nullptr)
+ , m_wideYAxis(nullptr)
+ , m_wideZAxis(nullptr)
, m_XPlane(nullptr)
, m_YPlane(nullptr)
, m_ZPlane(nullptr)
@@ -108,7 +113,72 @@ struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translat
QT3DSVec3(axisPos, axisPos, 0), axisDiscRadius, axisRingRadius,
0.0f, 1.0f, "TranslationWidgetZPlane");
}
- QT3DSMat44 theMVP = TBase::SetupMVP(inWidgetContext);
+
+ QT3DSMat44 theMVP;
+
+ if (m_isAxisHelper) {
+ auto helpWidgetInfo
+ = inWidgetContext.GetWidgetRenderInformation(*m_Node,
+ QT3DSVec3(0, 0, 0),
+ RenderWidgetModes::Global);
+ auto viewport = inRenderContext.GetViewport();
+ SCamera theTempCamera;
+
+ QT3DSMat44 theViewProjection;
+ theTempCamera.m_Flags.SetOrthographic(true);
+
+ // Move the camera back far enough that we can see everything
+ static QT3DSF32 theCameraSetback(600);
+
+ // Move the camera to position axis helper to the lower left.
+ theTempCamera.m_Position.z = -theCameraSetback;
+ theTempCamera.m_Position.x = 0;
+ theTempCamera.m_Position.y = 0;
+ theTempCamera.m_ClipFar = 2.0f * theCameraSetback;
+ // Use entire viewport
+ theTempCamera.CalculateGlobalVariables(
+ viewport,
+ QT3DSVec2((QT3DSF32)viewport.m_Width, (QT3DSF32)viewport.m_Height));
+ theTempCamera.CalculateViewProjectionMatrix(theViewProjection);
+
+ // Get the rotation for the scene view camera (the actual direction of world axes)
+ // and rotate the widget axes to match world axes. Scale the widget to be smaller
+ // and less intrusive than actual translation widget.
+ auto rot = QT3DSMat44::createIdentity();
+ if (helpWidgetInfo.m_Camera->m_Flags.IsOrthographic()) {
+ rot = helpWidgetInfo.m_Camera->m_LocalTransform;
+ rot.setPosition({0, 0, 0});
+ rot = rot.getInverse().getTranspose();
+ } else {
+ helpWidgetInfo.m_Camera->CalculateRotationMatrix(rot);
+ }
+
+ helpWidgetInfo.m_Camera->FlipCoordinateSystem(rot);
+ // In the scale calculation 200.f = 120 / 0.6; 120 being the default width and 0.6
+ // being the default scale for the axis helper
+ const float scale = float(viewport.m_Width) / 200.f;
+ rot.scale(QT3DSVec4(scale, scale, scale, 1));
+ theMVP = theViewProjection * rot.getTranspose();
+
+ if (m_wideXAxis == nullptr) {
+ QT3DSF32 axisWidth = 6;
+ QT3DSF32 triWidth = axisWidth * 3;
+ QT3DSF32 axisStart = 0;
+ QT3DSF32 axisLength = axisWidth * 10;
+ QT3DSF32 triLength = axisWidth * 5;
+ m_wideXAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext,
+ QT3DSVec3(1, 0, 0), axisStart, axisLength, triLength,
+ axisWidth, triWidth, "TranslationWidgetWideXAxis");
+ m_wideYAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext,
+ QT3DSVec3(0, 1, 0), axisStart, axisLength, triLength,
+ axisWidth, triWidth, "TranslationWidgetWideYAxis");
+ m_wideZAxis = CreateAxis(m_Allocator, inWidgetContext, inRenderContext,
+ QT3DSVec3(0, 0, -1), axisStart, axisLength, triLength,
+ axisWidth, triWidth, "TranslationWidgetWideZAxis");
+ }
+ } else {
+ theMVP = TBase::SetupMVP(inWidgetContext);
+ }
if (isNodeBehindCamera())
return;
@@ -127,18 +197,27 @@ struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translat
QT3DSVec3 theZColor(GetZAxisColor());
QT3DSVec3 theRingColor(QT3DSVec3(.8f, .8f, .8f));
- RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
- m_XAxis);
- RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
- m_YAxis);
- RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
- m_ZAxis);
- RenderTwoToneGeometry(StudioWidgetComponentIds::XPlane, theXColor, theRingColor,
- inRenderContext, m_XPlane);
- RenderTwoToneGeometry(StudioWidgetComponentIds::YPlane, theYColor, theRingColor,
- inRenderContext, m_YPlane);
- RenderTwoToneGeometry(StudioWidgetComponentIds::ZPlane, theZColor, theRingColor,
- inRenderContext, m_ZPlane);
+ if (!m_isAxisHelper) {
+ RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
+ m_XAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
+ m_YAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
+ m_ZAxis);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::XPlane, theXColor, theRingColor,
+ inRenderContext, m_XPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::YPlane, theYColor, theRingColor,
+ inRenderContext, m_YPlane);
+ RenderTwoToneGeometry(StudioWidgetComponentIds::ZPlane, theZColor, theRingColor,
+ inRenderContext, m_ZPlane);
+ } else {
+ RenderSingleToneGeometry(StudioWidgetComponentIds::XAxis, theXColor, inRenderContext,
+ m_wideXAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::YAxis, theYColor, inRenderContext,
+ m_wideYAxis);
+ RenderSingleToneGeometry(StudioWidgetComponentIds::ZAxis, theZColor, inRenderContext,
+ m_wideZAxis);
+ }
m_Highlight = StudioWidgetComponentIds::NoId;
}
@@ -168,6 +247,11 @@ struct STranslationWidget : public SStudioWidgetImpl<StudioWidgetTypes::Translat
RenderPickBuffer(StudioWidgetComponentIds::ZPlane, m_ZPlane, inRenderContext);
}
}
+
+ void setAsAxisHelper(bool isAxisHelper) override
+ {
+ m_isAxisHelper = isAxisHelper;
+ }
};
}
diff --git a/src/Authoring/Qt3DStudio/Render/StudioWidget.h b/src/Authoring/Qt3DStudio/Render/StudioWidget.h
index 897c71cf..1287612e 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioWidget.h
+++ b/src/Authoring/Qt3DStudio/Render/StudioWidget.h
@@ -115,6 +115,8 @@ namespace widgets {
QT3DSF32 inColorIndex, TResultVecType &outResult);
void SetNode(SNode &inNode) override = 0;
+ virtual void setAsAxisHelper(bool isAxisWidget) = 0;
+
virtual StudioWidgetTypes::Enum GetWidgetType() const = 0;
virtual void SetSubComponentId(int inSubComponentId) = 0;
virtual void SetRenderWidgetMode(RenderWidgetModes::Enum inSpace) = 0;
diff --git a/src/Authoring/Qt3DStudio/Render/StudioWidgetImpl.h b/src/Authoring/Qt3DStudio/Render/StudioWidgetImpl.h
index d963bee1..9205fc5d 100644
--- a/src/Authoring/Qt3DStudio/Render/StudioWidgetImpl.h
+++ b/src/Authoring/Qt3DStudio/Render/StudioWidgetImpl.h
@@ -92,6 +92,7 @@ namespace widgets {
NVRenderVertexBuffer *m_ImmediateVertexBuffer;
NVRenderInputAssembler *m_ImmediateInputAssembler;
NVRenderShaderProgram *m_ImmediateShader;
+ bool m_isAxisHelper;
SStudioWidgetImpl(NVAllocatorCallback &inAlloc)
: m_Allocator(inAlloc)
@@ -104,6 +105,7 @@ namespace widgets {
, m_ImmediateVertexBuffer(NULL)
, m_ImmediateInputAssembler(NULL)
, m_ImmediateShader(NULL)
+ , m_isAxisHelper(false)
{
}
@@ -319,6 +321,8 @@ namespace widgets {
void SetAxisScale(const QT3DSVec3 &inAxisScale) override { m_AxisScale = inAxisScale; }
+ void setAsAxisHelper(bool isAxisHelper) override { m_isAxisHelper = isAxisHelper; }
+
void SetRotationEdges(const QT3DSVec3 &inStartDirection, const QT3DSVec3 &inRotationAxis,
QT3DSF32 inAngleRad, QT3DSF32 inEndLineLen) override
{
diff --git a/src/Authoring/Qt3DStudio/UI/SceneView.cpp b/src/Authoring/Qt3DStudio/UI/SceneView.cpp
index 46b8ccac..653fcd9b 100644
--- a/src/Authoring/Qt3DStudio/UI/SceneView.cpp
+++ b/src/Authoring/Qt3DStudio/UI/SceneView.cpp
@@ -338,6 +338,10 @@ void CSceneView::setToolMode(long inMode)
*/
void CSceneView::onEditCameraChanged()
{
+ // Update the view mode accordingly
+ setViewMode(g_StudioApp.getRenderer().GetEditCamera() >= 0 ? CPlayerContainerWnd::VIEW_EDIT
+ : CPlayerContainerWnd::VIEW_SCENE);
+
// Reset any scrolling and recalculate the window position.
if (m_playerContainerWnd) {
m_playerContainerWnd->SetScrollRanges();
@@ -345,9 +349,6 @@ void CSceneView::onEditCameraChanged()
setPlayerWndPosition();
}
- // Update the view mode accordingly
- setViewMode(g_StudioApp.getRenderer().GetEditCamera() >= 0 ? CPlayerContainerWnd::VIEW_EDIT
- : CPlayerContainerWnd::VIEW_SCENE);
m_playerWnd->update();
}
diff --git a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.cpp b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.cpp
index df918d19..bf0dc167 100644
--- a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.cpp
+++ b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.cpp
@@ -90,7 +90,6 @@ void CStudioAppPrefsPage::onInitDialog()
// Add tool tips for controls
m_ui->m_DefaultInterpolation->setToolTip(tr("Set default keyframe interpolation type"));
m_ui->m_checkTimelineAbsoluteSnapping->setToolTip(tr("Enable timeline snapping grid"));
- m_ui->m_checkLegacyViewer->setToolTip(tr("Enable preview with Qt3D Runtime Viewer"));
m_ui->m_SnapRangeCombo->setToolTip(tr("Set resolution of timeline snapping grid"));
m_ui->m_buttonRestoreDefaults->setToolTip(tr("Click to restore default Studio settings"));
@@ -115,12 +114,12 @@ void CStudioAppPrefsPage::onInitDialog()
onApply(); // Save changed preferences before resetting, as it causes Studio to shut down
CStudioPreferencesPropPage::endDialog(PREFS_RESET_LAYOUT);
});
+ connect(m_ui->m_buttonResetPopupWarnings, &QPushButton::clicked, this,
+ &CStudioAppPrefsPage::onButtonResetPopupWarnings);
connect(m_ui->m_DefaultInterpolation, activated, this, [=](){ setModified(true); });
connect(m_ui->m_SnapRangeCombo, activated, this, [=](){ setModified(true); });
connect(m_ui->m_checkTimelineAbsoluteSnapping, &QCheckBox::clicked,
this, [=](){ setModified(true); enableOptions(); });
- connect(m_ui->m_checkLegacyViewer, &QCheckBox::clicked,
- this, [=](){ setModified(true); m_restartNeeded = true; });
connect(m_ui->m_EditViewStartupView, activated, this, [=](){ setModified(true); });
connect(m_ui->helperGridLinesSpinBox,
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
@@ -170,9 +169,6 @@ void CStudioAppPrefsPage::loadSettings()
m_ui->m_checkTimelineAbsoluteSnapping->setChecked(
CStudioPreferences::isTimelineSnappingGridActive());
- // Legacy viewer
- m_ui->m_checkLegacyViewer->setChecked(CStudioPreferences::isLegacyViewerActive());
-
// Helper grid
m_ui->helperGridLinesSpinBox->setValue(CStudioPreferences::helperGridLines());
m_ui->helperGridSpacingSpinBox->setValue(CStudioPreferences::helperGridSpacing());
@@ -220,9 +216,6 @@ void CStudioAppPrefsPage::saveSettings()
int theCurrentSelection = m_ui->m_SnapRangeCombo->currentIndex();
CStudioPreferences::setTimelineSnappingGridResolution(ESnapGridResolution(theCurrentSelection));
- // Viewing settings
- // Legacy viewer
- CStudioPreferences::setLegacyViewerActive(m_ui->m_checkLegacyViewer->isChecked());
// Preferred Startup View
CStudioPreferences::setPreferredStartupView(m_ui->m_EditViewStartupView->currentIndex());
@@ -293,6 +286,12 @@ void CStudioAppPrefsPage::onButtonRestoreDefaults()
}
}
+void CStudioAppPrefsPage::onButtonResetPopupWarnings()
+{
+ // Setters per pop-up type
+ CStudioPreferences::setDoNotShowImportWarnings(false);
+}
+
//==============================================================================
/**
* EnableOptions: Enable/disable options.
diff --git a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.h b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.h
index abea304b..d2aa18ca 100644
--- a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.h
+++ b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.h
@@ -76,6 +76,7 @@ protected:
#if 0 // Removed until we have some other Preview configurations that just Viewer
void onChangePreviewConfiguration();
#endif
+ void onButtonResetPopupWarnings();
void enableAutosave(bool enabled);
void setAutosaveInterval(int interval);
diff --git a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.ui b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.ui
index d9187726..a49ceda4 100644
--- a/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.ui
+++ b/src/Authoring/Qt3DStudio/UI/StudioAppPrefsPage.ui
@@ -30,6 +30,9 @@
</property>
</widget>
</item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="m_SnapRangeCombo"/>
+ </item>
<item row="0" column="1">
<widget class="QComboBox" name="m_DefaultInterpolation">
<property name="maximumSize">
@@ -40,9 +43,6 @@
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QComboBox" name="m_SnapRangeCombo"/>
- </item>
<item row="1" column="0">
<widget class="QCheckBox" name="m_checkTimelineAbsoluteSnapping">
<property name="text">
@@ -50,13 +50,6 @@
</property>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="m_checkLegacyViewer">
- <property name="text">
- <string>Qt3D Viewer</string>
- </property>
- </widget>
- </item>
</layout>
</widget>
</item>
@@ -424,6 +417,16 @@ palette positions and visibilities</string>
</widget>
</item>
<item>
+ <widget class="QPushButton" name="m_buttonResetPopupWarnings">
+ <property name="toolTip">
+ <string>Click to clear &quot;Do not Show Again&quot; selections in all pop-ups.</string>
+ </property>
+ <property name="text">
+ <string>Reset Pop-up Warnings</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
diff --git a/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.cpp b/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.cpp
index d011d57c..030d1dac 100644
--- a/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.cpp
+++ b/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.cpp
@@ -32,6 +32,7 @@
#include "StudioProjectSettingsPage.h"
#include "StudioProjectSettings.h"
#include "StudioApp.h"
+#include "IDocumentBufferCache.h"
#include "Doc.h"
#include "Views.h"
#include "MainFrm.h"
@@ -100,6 +101,7 @@ void CStudioProjectSettingsPage::onInitDialog()
connect(m_ui->m_checkConstrainProportions, &QCheckBox::clicked,
this, &CStudioProjectSettingsPage::onCheckMaintainRatio);
connect(m_ui->m_checkUseKtx, &QCheckBox::clicked, [=](){ this->setModified(true); });
+ connect(m_ui->m_checkFlipTex, &QCheckBox::clicked, [=](){ this->setModified(true); });
connect(m_ui->m_Author, &QLineEdit::textEdited, [=](){ this->setModified(true); });
connect(m_ui->m_Company, &QLineEdit::textEdited, [=](){ this->setModified(true); });
}
@@ -130,6 +132,9 @@ void CStudioProjectSettingsPage::loadSettings()
// Prefer compressed textures
m_ui->m_checkUseKtx->setChecked(theProjectSettings->getPreferCompressedTextures());
+ // Automatically flip compressed textures
+ m_ui->m_checkFlipTex->setChecked(theProjectSettings->getFlipCompressedTextures());
+
// Author
m_ui->m_Author->setText(theProjectSettings->getAuthor());
@@ -169,6 +174,12 @@ void CStudioProjectSettingsPage::saveSettings()
// Prefer compressed textures
theProjectSettings->setPreferCompressedTextures(m_ui->m_checkUseKtx->isChecked());
+
+ // Automatically flip compressed textures. Trigger reloading if flip status changed.
+ bool updatedFlipTextures = m_ui->m_checkFlipTex->isChecked();
+ if (theProjectSettings->getFlipCompressedTextures() != updatedFlipTextures)
+ g_StudioApp.GetCore()->GetDoc()->GetBufferCache().reloadAll(updatedFlipTextures);
+ theProjectSettings->setFlipCompressedTextures(updatedFlipTextures);
}
// OnApply: Handler for the Apply button
diff --git a/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.ui b/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.ui
index 3ef4ccd2..e6c3d767 100644
--- a/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.ui
+++ b/src/Authoring/Qt3DStudio/UI/StudioProjectSettingsPage.ui
@@ -86,6 +86,16 @@ when ktx textures are present.</string>
</property>
</widget>
</item>
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="m_checkFlipTex">
+ <property name="toolTip">
+ <string>Flip the y coordinate of compressed textures</string>
+ </property>
+ <property name="text">
+ <string>Flip compressed textures</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp b/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
index d8365a7e..93dc220c 100644
--- a/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
+++ b/src/Authoring/Qt3DStudio/Workspace/Dialogs.cpp
@@ -364,9 +364,11 @@ void CDialogs::DisplayImportFailed(const QUrl &inURL, const QString &inDescripti
theMsgText += QStringLiteral("\n%1\n\n").arg(inURL.toDisplayString()) + theText;
// Display the failed import resource message.
- if (m_ShowGUI) {
- Qt3DSMessageBox::Show(theTitle, theMsgText, Qt3DSMessageBox::ICON_WARNING, false,
- g_StudioApp.m_pMainWnd);
+ if (m_ShowGUI && !CStudioPreferences::doNotShowImportWarnings()) {
+ bool doNotShowAgain = false;
+ Qt3DSMessageBox::Show(theTitle, theMsgText, Qt3DSMessageBox::ICON_WARNING, doNotShowAgain,
+ false, true, g_StudioApp.m_pMainWnd);
+ CStudioPreferences::setDoNotShowImportWarnings(doNotShowAgain);
} else {
qCDebug(qt3ds::TRACE_INFO) << theTitle << ": " << theMsgText;
}
diff --git a/src/Authoring/Qt3DStudio/images.qrc b/src/Authoring/Qt3DStudio/images.qrc
index b808711e..9dfdee3b 100644
--- a/src/Authoring/Qt3DStudio/images.qrc
+++ b/src/Authoring/Qt3DStudio/images.qrc
@@ -331,6 +331,12 @@
<file>images/gradient@2x.png</file>
<file>images/gradient_disabled.png</file>
<file>images/gradient_disabled@2x.png</file>
+ <file>images/Asset-Signal-Normal.png</file>
+ <file>images/Asset-Signal-Normal@2x.png</file>
+ <file>images/Objects-Signal-Normal.png</file>
+ <file>images/Objects-Signal-Normal@2x.png</file>
+ <file>images/Objects-Signal-Disabled.png</file>
+ <file>images/Objects-Signal-Disabled@2x.png</file>
</qresource>
<qresource prefix="/startup">
<file alias="open_dialog.png">images/open_dialog.png</file>
diff --git a/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal.png b/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal.png
new file mode 100644
index 00000000..dda0e2c3
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal.png
Binary files differ
diff --git a/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal@2x.png b/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal@2x.png
new file mode 100644
index 00000000..04f34fd1
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Asset-Signal-Normal@2x.png
Binary files differ
diff --git a/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled.png b/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled.png
new file mode 100644
index 00000000..e1301aa4
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled.png
Binary files differ
diff --git a/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled@2x.png b/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled@2x.png
new file mode 100644
index 00000000..905e23a1
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Objects-Signal-Disabled@2x.png
Binary files differ
diff --git a/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal.png b/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal.png
new file mode 100644
index 00000000..2463c2f1
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal.png
Binary files differ
diff --git a/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal@2x.png b/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal@2x.png
new file mode 100644
index 00000000..50932af4
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/images/Objects-Signal-Normal@2x.png
Binary files differ
diff --git a/src/Runtime/Runtime.pro b/src/Runtime/Runtime.pro
index eba449a2..8b07be9d 100644
--- a/src/Runtime/Runtime.pro
+++ b/src/Runtime/Runtime.pro
@@ -1,7 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS += \
- ogl-runtime \
+SUBDIRS += ogl-runtime
# HACK to ensure syncqt is run for ogl-runtime if one is run for studio
# This is necessary because CI doesn't create dummy .git directories for submodules
@@ -13,20 +12,3 @@ if(!build_pass|!debug_and_release) {
$$system("$$MAKE_DIR_CMD")
}
}
-
-
-# Qt3D based runtime needs Qt 5.11 or later
-greaterThan(QT_MAJOR_VERSION, 5)|greaterThan(QT_MINOR_VERSION, 10) {
- SUBDIRS += qt3d-runtime
-
- # HACK to ensure syncqt is run for qt3d-runtime if one is run for studio
- # This is necessary because CI doesn't create dummy .git directories for submodules
- if(!build_pass|!debug_and_release) {
- # Pro file existence is checked to ensure we don't create dummy .git in empty submodule dir,
- # which happens when studio is cloned without --recursive option
- exists($$PWD/../../.git):!exists($$PWD/qt3d-runtime/.git):exists($$PWD/qt3d-runtime/qt3d-runtime.pro) {
- MAKE_DIR_CMD = $$sprintf($$QMAKE_MKDIR_CMD, $$shell_quote($$shell_path($$PWD/qt3d-runtime/.git)))
- $$system("$$MAKE_DIR_CMD")
- }
- }
-}
diff --git a/src/Runtime/ogl-runtime b/src/Runtime/ogl-runtime
-Subproject 9395963fdef3030136c242dc27bbd5e17566f05
+Subproject 427fddb50d43aa21a90fc7356ee3cdd8a908df5
diff --git a/src/Runtime/qt3d-runtime b/src/Runtime/qt3d-runtime
deleted file mode 160000
-Subproject bd083f50691e35ac0ab572ebc92fe15dae2f298