From 324a151bf8d945d10486bc4fdb60613c1f84817e Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Tue, 8 Aug 2017 14:46:36 +0200 Subject: [PATCH 01/12] add update function --- data/gloperate/qml/PipelineView.qml | 5 +++++ data/gloperate/qml/Viewer.qml | 1 + 2 files changed, 6 insertions(+) diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index 40b57cb6..144a7363 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -76,4 +76,9 @@ Item pipelineEditor.load(path); } } + + function update() + { + pipelineEditor.update(); + } } diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index 70c3d1c0..0621bae6 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -247,6 +247,7 @@ ApplicationWindow settings.stage = name; window.stage = name; propertyEditor.update(); + pipelineView.update(); } } From 91ca1dd2f6cf2039bde2f3d2b4b992085d9361d4 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Wed, 16 Aug 2017 12:15:09 +0200 Subject: [PATCH 02/12] implement internal and external editor concept --- data/gloperate/qml/PipelineView.qml | 28 +++++++--- data/gloperate/qml/SettingsPage.qml | 20 +++++++ data/gloperate/qml/Viewer.qml | 87 ++++++++++++++++++++++++++--- 3 files changed, 120 insertions(+), 15 deletions(-) diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index 144a7363..0bc50f39 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -13,9 +13,11 @@ Item id: page signal closed() + signal toggled() - property var properties: null ///< Interface for communicating with the actual properties - property string path: '' ///< Path to pipeline + property var properties: null ///< Interface for communicating with the actual properties + property string path: '' ///< Path to pipeline + property string toggleButton: '' ///< Description of the toggle state button implicitWidth: pipelineEditor.implicitWidth implicitHeight: pipelineEditor.implicitHeight @@ -42,6 +44,21 @@ Item } } + Button + { + text: page.toggleButton + visible: page.toggleButton === "" ? false : true + + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: Ui.style.paddingMedium + + onClicked: + { + page.toggled(); + } + } + Rectangle { x: 100 @@ -69,12 +86,9 @@ Item } } - onVisibleChanged: + function load() { - if (visible) - { - pipelineEditor.load(path); - } + pipelineEditor.load(path); } function update() diff --git a/data/gloperate/qml/SettingsPage.qml b/data/gloperate/qml/SettingsPage.qml index 3bcb1fa3..ae025047 100644 --- a/data/gloperate/qml/SettingsPage.qml +++ b/data/gloperate/qml/SettingsPage.qml @@ -122,6 +122,26 @@ Item } } + Label + { + Layout.alignment: Qt.AlignRight + + text: 'Pipeline Editor' + } + + ComboBox + { + model: [ 'external', 'internal' ] + + currentIndex: model.indexOf(settings.editor) + + onActivated: + { + var editor = model[index]; + settings.editor = editor; + } + } + Label { Layout.alignment: Qt.AlignRight | Qt.AlignTop diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index 0621bae6..d78b942e 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -1,6 +1,7 @@ import QtQuick 2.4 import QtQuick.Layouts 1.1 +import QtQuick.Window 2.2 import QmlToolbox.Base 1.0 import QmlToolbox.Controls 1.0 @@ -163,8 +164,7 @@ ApplicationWindow onTriggered: { - pipelineView.visible = true; - mainView.visible = false; + showEditor(); } } } @@ -247,7 +247,8 @@ ApplicationWindow settings.stage = name; window.stage = name; propertyEditor.update(); - pipelineView.update(); + internalPipelineView.update(); + externalPipelineView.update(); } } @@ -323,19 +324,88 @@ ApplicationWindow // Pipeline view PipelineView { - id: pipelineView + id: internalPipelineView anchors.fill: parent visible: false - properties: gloperatePipeline - path: 'root' + properties: gloperatePipeline + path: 'root' + toggleButton: 'Open in new window' onClosed: { - mainView.visible = true; - pipelineView.visible = false; + hideEditor(); } + + onToggled: + { + toggleEditor(); + } + } + } + + // Pipeline view in separate window + Window + { + id: popoutWindow + + title: 'Pipeline Editor' + + PipelineView + { + id: externalPipelineView + + anchors.fill: parent + + properties: gloperatePipeline + path: 'root' + toggleButton: 'Show inside main window' + + onClosed: + { + hideEditor(); + } + + onToggled: + { + toggleEditor(); + } + } + } + + // Toggles between internal and external pipeline editor + function toggleEditor() + { + hideEditor(); + settings.editor = (settings.editor === "internal" ? "external" : "internal"); + showEditor(); + } + + // Shows the pipeline editor + function showEditor() + { + if (settings.editor === "internal") + { + internalPipelineView.visible = true; + mainView.visible = false; + internalPipelineView.load(); + } else { + popoutWindow.showMaximized(); + popoutWindow.raise(); + externalPipelineView.load(); + } + } + + // Hides the pipeline editor + function hideEditor() + { + if (settings.editor === "internal") + { + mainView.visible = true; + internalPipelineView.visible = false; + } else { + popoutWindow.hide(); } } @@ -406,6 +476,7 @@ ApplicationWindow property int logLevel: 3 property bool debugMode: false property string panelPosition: 'left' + property string editor: 'internal' property string stage: '' property string pluginPaths: '' From 57c71112b39429a2ce029911a9a48b826abcb1ac Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Wed, 16 Aug 2017 12:42:21 +0200 Subject: [PATCH 03/12] add minimum size for window --- data/gloperate/qml/Viewer.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index d78b942e..db0e32d4 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -352,6 +352,9 @@ ApplicationWindow title: 'Pipeline Editor' + minimumWidth: 750 + minimumHeight: 550 + PipelineView { id: externalPipelineView From 2099c68139abdd6b498ad144f24b720bae2057b2 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 17 Aug 2017 15:49:25 +0200 Subject: [PATCH 04/12] provide feedback information for connections --- source/gloperate/source/base/Canvas.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index d63273b4..b3442d36 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -656,6 +656,11 @@ cppexpose::Variant Canvas::scr_getConnections(const std::string & path) (*connection.asMap())["from"] = from; (*connection.asMap())["to"] = to; + if (slot->isFeedback()) + { + (*connection.asMap())["feedback"] = true; + } + // Add connection obj.asArray()->push_back(connection); } From 809f60993cc1782061789b6518ebea407ceb14d4 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Wed, 23 Aug 2017 16:27:13 +0200 Subject: [PATCH 05/12] add required information --- source/gloperate/source/base/Canvas.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index b3442d36..27fb53bc 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -862,6 +862,7 @@ cppexpose::Variant Canvas::getSlotStatus(const std::string & path, const std::st (*status.asMap())["name"] = slot->name(); (*status.asMap())["type"] = slot->typeName(); (*status.asMap())["value"] = slot->toVariant(); + (*status.asMap())["required"] = slot->isRequired(); // Include options const VariantMap & options = slot->options(); From 55b7db401b4992f3027f72db03ba3a4edf964e23 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Wed, 16 Aug 2017 15:57:39 +0200 Subject: [PATCH 06/12] add preview item --- data/gloperate/qml/PipelineView.qml | 25 ++--------------- data/gloperate/qml/PreviewItem.qml | 43 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 23 deletions(-) create mode 100644 data/gloperate/qml/PreviewItem.qml diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index 0bc50f39..35796706 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -59,30 +59,9 @@ Item } } - Rectangle + PreviewItem { - x: 100 - y: 100 - width: 200 - height: 200 - - color: 'white' - border.color: 'black' - border.width: 1 - - TextureItem - { - anchors.fill: parent - anchors.margins: 1 - - path: 'ShapeDemo.Framebuffer.colorTexture' - } - - MouseArea - { - anchors.fill: parent - drag.target: parent - } + path: 'ShapeDemo.Framebuffer.colorTexture' } } diff --git a/data/gloperate/qml/PreviewItem.qml b/data/gloperate/qml/PreviewItem.qml new file mode 100644 index 00000000..0386f091 --- /dev/null +++ b/data/gloperate/qml/PreviewItem.qml @@ -0,0 +1,43 @@ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.0 + +import QmlToolbox.Base 1.0 +import QmlToolbox.Controls 1.0 + +import gloperate.rendering 1.0 + + +Item +{ + id: previewItem + + property string path: '' ///< holds the path to the texture + + Rectangle + { + x: 100 + y: 100 + width: 200 + height: 200 + + color: 'white' + border.color: 'black' + border.width: 1 + + TextureItem + { + anchors.fill: parent + anchors.margins: 1 + + path: previewItem.path + } + + MouseArea + { + anchors.fill: parent + drag.target: parent + } + } +} From 960c886291de49a148a274a9e3c7e250554abe34 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 24 Aug 2017 12:30:09 +0200 Subject: [PATCH 07/12] add internal stages concept and preview stage in internal viewer --- data/gloperate/qml/GlOperatePipeline.qml | 92 ++++++++++++++++++- data/gloperate/qml/InternalStage.qml | 76 +++++++++++++++ data/gloperate/qml/PipelineView.qml | 20 +++- data/gloperate/qml/PreviewItem.qml | 23 +++-- data/gloperate/qml/PreviewStage.qml | 57 ++++++++++++ data/gloperate/qml/Viewer.qml | 14 +++ .../source/TextureItemRenderer_ogl.cpp | 10 +- 7 files changed, 270 insertions(+), 22 deletions(-) create mode 100644 data/gloperate/qml/InternalStage.qml create mode 100644 data/gloperate/qml/PreviewStage.qml diff --git a/data/gloperate/qml/GlOperatePipeline.qml b/data/gloperate/qml/GlOperatePipeline.qml index c147ba83..8e32be24 100644 --- a/data/gloperate/qml/GlOperatePipeline.qml +++ b/data/gloperate/qml/GlOperatePipeline.qml @@ -13,8 +13,9 @@ Item signal slotChanged(string path, string slot, var status) - // Canvas scripting interface (accessed by 'root') - property var canvas: null + property var canvas: null ///< Canvas scripting interface (accessed by 'root') + property var internalStages: {} ///< Store stages only accessible for scripting and UI + property string editor: '' ///< State of editor function getStageTypes() { @@ -71,12 +72,35 @@ Item { var connections = canvas ? canvas.getConnections(path) : null; - if (connections) return connections; - else return []; + if (!connections) + { + return []; + } + + if (path === "root") + { + for (var internalPath in internalStages) + { + if (isVisible(internalStages[internalPath])) + { + connections = connections.concat(internalStages[internalPath].getConnections()); + } + } + } + + return connections; } function createConnection(sourcePath, sourceSlot, destPath, destSlot) { + for (var internalPath in internalStages) + { + if (destPath === internalPath) + { + internalStages[internalPath].connectionCreated(sourcePath, sourceSlot, destPath, destSlot); + } + } + if (canvas) { canvas.createConnection(sourcePath, sourceSlot, destPath, destSlot); @@ -85,6 +109,14 @@ Item function removeConnection(path, slot) { + for (var internalPath in internalStages) + { + if (path === internalPath) + { + internalStages[internalPath].connectionRemoved(path, slot); + } + } + if (canvas) { canvas.removeConnection(path, slot); @@ -95,6 +127,26 @@ Item { var info = canvas ? canvas.getStage(path) : null; + if (info && path === "root") + { + for (var internalPath in internalStages) + { + var stage = internalStages[internalPath]; + if (isVisible(stage)) + { + info.stages.push(stage.name); + } + } + } + + for (var internalPath in internalStages) + { + if (path === internalPath) + { + return internalStages[internalPath].getDescription(); + } + } + if (info) { return info; } else { @@ -137,4 +189,36 @@ Item canvas.setValue(path, slot, value); } } + + function isVisible(stage) + { + return editor === 'internal' ? stage.isVisibleInternal : stage.isVisibleExternal; + } + + function getInternalStages() + { + var stages = {}; + + for (var internalPath in internalStages) + { + var stage = internalStages[internalPath]; + + if (isVisible(stage)) + { + stages[internalPath] = stage; + } + } + + return stages; + } + + function clearInternalStages() + { + internalStages = {}; + } + + function addInternalStage(stage) + { + internalStages[stage.path] = stage; + } } diff --git a/data/gloperate/qml/InternalStage.qml b/data/gloperate/qml/InternalStage.qml new file mode 100644 index 00000000..a7d9bed3 --- /dev/null +++ b/data/gloperate/qml/InternalStage.qml @@ -0,0 +1,76 @@ + +import QtQuick 2.0 + + +/** +* InternalStage +* +* Describes the state of an internal stage for (scripting and UI), only supports inputs +*/ +Item +{ + id: stage + + signal connectionCreated(string sourcePath, string sourceSlot, string destPath, string destSlot) + signal connectionRemoved(string path, string slot) + + property string name: '' ///< Name of the stage (for display) + property string path: '' ///< Path of the stage + property var inputs: [] ///< Input configuration of the stage + property var connections: {} ///< Connections to this stage + + property bool isVisibleInternal: true ///< Whether this stage should be visible in 'internal' mode + property bool isVisibleExternal: true ///< Whether this stage should be visible in 'external' mode + + function configureComponents(stageItem) {} ///< Configure stage item in pipeline editor + + onConnectionCreated: + { + if (connections === undefined) + { + connections = {}; + } + connections[destSlot] = sourcePath + '.' + sourceSlot; + } + + onConnectionRemoved: + { + if (connections === undefined) + { + return; + } + + delete connections[slot]; + } + + // Generate stage description with inputs, outputs, and stages + function getDescription() { + var inputNames = []; + + for (var i in inputs) + { + var input = inputs[i]; + inputNames.push(input.name); + } + + return { + name: path, + inputs: inputNames, + outputs: [], + stages: [] + }; + } + + // Generate stage connections + function getConnections() { + var connectionList = []; + + for (var slot in connections) + { + connectionList.push({from: connections[slot], to: path + '.' + slot}); + } + + return connectionList; + } + +} diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index 35796706..a97da89c 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -58,20 +58,30 @@ Item page.toggled(); } } - - PreviewItem - { - path: 'ShapeDemo.Framebuffer.colorTexture' - } } function load() { pipelineEditor.load(path); + + configureInternalStages(properties.getInternalStages()); } function update() { pipelineEditor.update(); + + configureInternalStages(properties.getInternalStages()); + } + + function configureInternalStages(internalStages) + { + for (var stageName in internalStages) + { + var stageDefinition = internalStages[stageName]; + var stageObject = pipelineEditor.pipeline.stageItems[stageDefinition.name]; + + stageDefinition.configureComponents(stageObject); + } } } diff --git a/data/gloperate/qml/PreviewItem.qml b/data/gloperate/qml/PreviewItem.qml index 0386f091..b5551d57 100644 --- a/data/gloperate/qml/PreviewItem.qml +++ b/data/gloperate/qml/PreviewItem.qml @@ -1,10 +1,7 @@ import QtQuick 2.0 -import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.0 import QmlToolbox.Base 1.0 -import QmlToolbox.Controls 1.0 import gloperate.rendering 1.0 @@ -15,12 +12,14 @@ Item property string path: '' ///< holds the path to the texture + implicitWidth: 200 + implicitHeight: 180 + Rectangle { - x: 100 - y: 100 - width: 200 - height: 200 + anchors.fill: parent + anchors.leftMargin: Ui.style.pipelineSlotSize + anchors.rightMargin: Ui.style.pipelineSlotSize / 2 color: 'white' border.color: 'black' @@ -34,10 +33,10 @@ Item path: previewItem.path } - MouseArea - { - anchors.fill: parent - drag.target: parent - } + // MouseArea + // { + // anchors.fill: parent + // drag.target: parent + // } } } diff --git a/data/gloperate/qml/PreviewStage.qml b/data/gloperate/qml/PreviewStage.qml new file mode 100644 index 00000000..f2289a97 --- /dev/null +++ b/data/gloperate/qml/PreviewStage.qml @@ -0,0 +1,57 @@ + +import QtQuick 2.0 + +import gloperate.rendering 1.0 + + +/** +* PreviewStage +* +* Describes the state of a preview stage +*/ +Item +{ + id: previewStage + + property var stageDefinition: internalStage ///< For access to stage definition + + property var previewComponent: null ///< Preview component on stage item in pipeline editor + + InternalStage + { + id: internalStage + + name: 'PreviewStage' + path: 'root.PreviewStage' + + inputs: [ + { + name: 'PreviewTexture', + type: 'texture', + value: null, + } + ] + + isVisibleInternal: true + isVisibleExternal: false + + onConnectionCreated: + { + previewComponent.path = sourcePath + '.' + sourceSlot; + } + + onConnectionRemoved: + { + previewComponent.path = ''; + } + + function configureComponents(stageItem) + { + previewComponent = stageItem.addComponent(newPreview, {}); + } + } + + property Component newPreview : PreviewItem + { + } +} diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index db0e32d4..2325460b 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -468,6 +468,11 @@ ApplicationWindow } } + PreviewStage + { + id: previewStage + } + Settings { id: settings @@ -499,6 +504,11 @@ ApplicationWindow gloperate.components.setPluginPaths(settings.pluginPaths); gloperate.components.scanPlugins(); } + + onEditorChanged: + { + gloperatePipeline.editor = settings.editor; + } } Component.onCompleted: @@ -515,6 +525,10 @@ ApplicationWindow // Scan for plugins gloperate.components.scanPlugins(); + // Add preview stage + gloperatePipeline.clearInternalStages(); + gloperatePipeline.addInternalStage(previewStage.stageDefinition); + // Set render stage window.stage = settings.stage; propertyEditor.update(); diff --git a/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp b/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp index 5b5de113..9eb18028 100644 --- a/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp +++ b/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp @@ -62,7 +62,15 @@ void TextureItemRenderer::renderTexture() Canvas * canvas = m_environment->canvases().front(); Stage * stage = canvas->renderStage(); if (!stage) return; - AbstractSlot * slot = stage->getSlot(m_path.toStdString()); + + std::string slotPath = m_path.toStdString(); + + // Replace root in slot path with render stage name + if (string::hasPrefix(slotPath, "root")) { + slotPath.replace(0, 4, stage->name()); + } + + AbstractSlot * slot = stage->getSlot(slotPath); if (!slot) return; // Check if it is a texture slot From 01262e1e4cd40227dbf9a85f79592ac1971290e6 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 24 Aug 2017 15:23:50 +0200 Subject: [PATCH 08/12] fix window becoming stuck if changing internal/external setting while editor is open --- data/gloperate/qml/Viewer.qml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index 2325460b..a643e9e3 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -403,13 +403,11 @@ ApplicationWindow // Hides the pipeline editor function hideEditor() { - if (settings.editor === "internal") - { - mainView.visible = true; - internalPipelineView.visible = false; - } else { - popoutWindow.hide(); - } + // hide internal editor + mainView.visible = true; + internalPipelineView.visible = false; + // hide external editor + popoutWindow.hide(); } // Bottom Panel From c6d77c5ac38b1534ec5cf9456b333678f091a853 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 24 Aug 2017 15:49:38 +0200 Subject: [PATCH 09/12] fix initial editor setting --- data/gloperate/qml/PipelineView.qml | 5 +++++ data/gloperate/qml/Viewer.qml | 1 + 2 files changed, 6 insertions(+) diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index a97da89c..1ebb07af 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -62,6 +62,11 @@ Item function load() { + if (pipelineEditor.loaded) + { + return; + } + pipelineEditor.load(path); configureInternalStages(properties.getInternalStages()); diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index a643e9e3..f5c8d90d 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -526,6 +526,7 @@ ApplicationWindow // Add preview stage gloperatePipeline.clearInternalStages(); gloperatePipeline.addInternalStage(previewStage.stageDefinition); + gloperatePipeline.editor = settings.editor; // Set render stage window.stage = settings.stage; From e4a874e3a3de3f045b1cbf9466dc0b1a756964d2 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Thu, 24 Aug 2017 16:03:05 +0200 Subject: [PATCH 10/12] accept texture from colorrendertarget --- .../source/TextureItemRenderer_ogl.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp b/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp index 9eb18028..5ee3725f 100644 --- a/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp +++ b/source/gloperate-qtquick/source/TextureItemRenderer_ogl.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include #include @@ -15,6 +17,7 @@ #include #include #include +#include #include @@ -79,6 +82,16 @@ void TextureItemRenderer::renderTexture() texture = static_cast< Slot * >(slot)->value(); } + // Check if it is a texture slot + if (slot && slot->type() == typeid(gloperate::ColorRenderTarget *)) + { + gloperate::ColorRenderTarget * renderTarget = static_cast< Slot * >(slot)->value(); + if (renderTarget->currentTargetType() == RenderTargetType::UserDefinedFBOAttachment) + { + texture = renderTarget->framebufferAttachment()->asTextureAttachment()->texture(); + } + } + // Abort if texture is invalid if (!texture) { From ef6fdd5f0a03d63636e24faa79ae27d4d9d9d1a8 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Mon, 28 Aug 2017 14:13:56 +0200 Subject: [PATCH 11/12] fix errors on startup --- data/gloperate/qml/PipelinePage.qml | 10 +++++----- data/gloperate/qml/Viewer.qml | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/data/gloperate/qml/PipelinePage.qml b/data/gloperate/qml/PipelinePage.qml index b827a59c..5c1d8a9d 100644 --- a/data/gloperate/qml/PipelinePage.qml +++ b/data/gloperate/qml/PipelinePage.qml @@ -13,10 +13,10 @@ ScrollArea /// Called when a render stage has been selected signal renderStageSelected(string name) - property var categories: [] ///< List of categories - property var stages: {} ///< List of stages, sorted by categories ( { 'cat1': [ { name: '', description: '', ... } ], 'cat2': [], ...}) - property var currentCategory: 'Demo' ///< The currently selected category - property var currentStage: '' ///< The currently selected stage + property var categories: [] ///< List of categories + property var stages: {} ///< List of stages, sorted by categories ( { 'cat1': [ { name: '', description: '', ... } ], 'cat2': [], ...}) + property var currentCategory: 'Demos' ///< The currently selected category + property var currentStage: '' ///< The currently selected stage contentWidth: layout.width contentHeight: layout.height @@ -66,7 +66,7 @@ ScrollArea Repeater { - model: item.stages[item.currentCategory].length + model: item.stages === undefined ? 0 : item.stages[item.currentCategory].length ClickLabel { diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index f5c8d90d..a4c51e5e 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -459,10 +459,13 @@ ApplicationWindow { propertyEditor.update(); - canvas.onStageInputChanged(function(slot, status) + if (canvas) { - gloperatePipeline.slotChanged('root', slot, status); - }); + canvas.onStageInputChanged(function(slot, status) + { + gloperatePipeline.slotChanged('root', slot, status); + }); + } } } From 816f119fa3134ef6e244d9185a7fc860d7f6dfb8 Mon Sep 17 00:00:00 2001 From: Joseph Bethge Date: Mon, 28 Aug 2017 16:18:39 +0200 Subject: [PATCH 12/12] add creation of internal stages --- data/gloperate/qml/GlOperatePipeline.qml | 55 +++++++++++++++++++++++- data/gloperate/qml/InternalStage.qml | 15 ++++++- data/gloperate/qml/PipelineView.qml | 12 ++++-- data/gloperate/qml/PreviewItem.qml | 6 --- data/gloperate/qml/PreviewStage.qml | 2 +- data/gloperate/qml/Viewer.qml | 12 ++---- 6 files changed, 81 insertions(+), 21 deletions(-) diff --git a/data/gloperate/qml/GlOperatePipeline.qml b/data/gloperate/qml/GlOperatePipeline.qml index 8e32be24..b1501024 100644 --- a/data/gloperate/qml/GlOperatePipeline.qml +++ b/data/gloperate/qml/GlOperatePipeline.qml @@ -15,6 +15,7 @@ Item property var canvas: null ///< Canvas scripting interface (accessed by 'root') property var internalStages: {} ///< Store stages only accessible for scripting and UI + property var internalTypes: null ///< Stores internal stage types, lazy initialize property string editor: '' ///< State of editor function getStageTypes() @@ -33,6 +34,8 @@ Item } } + types = types.concat(Object.keys(getInternalTypes())); + return types; } @@ -46,6 +49,11 @@ Item function createStage(path, name, type) { + if (getInternalTypes().hasOwnProperty(type)) + { + return createInternalStage(path, name, type); + } + if (canvas) { return canvas.createStage(path, name, type); @@ -190,11 +198,21 @@ Item } } + // Functions regarding internal stages function isVisible(stage) { return editor === 'internal' ? stage.isVisibleInternal : stage.isVisibleExternal; } + function getInternalTypes() + { + if (internalTypes === null) + { + initializeInternalTypes(); + } + return internalTypes; + } + function getInternalStages() { var stages = {}; @@ -217,8 +235,43 @@ Item internalStages = {}; } - function addInternalStage(stage) + function createInternalStage(path, name, type) { + var realName = name; + + if (internalStages.hasOwnProperty(path + "." + name)) + { + // name already taken, add a number + var i = 2; + while (internalStages.hasOwnProperty(path + "." + name + i)) + { + i += 1; + } + realName = name + i; + } + + var stageComponent = getInternalTypes()[type]; + + var newStage = stageComponent.createObject(pipelineInterface, {}); + var stage = newStage.stageDefinition; + + stage.name = realName; + stage.path = path + "." + realName; + internalStages[stage.path] = stage; + + return realName; + } + + function initializeInternalTypes() + { + internalTypes = {}; + + internalTypes['PreviewStage'] = previewStageComponent; + } + + property Component previewStageComponent : PreviewStage + { + id: previewStage } } diff --git a/data/gloperate/qml/InternalStage.qml b/data/gloperate/qml/InternalStage.qml index a7d9bed3..cc3aa847 100644 --- a/data/gloperate/qml/InternalStage.qml +++ b/data/gloperate/qml/InternalStage.qml @@ -22,7 +22,20 @@ Item property bool isVisibleInternal: true ///< Whether this stage should be visible in 'internal' mode property bool isVisibleExternal: true ///< Whether this stage should be visible in 'external' mode - function configureComponents(stageItem) {} ///< Configure stage item in pipeline editor + property bool configured: false ///< Whether this stage is already configured + + function onConfigure(stageItem) {} ///< To be overridden with actual configuration + + function configure(stageItem) { + if (configured) + { + return; + } + + onConfigure(stageItem); + + configured = true; + } onConnectionCreated: { diff --git a/data/gloperate/qml/PipelineView.qml b/data/gloperate/qml/PipelineView.qml index 1ebb07af..e944c1ce 100644 --- a/data/gloperate/qml/PipelineView.qml +++ b/data/gloperate/qml/PipelineView.qml @@ -69,24 +69,28 @@ Item pipelineEditor.load(path); - configureInternalStages(properties.getInternalStages()); + configureInternalStages(); + + pipelineEditor.pipeline.stageCreated.connect(configureInternalStages); } function update() { pipelineEditor.update(); - configureInternalStages(properties.getInternalStages()); + configureInternalStages(); } - function configureInternalStages(internalStages) + function configureInternalStages() { + var internalStages = properties.getInternalStages(); + for (var stageName in internalStages) { var stageDefinition = internalStages[stageName]; var stageObject = pipelineEditor.pipeline.stageItems[stageDefinition.name]; - stageDefinition.configureComponents(stageObject); + stageDefinition.configure(stageObject); } } } diff --git a/data/gloperate/qml/PreviewItem.qml b/data/gloperate/qml/PreviewItem.qml index b5551d57..f271586c 100644 --- a/data/gloperate/qml/PreviewItem.qml +++ b/data/gloperate/qml/PreviewItem.qml @@ -32,11 +32,5 @@ Item path: previewItem.path } - - // MouseArea - // { - // anchors.fill: parent - // drag.target: parent - // } } } diff --git a/data/gloperate/qml/PreviewStage.qml b/data/gloperate/qml/PreviewStage.qml index f2289a97..b78a31b8 100644 --- a/data/gloperate/qml/PreviewStage.qml +++ b/data/gloperate/qml/PreviewStage.qml @@ -45,7 +45,7 @@ Item previewComponent.path = ''; } - function configureComponents(stageItem) + function onConfigure(stageItem) { previewComponent = stageItem.addComponent(newPreview, {}); } diff --git a/data/gloperate/qml/Viewer.qml b/data/gloperate/qml/Viewer.qml index a4c51e5e..20edb169 100644 --- a/data/gloperate/qml/Viewer.qml +++ b/data/gloperate/qml/Viewer.qml @@ -455,6 +455,8 @@ ApplicationWindow { id: gloperatePipeline + editor: settings.editor + onCanvasChanged: { propertyEditor.update(); @@ -469,11 +471,6 @@ ApplicationWindow } } - PreviewStage - { - id: previewStage - } - Settings { id: settings @@ -526,10 +523,9 @@ ApplicationWindow // Scan for plugins gloperate.components.scanPlugins(); - // Add preview stage + // Initialize internal stages and add one preview stage gloperatePipeline.clearInternalStages(); - gloperatePipeline.addInternalStage(previewStage.stageDefinition); - gloperatePipeline.editor = settings.editor; + gloperatePipeline.createInternalStage("root", "PreviewStage", "PreviewStage"); // Set render stage window.stage = settings.stage;