From 74a66ca4cc5208d0ee55a81a5997ab5710a9500f Mon Sep 17 00:00:00 2001 From: Digital Artifex <7929434+DigitalArtifex@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:21:04 -0500 Subject: [PATCH] Fixed inconsistent mirroring. Closes #10 --- package/contents/config/main.xml | 48 ++++-- package/contents/ui/ShaderChannel.qml | 5 +- .../ui/ShaderChannelConfiguration.qml | 139 ++++++++++++++++-- package/contents/ui/ShaderToyHub.qml | 4 +- package/contents/ui/ShaderToyModel.qml | 87 +++++++---- package/contents/ui/config.qml | 22 ++- package/contents/ui/main.qml | 9 +- 7 files changed, 234 insertions(+), 80 deletions(-) diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 74c9973..1becfd7 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -65,17 +65,21 @@ true - - - true - 1.0 + + + 2 + + + + 3 + - ./Resources/wallpaper2.png + "" @@ -97,14 +101,18 @@ true - - - true - 1.0 + + + 2 + + + + 3 + ./Resources/Shadertoy_Organic_2.jpg @@ -129,9 +137,13 @@ true - - - true + + + 2 + + + + 3 @@ -161,14 +173,18 @@ false - - - true - 1.0 + + + 0 + + + + 3 + 1920 diff --git a/package/contents/ui/ShaderChannel.qml b/package/contents/ui/ShaderChannel.qml index baf3474..9afa98e 100644 --- a/package/contents/ui/ShaderChannel.qml +++ b/package/contents/ui/ShaderChannel.qml @@ -79,7 +79,6 @@ Item property var wrapMode: ShaderEffectSource.Repeat property var format: ShaderEffectSource.RGBA8 property var windowModel - property bool invert: false property var iChannelResolution: [Qt.vector3d(channel.iResolution.x * iResolutionScale, channel.iResolution.y * iResolutionScale, 1), Qt.vector3d(channel.iResolution.x * iResolutionScale, channel.iResolution.y * iResolutionScale, 1), Qt.vector3d(channel.iResolution.x * iResolutionScale, channel.iResolution.y * iResolutionScale, 1)] @@ -95,7 +94,7 @@ Item property vector4d iMouse: Qt.vector4d(channel.iMouse.x * channel.mouseBias, channel.iMouse.y * channel.mouseBias, channel.iMouse.z, channel.iMouse.w) property real iTime: 0 property real lastITime: 0 - property real angle: channel.invert ? 180 : 0 + property real angle: 0 } onITimeChanged: @@ -473,7 +472,7 @@ Item // recursive frame buffer ShaderEffectSource - { + { id: frameBufferSource sourceItem: channel.channelShaderOutput === -1 ? null : channelShaderOutput sourceRect: Qt.rect(0,0, channelShaderOutput.width, channelShaderOutput.height) diff --git a/package/contents/ui/ShaderChannelConfiguration.qml b/package/contents/ui/ShaderChannelConfiguration.qml index f10e7b7..922f476 100644 --- a/package/contents/ui/ShaderChannelConfiguration.qml +++ b/package/contents/ui/ShaderChannelConfiguration.qml @@ -63,7 +63,8 @@ Item property alias tmp_resolution_scale: resolutionScaleSlider.value property alias tmp_resolution_x: resolutionXEdit.value property alias tmp_resolution_y: resolutionYEdit.value - property alias tmp_invert: channelInvertedCheckBox.checked + property alias tmp_mirroring: textureMirroringSelector.currentIndex + property alias tmp_wrap: textureWrapSelector.currentIndex property bool tmp_enabled: tmp_source !== "" property Palette palette @@ -73,8 +74,9 @@ Item property real resolution_scale property int resolution_x property int resolution_y + property int textureMirroring + property int textureWrapping property bool enabled - property bool invert property bool changed id: window @@ -355,12 +357,19 @@ Item pexelsVideoDialog.open() } } - } - CheckBox - { - id: channelInvertedCheckBox - text: i18n("Invert Channel Data") + Button + { + visible: window.tmp_type === ShaderChannel.CubeMapChannel + icon.name: "network-symbolic" + Layout.preferredWidth: Kirigami.Units.gridUnit * 2 + Layout.preferredHeight: Kirigami.Units.gridUnit * 2 + + onClicked: + { + cubemapHubDialog.open() + } + } } RowLayout @@ -568,6 +577,80 @@ Item } } } + + RowLayout + { + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true + + RowLayout + { + Layout.fillWidth: true + Label + { + text: "Texture Mirroring" + color: palette.text + Layout.preferredHeight: 35 + verticalAlignment: Text.AlignVCenter + } + + ComboBox + { + id: textureMirroringSelector + Layout.fillWidth: true + Layout.preferredHeight: 35 + + model: ListModel { + ListElement { text: "No Mirroring" } + ListElement { text: "Mirror Horizontally" } + ListElement { text: "Mirror Vertically" } + } + + onCurrentIndexChanged: () => + { + mainItem.tmp_mirroring = currentIndex + } + } + } + + RowLayout + { + Layout.fillWidth: true + Label + { + text: "Texture Wrap Mode" + color: palette.text + Layout.preferredHeight: 35 + verticalAlignment: Text.AlignVCenter + } + + ComboBox + { + id: textureWrapSelector + Layout.fillWidth: true + Layout.preferredHeight: 35 + + model: ListModel { + ListElement { text: "Clamp To Edge" } + ListElement { text: "Repeat Horizontally" } + ListElement { text: "Repeat Vertically" } + ListElement { text: "Repeat" } + } + + onCurrentIndexChanged: () => + { + mainItem.tmp_wrap = currentIndex + } + } + } + } + + Rectangle + { + color: "transparent" + Layout.fillHeight: true + } + RowLayout { Layout.fillWidth: true @@ -630,7 +713,7 @@ Item width: pexelsVideoDialog.width - 10 height: pexelsVideoDialog.height - 40 - onSelectedFileChanged: + onSelectedFileChanged: () => { window.tmp_source = pexelsImageHub.selectedFile @@ -642,6 +725,32 @@ Item } } + Kirigami.OverlaySheet + { + title: "Cubemap Import" + id: cubemapHubDialog + implicitWidth: 960 + implicitHeight: 480 + parent: applicationWindow().overlay + + CubemapHub + { + id: cubemapHub + width: cubemapHubDialog.width - 10 + height: cubemapHubDialog.height - 40 + + onSelectedFileChanged: () => + { + window.tmp_source = cubemapHub.selectedFile + + if(selectedFile === "" || selectedFile === undefined) + return; + + cubemapHubDialog.close() + } + } + } + Kirigami.OverlaySheet { title: "Pexels Video Import" @@ -656,7 +765,7 @@ Item width: pexelsVideoDialog.width - 10 height: pexelsVideoDialog.height - 40 - onSelectedFileChanged: + onSelectedFileChanged: () => { window.tmp_source = pexelsVideoHub.selectedFile @@ -678,7 +787,8 @@ Item resolution_x = tmp_resolution_x resolution_y = tmp_resolution_y enabled = tmp_enabled - invert = tmp_invert + textureMirroring = tmp_mirroring + textureWrapping = tmp_wrap // Emit the accepted signal and reset the selection window.accepted() @@ -727,17 +837,18 @@ Item function resetSelection() { if((tmp_source !== source) || (tmp_enabled !== enabled) || - (tmp_invert !== invert) || (tmp_resolution_scale !== resolution_scale) || + (tmp_mirroring !== textureMirroring) || (tmp_resolution_scale !== resolution_scale) || (tmp_resolution_x !== resolution_x) || (tmp_resolution_y !== resolution_y) || - (tmp_timeScale !== timeScale) || (tmp_type !== type)) + (tmp_timeScale !== timeScale) || (tmp_type !== type) || (tmp_wrap !== textureWrapping)) changed = true; - + tmp_source = source tmp_timeScale = timeScale tmp_resolution_scale = resolution_scale tmp_resolution_x = resolution_x tmp_resolution_y = resolution_y - tmp_invert = invert + tmp_mirroring = textureMirroring + tmp_wrap = textureWrapping tmp_type = type updateCurrentSelection() diff --git a/package/contents/ui/ShaderToyHub.qml b/package/contents/ui/ShaderToyHub.qml index 228d36d..b4fbf08 100644 --- a/package/contents/ui/ShaderToyHub.qml +++ b/package/contents/ui/ShaderToyHub.qml @@ -587,7 +587,7 @@ Item { Layout.alignment: Qt.AlignRight standardButtons: DialogButtonBox.Ok - onAccepted: messageDialog.close() + onAccepted: warningDialog.close() } } @@ -596,8 +596,6 @@ Item target: searchModel function onStatusChanged() { - console.log("Search Model Status " + searchModel.status) - if(searchModel.status === Komplex.KomplexSearchModel.Error) { warningDialog.open(); diff --git a/package/contents/ui/ShaderToyModel.qml b/package/contents/ui/ShaderToyModel.qml index dc5dea5..4f80df1 100644 --- a/package/contents/ui/ShaderToyModel.qml +++ b/package/contents/ui/ShaderToyModel.qml @@ -83,18 +83,25 @@ Item visible: true iTime: mainItem.iTime iMouse: mainItem.iMouse - iResolution: mainItem.iResolution + + iResolution: [ + wallpaper.configuration.iChannel0_resolution_x, + wallpaper.configuration.iChannel0_resolution_y + ] + + iDate: mainItem.iDate iFrame: mainItem.iFrame id: channel0 - // width: mainItem.iResolution.x - // height: mainItem.iResolution.y - type: wallpaper.configuration.iChannel0_flag ? wallpaper.configuration.iChannel0_type : 0 + width: wallpaper.configuration.iChannel0_resolution_x + height: wallpaper.configuration.iChannel0_resolution_y + type: wallpaper.configuration.iChannel0_type - source: wallpaper.configuration.iChannel0_flag ? Qt.resolvedUrl(wallpaper.configuration.iChannel0) : "" + source: Qt.resolvedUrl(wallpaper.configuration.iChannel0) // ShaderToy seems to start at bottom left for 0,0 - invert: wallpaper.configuration.iChannel0_inverted !== undefined ? wallpaper.configuration.iChannel0_inverted : true + wrapMode: wallpaper.configuration.iChannel0_wrap_mode + textureMirroring: wallpaper.configuration.iChannel0_mirroring_mode } ShaderChannel @@ -102,18 +109,25 @@ Item //Fallback to a channel if the output channel is not set or there was an error loading the shader visible: wallpaper.configuration.iChannel1_flag && (channelOutput.source === "" || channelOutput.source === undefined) iTime: mainItem.iTime - iResolution: mainItem.iResolution + + iResolution: [ + wallpaper.configuration.iChannel1_resolution_x, + wallpaper.configuration.iChannel1_resolution_y + ] + + iDate: mainItem.iDate iFrame: mainItem.iFrame id: channel1 - width: mainItem.iResolution.x - height: mainItem.iResolution.y + width: wallpaper.configuration.iChannel1_resolution_x + height: wallpaper.configuration.iChannel1_resolution_y type: wallpaper.configuration.iChannel1_flag ? wallpaper.configuration.iChannel1_type : 0 source: wallpaper.configuration.iChannel1_flag ? Qt.resolvedUrl(wallpaper.configuration.iChannel1) : "" // ShaderToy seems to start at bottom left for 0,0 - invert: wallpaper.configuration.iChannel1_inverted ? wallpaper.configuration.iChannel1_inverted : true + wrapMode: wallpaper.configuration.iChannel1_wrap_mode + textureMirroring: wallpaper.configuration.iChannel1_mirroring_mode } ShaderChannel @@ -121,18 +135,25 @@ Item //Fallback to a channel if the output channel is not set or there was an error loading the shader visible: wallpaper.configuration.iChannel2_flag && (channelOutput.source === "" || channelOutput.source === undefined) iTime: mainItem.iTime - iResolution: mainItem.iResolution + + iResolution: [ + wallpaper.configuration.iChannel2_resolution_x, + wallpaper.configuration.iChannel2_resolution_y + ] + + iDate: mainItem.iDate iFrame: mainItem.iFrame id: channel2 - width: mainItem.iResolution.x - height: mainItem.iResolution.y + width: wallpaper.configuration.iChannel2_resolution_x + height: wallpaper.configuration.iChannel2_resolution_y type: wallpaper.configuration.iChannel2_flag ? wallpaper.configuration.iChannel2_type : 0 source: wallpaper.configuration.iChannel2_flag ? Qt.resolvedUrl(wallpaper.configuration.iChannel2) : "" // ShaderToy seems to start at bottom left for 0,0 - invert: wallpaper.configuration.iChannel2_inverted ? wallpaper.configuration.iChannel2_inverted : true + wrapMode: wallpaper.configuration.iChannel2_wrap_mode + textureMirroring: wallpaper.configuration.iChannel2_mirroring_mode } ShaderChannel @@ -140,19 +161,25 @@ Item //Fallback to a channel if the output channel is not set or there was an error loading the shader visible: wallpaper.configuration.iChannel3_flag && (channelOutput.source === "" || channelOutput.source === undefined) iTime: mainItem.iTime - iResolution: mainItem.iResolution + + iResolution: [ + wallpaper.configuration.iChannel3_resolution_x, + wallpaper.configuration.iChannel3_resolution_y + ] + iDate: mainItem.iDate iFrame: mainItem.iFrame id: channel3 - width: mainItem.iResolution.x - height: mainItem.iResolution.y + width: wallpaper.configuration.iChannel3_resolution_x + height: wallpaper.configuration.iChannel3_resolution_y type: wallpaper.configuration.iChannel3_flag ? wallpaper.configuration.iChannel3_type : 0 source: wallpaper.configuration.iChannel3_flag ? Qt.resolvedUrl(wallpaper.configuration.iChannel3) : "" // ShaderToy seems to start at bottom left for 0,0 - invert: wallpaper.configuration.iChannel3_inverted ? wallpaper.configuration.iChannel3_inverted : true + wrapMode: wallpaper.configuration.iChannel3_wrap_mode + textureMirroring: wallpaper.configuration.iChannel3_mirroring_mode } // The output channel that combines all the input channels and displays the final shader output @@ -179,19 +206,19 @@ Item blending: false } - // ShaderEffectSource - // { - // anchors.fill: parent - // sourceItem: channelOutput - // sourceRect: Qt.rect(0,0, mainItem.iResolution.x, mainItem.iResolution.y) - // textureSize: Qt.size(mainItem.iResolution.x, mainItem.iResolution.y) - // hideSource: true - // visible: true - // smooth: true - // live: true + ShaderEffectSource + { + anchors.fill: parent + sourceItem: channelOutput + sourceRect: Qt.rect(0,0, mainItem.iResolution.x, mainItem.iResolution.y) + textureSize: Qt.size(mainItem.iResolution.x, mainItem.iResolution.y) + hideSource: true + visible: true + smooth: true + live: true - // id: finalSource - // } + id: finalSource + } // To save on performance, just use one timer for all channels Timer diff --git a/package/contents/ui/config.qml b/package/contents/ui/config.qml index ed40eb1..9a2791e 100644 --- a/package/contents/ui/config.qml +++ b/package/contents/ui/config.qml @@ -36,6 +36,7 @@ import com.github.digitalartifex.komplex 1.0 as Komplex Kirigami.FormLayout { + wideMode: true id: root twinFormLayouts: parentLayout // required by parent property alias formLayout: root // required by parent @@ -71,10 +72,14 @@ Kirigami.FormLayout property alias cfg_iChannel2_resolution_y: shaderChannelConfig2.resolution_y property alias cfg_iChannel3_resolution_x: shaderChannelConfig3.resolution_x property alias cfg_iChannel3_resolution_y: shaderChannelConfig3.resolution_y - property alias cfg_iChannel0_inverted: shaderChannelConfig0.invert - property alias cfg_iChannel1_inverted: shaderChannelConfig1.invert - property alias cfg_iChannel2_inverted: shaderChannelConfig2.invert - property alias cfg_iChannel3_inverted: shaderChannelConfig3.invert + property alias cfg_iChannel0_wrap_mode: shaderChannelConfig0.textureWrapping + property alias cfg_iChannel1_wrap_mode: shaderChannelConfig1.textureWrapping + property alias cfg_iChannel2_wrap_mode: shaderChannelConfig2.textureWrapping + property alias cfg_iChannel3_wrap_mode: shaderChannelConfig3.textureWrapping + property alias cfg_iChannel0_mirroring_mode: shaderChannelConfig0.textureMirroring + property alias cfg_iChannel1_mirroring_mode: shaderChannelConfig1.textureMirroring + property alias cfg_iChannel2_mirroring_mode: shaderChannelConfig2.textureMirroring + property alias cfg_iChannel3_mirroring_mode: shaderChannelConfig3.textureMirroring property alias cfg_shaderSpeed: speedSlider.value property alias cfg_mouseSpeedBias: mouseBiasSlider.value property alias cfg_mouseAllowed: mouseEnableButton.checked @@ -459,6 +464,7 @@ Kirigami.FormLayout id: shaderChannelOverlay1 parent: applicationWindow().overlay implicitHeight: 420 + implicitWidth: 960 ShaderChannelConfiguration { @@ -511,6 +517,7 @@ Kirigami.FormLayout id: shaderChannelOverlay2 parent: applicationWindow().overlay implicitHeight: 420 + implicitWidth: 960 ShaderChannelConfiguration { @@ -562,6 +569,7 @@ Kirigami.FormLayout id: shaderChannelOverlay3 parent: applicationWindow().overlay implicitHeight: 420 + implicitWidth: 960 ShaderChannelConfiguration { @@ -685,11 +693,11 @@ Kirigami.FormLayout } background: Rectangle { - color: resolutionXField.activeFocus ? palette.base : "transparent" - border.color: resolutionXField.activeFocus ? palette.highlight : "transparent" + color: frameRateField.activeFocus ? palette.base : "transparent" + border.color: frameRateField.activeFocus ? palette.highlight : "transparent" border.width: 1 radius: 4 - anchors.fill: resolutionXField + anchors.fill: frameRateField anchors.margins: -2 } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index b49ff4e..1747cfe 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -36,8 +36,9 @@ import org.kde.plasma.plasmoid WallpaperItem { id: wallpaperItem - Item + Rectangle { + color: "black" property int resolution_x: wallpaper.configuration.resolution_x property int resolution_y: wallpaper.configuration.resolution_y property string shaderPack: wallpaper.configuration.shader_package @@ -45,11 +46,6 @@ WallpaperItem property bool updated: wallpaper.configuration.shader_updated - property bool iChannel0_inverted: wallpaper.configuration.iChannel0_inverted - property bool iChannel1_inverted: wallpaper.configuration.iChannel1_inverted - property bool iChannel2_inverted: wallpaper.configuration.iChannel2_inverted - property bool iChannel3_inverted: wallpaper.configuration.iChannel3_inverted - anchors.fill: parent Loader @@ -106,7 +102,6 @@ WallpaperItem onResolution_xChanged: () => reload(); onResolution_yChanged: () => reload(); onShaderPackChanged: () => reload(); - onIChannel0_invertedChanged: () => reload(); onUpdatedChanged: () => {