Files
RedBear-OS/recipes/wip/qt/qtquick3d/source/examples/quick3d/principledmaterial/TextureSourceControl.qml
T
vasilito ff4ff35918 feat: track all source trees in git — full fork offline-first model
Red Bear OS is a full fork. All sources must be available from git clone
with zero network access. Removed gitignore rules that excluded fetched
source trees under recipes/*/source/, local/recipes/kde/*/source/,
local/recipes/qt/*/source/, and vendor source trees.

Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded.

127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt
frameworks, mesa, wayland, DRM drivers, and every other recipe source.
2026-05-14 10:55:53 +01:00

370 lines
12 KiB
QML

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D
import QtQuick.Dialogs
import Example
RowLayout {
id: root
property Texture targetTexture: null
property bool stampMode: false
required property url defaultTexture
property url stampSource: ""
property alias defaultClearColor: drawer.clearColor
property bool envMapMode: false
GroupBox {
title: "Image Source Mode"
ColumnLayout {
RadioButton {
id: noTextureChoice
text: "None"
checked: true
onCheckedChanged: {
root.targetTexture = null
}
}
RadioButton {
id: selectTextureChoice
text: "Texture"
checked: false
onCheckedChanged: root.targetTexture = selectedTexture
}
RadioButton {
id: loadImageChoice
text: "Load Image"
onCheckedChanged: root.targetTexture = loadTextureTexture
}
RadioButton {
id: drawerChoice
text: "Draw Texture"
onCheckedChanged: root.targetTexture = drawerTexture
}
Label {
visible: uvScale.visible
Layout.fillWidth: true
text: "UV Scale (" + uvScale.value.toFixed(2) + ")"
}
Slider {
id: uvScale
visible: !noTextureChoice.checked
from: 0.0
to: 50.0
value: 1.0
onValueChanged: {
updateUVScale()
}
function updateUVScale(){
if ( root.targetTexture ) {
root.targetTexture.scaleU = value
root.targetTexture.scaleV = value
}
}
Connections {
target: root
function onTargetTextureChanged(targetTexture){
uvScale.updateUVScale()
}
}
}
}
}
Item {
visible: selectTextureChoice.checked
implicitWidth: 256
implicitHeight: 256
Image {
id: previewImage
anchors.fill: parent
sourceSize.width: width
sourceSize.height: height
fillMode: Image.PreserveAspectFit
source: root.defaultTexture
Texture {
id: selectedTexture
source: root.defaultTexture
mappingMode: root.envMapMode ? Texture.Environment : Texture.UV
}
}
}
Rectangle {
id: loadTextureFrame
implicitWidth: 256
implicitHeight: 256
color: "transparent"
border.color: "black"
visible: loadImageChoice.checked
property url textureSource: ""
Text {
anchors.centerIn: parent
text: "[Load Image]"
}
Image {
anchors.fill: parent
sourceSize.width: width
sourceSize.height: height
fillMode: Image.PreserveAspectFit
visible: loadTextureFrame.textureSource !== null
source: loadTextureFrame.textureSource
}
MouseArea {
anchors.fill: parent
onClicked: {
textureSourceDialog.open()
}
}
Texture {
id: loadTextureTexture
source: loadTextureFrame.textureSource
mappingMode: root.envMapMode ? Texture.Environment : Texture.UV
}
ImageHelper {
id: imageHelper
}
FileDialog {
id: textureSourceDialog
title: "Open an Image File"
nameFilters: [ imageHelper.getSupportedImageFormatsFilter()]
onAccepted: {
if (textureSourceDialog.selectedFile !== null) {
loadTextureFrame.textureSource = textureSourceDialog.selectedFile
}
}
}
}
ColumnLayout {
visible: drawerChoice.checked
Rectangle {
implicitWidth: 260
implicitHeight: 260
color: "transparent"
border.color: "black"
Canvas {
id: drawer
width: 256
height: 256
x: 2
y: 2
property color penColor: "blue"
property real penWidth: penWidthSlider.value
property bool needsClear: true
property color clearColor: "white"
property var commands: []
property var stampCommands: []
property bool stampMode: root.stampMode
//property point prevPoint : Qt.point(0, 0)
onPaint: {
let ctx = getContext('2d');
if (needsClear) {
ctx.fillStyle = Qt.rgba(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
ctx.fillRect(0, 0, width, height)
needsClear = false;
}
if (!stampMode) {
ctx.strokeStyle = Qt.rgba(penColor.r, penColor.g, penColor.b, penColor.a)
ctx.lineCap = "round"
ctx.lineWidth = penWidth;
for (let i = 0; i < commands.length; ++i) {
let command = commands[i];
ctx.beginPath()
ctx.moveTo(command.start.x, command.start.y);
ctx.lineTo(command.end.x, command.end.y);
ctx.stroke();
}
commands = [];
} else {
for (let i = 0; i < stampCommands.length; ++i) {
let stampCommand = stampCommands[i]
// get offset
let dX = stampCommand.x - stampcursor.width * 0.5
let dY = stampCommand.y - stampcursor.height * 0.5
ctx.drawImage(stampcursor, dX, dY)
}
stampCommands = [];
}
}
}
MouseArea {
id: mouseArea
anchors.fill: drawer
enabled: drawerChoice.checked
hoverEnabled: true
//acceptedButtons: Qt.LeftButton
property bool isDrawing: false
property var lastPosition: Qt.point(0, 0)
preventStealing: true
clip: true
Item {
id: cursor
Rectangle {
anchors.centerIn: parent
visible: !root.stampMode
width: drawer.penWidth
height: drawer.penWidth
radius: width * 0.5
color: drawer.penColor
}
Image {
id: stampcursor
anchors.centerIn: parent
visible: root.stampMode
source: root.stampSource
}
}
onEntered: cursor.visible = true
onExited: cursor.visible = false
onPressed: (mouse)=> {
if (mouse.button === Qt.LeftButton && !root.stampMode) {
lastPosition = Qt.point(mouse.x, mouse.y)
isDrawing = true
}
}
onPositionChanged: (mouse)=> {
if (isDrawing) {
let pos = Qt.point(mouse.x, mouse.y);
let command = {"start": lastPosition, "end": pos}
drawer.commands.push(command)
lastPosition = pos;
drawer.requestPaint();
}
cursor.x = mouse.x
cursor.y = mouse.y
}
onReleased: (mouse)=> {
if (mouse.button === Qt.LeftButton && isDrawing) {
let pos = Qt.point(mouse.x, mouse.y);
let command = {"start": lastPosition, "end": pos}
drawer.commands.push(command)
isDrawing = false;
drawer.requestPaint();
} else if (root.stampMode) {
drawer.stampCommands.push(Qt.point(mouse.x, mouse.y));
drawer.requestPaint();
}
}
}
}
RowLayout {
visible: !root.stampMode
spacing: 0
Rectangle {
id: whiteBrush
implicitWidth: 25
implicitHeight: 25
color: "white"
border.color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
drawer.penColor = parent.color;
}
}
}
Rectangle {
id: blackBrush
implicitWidth: 25
implicitHeight: 25
color: "black"
border.color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
drawer.penColor = parent.color;
}
}
}
Rectangle {
id: redBrush
implicitWidth: 25
implicitHeight: 25
color: "red"
border.color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
drawer.penColor = parent.color;
}
}
}
Rectangle {
id: greenBrush
implicitWidth: 25
implicitHeight: 25
color: "green"
border.color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
drawer.penColor = parent.color;
}
}
}
Rectangle {
id: blueBrush
implicitWidth: 25
implicitHeight: 25
color: "blue"
border.color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
drawer.penColor = parent.color;
}
}
}
Label {
text: " "
}
Button {
text: "Clear"
onClicked: {
drawer.needsClear = true
drawer.requestPaint()
}
}
}
RowLayout {
visible: !root.stampMode
Slider {
id: penWidthSlider
from: 1
to: 50
value: 5
}
Label {
Layout.fillWidth: true
text: "Pen Width"
}
}
}
Texture {
id: drawerTexture
sourceItem: drawerChoice.checked ? drawer : null
mappingMode: root.envMapMode ? Texture.Environment : Texture.UV
}
}