Revision control

Copy as Markdown

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtQuick3D.MaterialEditor
Pane {
id: uniformManagerPane
property alias uniformModel: uniformModel
required property MaterialAdapter materialAdapter
SplitView {
anchors.fill: parent
ColumnLayout {
clip: true
RowLayout {
id: tableControls
function insertUniform() {
let rowCount = uniformManagerPane.materialAdapter.uniformModel.rowCount;
if (uniformManagerPane.materialAdapter.uniformModel.insertRow(rowCount, typeComboBox.currentIndex, uniformNameTextInput.text))
uniformNameTextInput.text = ""
}
Label {
text: "Type:"
}
ComboBox {
id: typeComboBox
textRole: "text"
valueRole: "value"
model: [
{ value: UniformModel.Bool, text: "bool" },
{ value: UniformModel.Int, text: "int" },
{ value: UniformModel.Float, text: "float" },
{ value: UniformModel.Vec2, text: "vec2" },
{ value: UniformModel.Vec3, text: "vec3" },
{ value: UniformModel.Vec4, text: "vec4" },
{ value: UniformModel.Mat44, text: "mat44" },
{ value: UniformModel.Sampler, text: "sampler" }
]
}
TextField {
id: uniformNameTextInput
validator: RegularExpressionValidator {
regularExpression: /[a-zA-Z_][a-zA-Z0-9_]+/
}
Layout.fillWidth: true
placeholderText: "Uniform Name"
onAccepted: tableControls.insertUniform()
}
Button {
id: addButton
text: "Add"
enabled: uniformNameTextInput.text != ""
onClicked: tableControls.insertUniform()
}
}
// Column Header
Row {
id: columnsHeader
Layout.fillWidth: true
Label {
width: uniformTable.columnWidth(0)
text: "Type"
verticalAlignment: Text.AlignVCenter
}
Label {
width: uniformTable.columnWidth(1)
text: "Name"
verticalAlignment: Text.AlignVCenter
}
Label {
width: uniformTable.columnWidth(2)
text: "Value"
verticalAlignment: Text.AlignVCenter
}
}
ListView {
id: uniformTable
Layout.fillHeight: true
Layout.fillWidth: true
flickableDirection: Flickable.VerticalFlick
model: UniformModel {
id: uniformModel
}
clip: true
ScrollBar.vertical: ScrollBar { }
highlight: Rectangle {
color: palette.highlight
}
property var typeStrings: [
"bool",
"int",
"float",
"vec2",
"vec3",
"vec4",
"mat44",
"sampler"
]
function convertValueToString(value, type)
{
if (type === 0) {
// bool
return String(value);
} if (type === 1) {
// int
return String(value);
} if (type === 2) {
// float
return String(value);
} if (type === 3) {
// vec2
return "(" + value.x + ", " + value.y + ")"
} if (type === 4) {
// vec3
return "(" + value.x + ", " + value.y + ", " + value.z + ")"
} if (type === 5) {
// vec4
return "(" + value.x + ", " + value.y + ", " + value.z + ", " + value.w + ")"
} if (type === 6) {
// mat44
return value.toString()
} if (type === 7) {
// sampler
return "[Texture]"
}
}
function columnWidth(column) {
if (column === 0)
return 50;
if (column === 1)
return 100;
return 100;
}
delegate: Item {
id: delegateRoot
required property int type
required property string name
required property var value
required property int index
width: ListView.view.width
height: typeLabel.implicitHeight
Row {
Label {
id: typeLabel
width: uniformTable.columnWidth(0)
text: uniformTable.typeStrings[delegateRoot.type]
}
Label {
width: uniformTable.columnWidth(1)
text: delegateRoot.name
}
Label {
width: uniformTable.columnWidth(2)
Layout.fillWidth: true
text: uniformTable.convertValueToString(delegateRoot.value, delegateRoot.type)
}
}
MouseArea {
anchors.fill: parent
onClicked: {
uniformTable.currentIndex = delegateRoot.index
}
}
}
}
}
Item {
id: uniformValueEditor
width: parent.width * 0.5
clip: true
Label {
id: emptyLabel
visible: uniformTable.currentIndex == -1
anchors.centerIn: parent
text: "Select a uniform to edit"
}
Repeater {
id: delegateRepeater
anchors.fill: parent
model: uniformModel
Item {
id: editorRoot
required property int index
required property int type
required property string name
required property var model
anchors.fill: parent
anchors.margins: 10
visible: index === uniformTable.currentIndex
Item {
id: header
width: parent.width
anchors.top: parent.top
height: removeButton.implicitHeight
RowLayout {
anchors.fill: parent
id: headerLayout
Label {
text: "Uniform: " + editorRoot.name
Layout.fillWidth: true
elide: Text.ElideRight
}
Button {
id: removeButton
text: "Remove"
Layout.alignment: Qt.AlignRight
onClicked: {
uniformManagerPane.materialAdapter.uniformModel.removeRow(uniformTable.currentIndex, 1)
}
}
}
}
Loader {
id: editorLoader
anchors.top: header.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
sourceComponent: editors[editorRoot.type]
readonly property list<Component> editors: [
boolEditor,
intEditor,
floatEditor,
vec2Editor,
vec3Editor,
vec4Editor,
mat44Editor,
samplerEditor
]
Component {
id: boolEditor
CheckBox {
text: "value"
checked: editorRoot.model.value
onCheckedChanged: editorRoot.model.value = checked
}
}
Component {
id: intEditor
TextField {
text: editorRoot.model.value
validator: IntValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = parseInt(text)
}
}
}
Component {
id: floatEditor
ColumnLayout {
TextField {
Layout.fillWidth: true
text: editorRoot.model.value
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput) {
var floatValue = parseFloat(text);
floatSlider.updateMinMax(floatValue);
editorRoot.value = floatValue;
}
}
}
Slider {
id: floatSlider
// Grow slider min & max based on given values
function updateMinMax(newValue) {
if (from > newValue)
from = newValue;
if (to < newValue)
to = newValue;
value = newValue;
}
from: 0.0
to: 1.0
onValueChanged: {
editorRoot.model.value = value;
}
Component.onCompleted: {
updateMinMax(editorRoot.model.value);
}
}
}
}
Component {
id: vec2Editor
ColumnLayout {
RowLayout {
Label {
text: "X:"
}
TextField {
id: xField
text: editorRoot.model.value.x
validator: DoubleValidator {
locale: "C"
}
onEditingFinished: {
if (acceptableInput)
editorRoot.model.value = Qt.vector2d(parseFloat(text), editorRoot.model.value.y)
}
}
}
RowLayout {
Label {
text: "Y:"
}
TextField {
id: yField
text: editorRoot.model.value.y
validator: DoubleValidator {
locale: "C"
}
onEditingFinished: {
if (acceptableInput)
editorRoot.model.value = Qt.vector2d(editorRoot.model.value.x, parseFloat(text))
}
}
}
}
}
Component {
id: vec3Editor
ColumnLayout {
RowLayout {
Label {
text: "X:"
}
TextField {
id: xField
text: editorRoot.model.value.x
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector3d(parseFloat(text), editorRoot.model.value.y, editorRoot.model.value.z)
}
}
}
RowLayout {
Label {
text: "Y:"
}
TextField {
id: yField
text: editorRoot.model.value.y
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector3d(editorRoot.model.value.x, parseFloat(text), editorRoot.model.value.z)
}
}
}
RowLayout {
Label {
text: "Z:"
}
TextField {
id: zField
text: editorRoot.model.value.z
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector3d(editorRoot.model.value.x, editorRoot.model.value.y, parseFloat(text))
}
}
}
}
}
Component {
id: vec4Editor
ColumnLayout {
RowLayout {
Label {
text: "X:"
}
TextField {
id: xField
text: editorRoot.model.value.x
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector4d(parseFloat(text), editorRoot.model.value.y, editorRoot.model.value.z, editorRoot.model.value.w)
}
}
}
RowLayout {
Label {
text: "Y:"
}
TextField {
id: yField
text: editorRoot.model.value.y
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector4d(editorRoot.model.value.x, parseFloat(text), editorRoot.model.value.z, editorRoot.model.value.w)
}
}
}
RowLayout {
Label {
text: "Z:"
}
TextField {
id: zField
text: editorRoot.model.value.z
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector4d(editorRoot.model.value.x, editorRoot.model.value.y, parseFloat(text), editorRoot.model.value.w)
}
}
}
RowLayout {
Label {
text: "W:"
}
TextField {
id: wField
text: editorRoot.model.value.w
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.vector4d(editorRoot.model.value.x, editorRoot.model.value.y, editorRoot.model.value.z, parseFloat(text))
}
}
}
}
}
Component {
id: mat44Editor
ColumnLayout {
RowLayout {
TextField {
text: editorRoot.model.value.m11
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(parseFloat(text), editorRoot.model.value.m12, editorRoot.model.value.m13 , editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m12
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, parseFloat(text), editorRoot.model.value.m13 , editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m13
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, parseFloat(text), editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m14
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, parseFloat(text),
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
}
RowLayout {
TextField {
text: editorRoot.model.value.m21
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
parseFloat(text), editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m22
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, parseFloat(text), editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m23
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, parseFloat(text), editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m24
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, parseFloat(text),
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
}
RowLayout {
TextField {
text: editorRoot.model.value.m31
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
parseFloat(text), editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m32
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, parseFloat(text), editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m33
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, parseFloat(text), editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m34
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, parseFloat(text),
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
}
RowLayout {
TextField {
text: editorRoot.model.value.m41
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
parseFloat(text), editorRoot.model.value.m42, editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m42
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, parseFloat(text), editorRoot.model.value.m43, editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m43
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, parseFloat(text), editorRoot.model.value.m44)
}
}
TextField {
text: editorRoot.model.value.m44
validator: DoubleValidator {
locale: "C"
}
onEditingFinished:{
if (acceptableInput)
editorRoot.model.value = Qt.matrix4x4(editorRoot.model.value.m11, editorRoot.model.value.m12, editorRoot.model.value.m13, editorRoot.model.value.m14,
editorRoot.model.value.m21, editorRoot.model.value.m22, editorRoot.model.value.m23, editorRoot.model.value.m24,
editorRoot.model.value.m31, editorRoot.model.value.m32, editorRoot.model.value.m33, editorRoot.model.value.m34,
editorRoot.model.value.m41, editorRoot.model.value.m42, editorRoot.model.value.m43, parseFloat(text))
}
}
}
}
}
Component {
id: samplerEditor
ColumnLayout {
Image {
id: previewImage
sourceSize.width: 128
sourceSize.height: 128
fillMode: Image.PreserveAspectFit
}
Button {
text: "Choose Image"
onClicked: {
textureSourceDialog.open()
}
}
FileDialog {
id: textureSourceDialog
title: "Open an Image File"
nameFilters: [ uniformManagerPane.materialAdapter.getSupportedImageFormatsFilter()]
onAccepted: {
if (textureSourceDialog.selectedFile !== null) {
editorRoot.model.value = textureSourceDialog.selectedFile
previewImage.source = textureSourceDialog.selectedFile
}
}
}
}
}
}
}
}
}
}
}