mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Merge pull request #7043 from zzmp/fix/render-ui
Revamp the render engine ui
This commit is contained in:
commit
99e9b3ecdd
9 changed files with 247 additions and 229 deletions
66
examples/utilities/tools/render/ConfigSlider.qml
Normal file
66
examples/utilities/tools/render/ConfigSlider.qml
Normal file
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// ConfigSlider.qml
|
||||
// examples/utilities/tools/render
|
||||
//
|
||||
// Created by Zach Pomerantz on 2/8/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 400
|
||||
height: 24
|
||||
property bool integral: false
|
||||
property var config
|
||||
property string property
|
||||
property alias label: labelControl.text
|
||||
property alias min: sliderControl.minimumValue
|
||||
property alias max: sliderControl.maximumValue
|
||||
|
||||
Component.onCompleted: {
|
||||
// Binding favors qml value, so set it first
|
||||
sliderControl.value = root.config[root.property];
|
||||
bindingControl.when = true;
|
||||
}
|
||||
|
||||
Label {
|
||||
id: labelControl
|
||||
text: root.label
|
||||
anchors.left: root.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: root.top
|
||||
anchors.topMargin: 7
|
||||
}
|
||||
|
||||
Label {
|
||||
text: sliderControl.value.toFixed(root.integral ? 0 : 2)
|
||||
anchors.left: root.left
|
||||
anchors.leftMargin: 140
|
||||
anchors.top: root.top
|
||||
anchors.topMargin: 7
|
||||
}
|
||||
|
||||
Binding {
|
||||
id: bindingControl
|
||||
target: root.config
|
||||
property: root.property
|
||||
value: sliderControl.value
|
||||
when: false
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: sliderControl
|
||||
stepSize: root.integral ? 1.0 : 0.0
|
||||
width: 192
|
||||
height: 20
|
||||
anchors.right: root.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.top: root.top
|
||||
anchors.topMargin: 3
|
||||
}
|
||||
}
|
42
examples/utilities/tools/render/debug.js
Normal file
42
examples/utilities/tools/render/debug.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// debug.js
|
||||
// examples/utilities/tools/render
|
||||
//
|
||||
// Zach Pomerantz, created on 1/27/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
oldConfig = Render.toJSON();
|
||||
Render.RenderShadowTask.enabled = true;
|
||||
var RDT = Render.RenderDeferredTask;
|
||||
RDT.AmbientOcclusion.enabled = true;
|
||||
RDT.DebugDeferredBuffer.enabled = false;
|
||||
["DrawOpaqueDeferred", "DrawTransparentDeferred", "DrawOverlay3DOpaque", "DrawOverlay3DTransparent"]
|
||||
.map(function(name) { return RDT[name]; })
|
||||
.forEach(function(job) { job.maxDrawn = job.numDrawn; });
|
||||
|
||||
// Set up the qml ui
|
||||
var qml = Script.resolvePath('main.qml');
|
||||
var window = new OverlayWindow({
|
||||
title: 'Render Engine Configuration',
|
||||
source: qml,
|
||||
width: 400, height: 900,
|
||||
});
|
||||
window.setPosition(25, 50);
|
||||
window.closed.connect(function() { Script.stop(); });
|
||||
|
||||
// Debug buffer sizing
|
||||
var resizing = false;
|
||||
Controller.mousePressEvent.connect(function() { resizing = true; });
|
||||
Controller.mouseReleaseEvent.connect(function() { resizing = false; });
|
||||
Controller.mouseMoveEvent.connect(function(e) { resizing && setDebugBufferSize(e.x); });
|
||||
function setDebugBufferSize(x) {
|
||||
x = (2.0 * (x / Window.innerWidth) - 1.0); // scale
|
||||
x = Math.min(Math.max(-1, x), 1); // clamp
|
||||
Render.RenderDeferredTask.DebugDeferredBuffer.size = {x: x, y: -1, z: 1, w: 1};
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(function() { Render.fromJSON(oldConfig); } );
|
110
examples/utilities/tools/render/main.qml
Normal file
110
examples/utilities/tools/render/main.qml
Normal file
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// main.qml
|
||||
// examples/utilities/tools/render
|
||||
//
|
||||
// Created by Zach Pomerantz on 2/8/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
model: [ "Opaque:DrawOpaqueDeferred", "Transparent:DrawTransparentDeferred",
|
||||
"Opaque Overlays:DrawOverlay3DOpaque", "Transparent Overlays:DrawOverlay3DTransparent" ]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
integral: true
|
||||
config: Render.getConfig(modelData.split(":")[1])
|
||||
property: "maxDrawn"
|
||||
max: config.numDrawn
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
CheckBox {
|
||||
text: qsTr("Display Status")
|
||||
onCheckedChanged: { Render.getConfig("DrawStatus").showDisplay = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: qsTr("Network/Physics Status")
|
||||
onCheckedChanged: { Render.getConfig("DrawStatus").showNetwork = checked }
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSlider {
|
||||
label: qsTr("Tone Mapping Exposure")
|
||||
config: Render.getConfig("ToneMapping")
|
||||
property: "exposure"
|
||||
min: -10; max: 10
|
||||
}
|
||||
|
||||
Column {
|
||||
id: ambientOcclusion
|
||||
property var config: Render.getConfig("AmbientOcclusion")
|
||||
|
||||
Label { text: qsTr("Ambient Occlusion") }
|
||||
// TODO: Add gpuTimer
|
||||
CheckBox { text: qsTr("Dithering"); checked: ambientOcclusion.config.ditheringEnabled }
|
||||
Repeater {
|
||||
model: [
|
||||
"Resolution Level:resolutionLevel:4",
|
||||
"Obscurance Level:obscuranceLevel:1",
|
||||
"Radius:radius:2",
|
||||
"Falloff Bias:falloffBias:0.2",
|
||||
"Edge Sharpness:edgeSharpness:1",
|
||||
"Blur Radius:blurRadius:6",
|
||||
"Blur Deviation:blurDeviation:3"
|
||||
]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
config: ambientOcclusion.config
|
||||
property: modelData.split(":")[1]
|
||||
max: modelData.split(":")[2]
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
model: [
|
||||
"Samples:numSamples:32",
|
||||
"Spiral Turns:numSpiralTurns:30:"
|
||||
]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
integral: true
|
||||
config: ambientOcclusion.config
|
||||
property: modelData.split(":")[1]
|
||||
max: modelData.split(":")[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: debug
|
||||
property var config: Render.getConfig("DebugDeferredBuffer")
|
||||
|
||||
function setDebugMode(mode) {
|
||||
debug.config.enabled = (mode != 0);
|
||||
debug.config.mode = mode;
|
||||
}
|
||||
|
||||
Label { text: qsTr("Debug Buffer") }
|
||||
ExclusiveGroup { id: bufferGroup }
|
||||
Repeater {
|
||||
model: [
|
||||
"Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth",
|
||||
"Lighting", "Shadow", "Pyramid Depth", "Ambient Occlusion", "Custom Shader"
|
||||
]
|
||||
RadioButton {
|
||||
text: qsTr(modelData)
|
||||
exclusiveGroup: bufferGroup
|
||||
checked: index == 0
|
||||
onCheckedChanged: if (checked) debug.setDebugMode(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,216 +0,0 @@
|
|||
//
|
||||
// renderEngineDebug.js
|
||||
// examples/utilities/tools
|
||||
//
|
||||
// Sam Gateau
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("cookies.js");
|
||||
|
||||
var MENU = "Developer>Render>Debug Deferred Buffer";
|
||||
var ACTIONS = ["Off", "Diffuse", "Metallic", "Roughness", "Normal", "Depth", "Lighting", "Shadow", "PyramidDepth", "AmbientOcclusion", "OcclusionBlurred", "Custom"];
|
||||
var SETTINGS_KEY = "EngineDebugScript.DebugMode";
|
||||
|
||||
Number.prototype.clamp = function(min, max) {
|
||||
return Math.min(Math.max(this, min), max);
|
||||
};
|
||||
|
||||
var panel = new Panel(10, 100);
|
||||
|
||||
function CounterWidget(parentPanel, name, counter) {
|
||||
var subPanel = parentPanel.newSubPanel(name);
|
||||
var widget = parentPanel.items[name];
|
||||
widget.editTitle({ width: 270 });
|
||||
|
||||
subPanel.newSlider('Max Drawn', -1, 1,
|
||||
function(value) { counter.maxDrawn = value; }, // setter
|
||||
function() { return counter.maxDrawn; }, // getter
|
||||
function(value) { return value; });
|
||||
|
||||
var slider = subPanel.getWidget('Max Drawn');
|
||||
|
||||
this.update = function () {
|
||||
var numDrawn = counter.numDrawn; // avoid double polling
|
||||
var numMax = Math.max(numDrawn, 1);
|
||||
var title = [
|
||||
' ' + name,
|
||||
numDrawn + ' / ' + counter.numFeed
|
||||
].join('\t');
|
||||
|
||||
widget.editTitle({ text: title });
|
||||
slider.setMaxValue(numMax);
|
||||
};
|
||||
};
|
||||
|
||||
var opaquesCounter = new CounterWidget(panel, "Opaques", Render.opaque);
|
||||
var transparentsCounter = new CounterWidget(panel, "Transparents", Render.transparent);
|
||||
var overlaysCounter = new CounterWidget(panel, "Overlays", Render.overlay3D);
|
||||
|
||||
var resizing = false;
|
||||
var previousMode = Settings.getValue(SETTINGS_KEY, -1);
|
||||
previousMode = 8;
|
||||
Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]);
|
||||
Render.deferredDebugMode = previousMode;
|
||||
Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; // Reset to default size
|
||||
|
||||
function setEngineDeferredDebugSize(eventX) {
|
||||
var scaledX = (2.0 * (eventX / Window.innerWidth) - 1.0).clamp(-1.0, 1.0);
|
||||
Render.deferredDebugSize = { x: scaledX, y: -1.0, z: 1.0, w: 1.0 };
|
||||
}
|
||||
function shouldStartResizing(eventX) {
|
||||
var x = Math.abs(eventX - Window.innerWidth * (1.0 + Render.deferredDebugSize.x) / 2.0);
|
||||
var mode = Render.deferredDebugMode;
|
||||
return mode !== -1 && x < 20;
|
||||
}
|
||||
|
||||
function menuItemEvent(menuItem) {
|
||||
var index = ACTIONS.indexOf(menuItem);
|
||||
if (index >= 0) {
|
||||
Render.deferredDebugMode = (index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// see libraries/render/src/render/Engine.h
|
||||
var showDisplayStatusFlag = 1;
|
||||
var showNetworkStatusFlag = 2;
|
||||
|
||||
panel.newCheckbox("Display status",
|
||||
function(value) { Render.displayItemStatus = (value ?
|
||||
Render.displayItemStatus | showDisplayStatusFlag :
|
||||
Render.displayItemStatus & ~showDisplayStatusFlag); },
|
||||
function() { return (Render.displayItemStatus & showDisplayStatusFlag) > 0; },
|
||||
function(value) { return (value & showDisplayStatusFlag) > 0; }
|
||||
);
|
||||
|
||||
panel.newCheckbox("Network/Physics status",
|
||||
function(value) { Render.displayItemStatus = (value ?
|
||||
Render.displayItemStatus | showNetworkStatusFlag :
|
||||
Render.displayItemStatus & ~showNetworkStatusFlag); },
|
||||
function() { return (Render.displayItemStatus & showNetworkStatusFlag) > 0; },
|
||||
function(value) { return (value & showNetworkStatusFlag) > 0; }
|
||||
);
|
||||
|
||||
panel.newSlider("Tone Mapping Exposure", -10, 10,
|
||||
function (value) { Render.tone.exposure = value; },
|
||||
function() { return Render.tone.exposure; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Resolution Level", 0.0, 4.0,
|
||||
function (value) { Render.ambientOcclusion.resolutionLevel = value; },
|
||||
function() { return Render.ambientOcclusion.resolutionLevel; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Radius", 0.0, 2.0,
|
||||
function (value) { Render.ambientOcclusion.radius = value; },
|
||||
function() { return Render.ambientOcclusion.radius; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Level", 0.0, 1.0,
|
||||
function (value) { Render.ambientOcclusion.level = value; },
|
||||
function() { return Render.ambientOcclusion.level; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Num Samples", 1, 32,
|
||||
function (value) { Render.ambientOcclusion.numSamples = value; },
|
||||
function() { return Render.ambientOcclusion.numSamples; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Num Spiral Turns", 0.0, 30.0,
|
||||
function (value) { Render.ambientOcclusion.numSpiralTurns = value; },
|
||||
function() { return Render.ambientOcclusion.numSpiralTurns; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
panel.newCheckbox("Ambient Occlusion Dithering",
|
||||
function (value) { Render.ambientOcclusion.ditheringEnabled = value; },
|
||||
function() { return Render.ambientOcclusion.ditheringEnabled; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Falloff Bias", 0.0, 0.2,
|
||||
function (value) { Render.ambientOcclusion.falloffBias = value; },
|
||||
function() { return Render.ambientOcclusion.falloffBias; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Edge Sharpness", 0.0, 1.0,
|
||||
function (value) { Render.ambientOcclusion.edgeSharpness = value; },
|
||||
function() { return Render.ambientOcclusion.edgeSharpness; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Blur Radius", 0.0, 6.0,
|
||||
function (value) { Render.ambientOcclusion.blurRadius = value; },
|
||||
function() { return Render.ambientOcclusion.blurRadius; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Blur Deviation", 0.0, 3.0,
|
||||
function (value) { Render.ambientOcclusion.blurDeviation = value; },
|
||||
function() { return Render.ambientOcclusion.blurDeviation; },
|
||||
function (value) { return (value.toFixed(2)); });
|
||||
|
||||
|
||||
panel.newSlider("Ambient Occlusion GPU time", 0.0, 10.0,
|
||||
function (value) {},
|
||||
function() { return Render.ambientOcclusion.gpuTime; },
|
||||
function (value) { return (value.toFixed(2) + " ms"); });
|
||||
|
||||
|
||||
var tickTackPeriod = 500;
|
||||
|
||||
function updateCounters() {
|
||||
opaquesCounter.update();
|
||||
transparentsCounter.update();
|
||||
overlaysCounter.update();
|
||||
panel.update("Ambient Occlusion GPU time");
|
||||
}
|
||||
Script.setInterval(updateCounters, tickTackPeriod);
|
||||
|
||||
function mouseMoveEvent(event) {
|
||||
if (resizing) {
|
||||
setEngineDeferredDebugSize(event.x);
|
||||
} else {
|
||||
panel.mouseMoveEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function mousePressEvent(event) {
|
||||
if (shouldStartResizing(event.x)) {
|
||||
resizing = true;
|
||||
} else {
|
||||
panel.mousePressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
if (resizing) {
|
||||
resizing = false;
|
||||
} else {
|
||||
panel.mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
|
||||
Menu.menuItemEvent.connect(menuItemEvent);
|
||||
|
||||
function scriptEnding() {
|
||||
panel.destroy();
|
||||
Menu.removeActionGroup(MENU);
|
||||
// Reset
|
||||
Settings.setValue(SETTINGS_KEY, Render.deferredDebugMode);
|
||||
Render.deferredDebugMode = -1;
|
||||
Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 };
|
||||
Render.opaque.maxDrawn = -1;
|
||||
Render.transparent.maxDrawn = -1;
|
||||
Render.overlay3D.maxDrawn = -1;
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
||||
|
||||
|
||||
// Collapse items
|
||||
panel.mousePressEvent({ x: panel.x, y: panel.items["Overlays"].y});
|
||||
panel.mousePressEvent({ x: panel.x, y: panel.items["Transparents"].y});
|
||||
panel.mousePressEvent({ x: panel.x, y: panel.items["Opaques"].y});
|
|
@ -27,7 +27,7 @@ public:
|
|||
void setMode(int newMode);
|
||||
|
||||
int mode{ 0 };
|
||||
glm::vec4 size{ 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
glm::vec4 size{ 0.0f, -1.0f, 1.0f, 1.0f };
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
|
|
@ -142,7 +142,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
batch.setStateScissorRect(args->_viewport);
|
||||
args->_batch = &batch;
|
||||
|
||||
config->numDrawn = (int)inItems.size();
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
emit config->numDrawnChanged();
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
|
@ -179,7 +180,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
|||
inItems.emplace_back(id);
|
||||
}
|
||||
}
|
||||
config->numItems = (int)inItems.size();
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
emit config->numDrawnChanged();
|
||||
|
||||
if (!inItems.empty()) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
|
|
@ -40,15 +40,20 @@ public:
|
|||
|
||||
class DrawConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn)
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
public:
|
||||
int getNumDrawn() { return numDrawn; }
|
||||
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
|
||||
|
||||
int numDrawn{ 0 };
|
||||
int maxDrawn{ -1 };
|
||||
|
||||
signals:
|
||||
void numDrawnChanged();
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
int numDrawn{ 0 };
|
||||
};
|
||||
|
||||
class DrawDeferred {
|
||||
|
@ -86,15 +91,20 @@ public:
|
|||
|
||||
class DrawOverlay3DConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numItems READ getNumItems)
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
public:
|
||||
int getNumItems() { return numItems; }
|
||||
int getNumDrawn() { return numDrawn; }
|
||||
void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); }
|
||||
|
||||
int numItems{ 0 };
|
||||
int maxDrawn{ -1 };
|
||||
|
||||
signals:
|
||||
void numDrawnChanged();
|
||||
void dirty();
|
||||
|
||||
protected:
|
||||
int numDrawn{ 0 };
|
||||
};
|
||||
|
||||
class DrawOverlay3D {
|
||||
|
|
|
@ -71,10 +71,12 @@ public:
|
|||
bool alwaysEnabled{ true };
|
||||
bool enabled{ true };
|
||||
|
||||
// This must be named toJSON to integrate with the global scripting JSON object
|
||||
Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); }
|
||||
Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); }
|
||||
|
||||
public slots:
|
||||
void load(const QJsonValue& json) { qObjectFromJsonValue(json, *this); }
|
||||
void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); }
|
||||
};
|
||||
|
||||
class TaskConfig : public JobConfig {
|
||||
|
@ -85,6 +87,9 @@ public:
|
|||
|
||||
void init(Task* task) { _task = task; }
|
||||
|
||||
// getter for qml integration, prefer the templated getter
|
||||
Q_INVOKABLE QObject* getConfig(const QString& name) { return QObject::findChild<JobConfig*>(name); }
|
||||
// getter for cpp (strictly typed), prefer this getter
|
||||
template <class T> typename T::Config* getConfig(std::string job = "") const {
|
||||
QString name = job.empty() ? QString() : QString(job.c_str()); // an empty string is not a null string
|
||||
return findChild<typename T::Config*>(name);
|
||||
|
|
|
@ -111,10 +111,9 @@ void qObjectFromJsonValue(const QJsonValue& j, QObject& o) {
|
|||
for (auto it = object.begin(); it != object.end(); it++) {
|
||||
std::string key = it.key().toStdString();
|
||||
if (it.value().isObject()) {
|
||||
QVariant child = o.property(key.c_str());
|
||||
if (child.isValid()) {
|
||||
QObject* object = child.value<QObject*>();
|
||||
qObjectFromJsonValue(it.value(), *object);
|
||||
QObject* child = o.findChild<QObject*>(key.c_str(), Qt::FindChildOption::FindDirectChildrenOnly);
|
||||
if (child) {
|
||||
qObjectFromJsonValue(it.value(), *child);
|
||||
}
|
||||
} else {
|
||||
o.setProperty(key.c_str(), it.value());
|
||||
|
|
Loading…
Reference in a new issue