diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 991b657..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch PNGTuber Plus (Godot)", - "type": "godot", - "request": "launch", - "port": 6007, - "address": "127.0.0.1" - }, - { - "name": "Attach to Running Godot", - "type": "godot", - "request": "attach", - "port": 6007, - "address": "127.0.0.1" - }, - { - "name": "Launch Built Executable", - "type": "PowerShell", - "request": "launch", - "script": "if (Test-Path '${workspaceFolder}\\build\\windows\\PNGTuber-Plus.exe') { Start-Process '${workspaceFolder}\\build\\windows\\PNGTuber-Plus.exe' } else { Write-Host 'Executable not found. Build the project first.' }", - "cwd": "${workspaceFolder}" - }, - { - "name": "Build and Launch", - "type": "PowerShell", - "request": "launch", - "script": ".\\build-windows.bat; if (Test-Path '.\\build\\windows\\PNGTuber-Plus.exe') { Start-Process '.\\build\\windows\\PNGTuber-Plus.exe' }", - "cwd": "${workspaceFolder}" - } - ] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 5182b61..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Build Windows (Local)", - "type": "shell", - "command": ".\\build-windows.bat", - "group": { - "kind": "build", - "isDefault": true - }, - "args": [], - "isBackground": false, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Build Windows executable using local build script with template management" - }, - { - "label": "Build Windows (CI)", - "type": "shell", - "command": ".\\build-windows-ci.bat", - "group": "build", - "args": [], - "isBackground": false, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Build Windows executable using CI build script (no template download)" - }, - { - "label": "Export Windows (Godot Direct)", - "type": "shell", - "command": "D:\\Godot\\Godot_v4.4.1-stable_win64.exe", - "group": "build", - "args": [ - "--headless", - "--export-release", - "\"Windows Desktop\"", - "\"build/windows/PNGTuber-Plus.exe\"" - ], - "isBackground": false, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Export Windows build directly using Godot (requires templates already installed)" - }, - { - "label": "Clean Build Directory", - "type": "shell", - "command": "if (Test-Path 'build') { Remove-Item -Recurse -Force 'build' }; Write-Host 'Build directory cleaned'", - "group": "build", - "args": [], - "isBackground": false, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Clean the build output directory" - }, - { - "label": "Open Build Directory", - "type": "shell", - "command": "if (Test-Path 'build\\windows') { explorer 'build\\windows' } else { Write-Host 'Build directory does not exist. Run a build first.' }", - "group": "build", - "args": [], - "isBackground": false, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Open the Windows build output directory in Explorer" - }, - { - "label": "Run Built Executable", - "type": "shell", - "command": "if (Test-Path 'build\\windows\\PNGTuber-Plus.exe') { Start-Process 'build\\windows\\PNGTuber-Plus.exe' } else { Write-Host 'Executable not found. Build the project first.' }", - "group": "test", - "args": [], - "isBackground": true, - "problemMatcher": [], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "shared", - "showReuseMessage": true, - "clear": false - }, - "detail": "Run the built Windows executable for testing" - } - ] -} \ No newline at end of file diff --git a/build-windows.bat b/build-windows.bat index 1dab021..d4483e9 100644 --- a/build-windows.bat +++ b/build-windows.bat @@ -47,3 +47,4 @@ if %ERRORLEVEL% EQU 0 ( echo. ) +pause diff --git a/main_scenes/main.gd b/main_scenes/main.gd index d61e0cd..70ea9fb 100644 --- a/main_scenes/main.gd +++ b/main_scenes/main.gd @@ -30,7 +30,6 @@ var editMode = true @onready var spriteObject = preload("res://ui_scenes/selectedSprite/spriteObject.tscn") var saveLoaded = false -var isSelectingMask = false #Motion var yVel = 0 @@ -63,9 +62,7 @@ func _ready(): Global.connect("startSpeaking",onSpeak) - var streamdeck_node = get_node_or_null("/root/ElgatoStreamDeck") - if streamdeck_node: - streamdeck_node.on_key_down.connect(changeCostumeStreamDeck) + ElgatoStreamDeck.on_key_down.connect(changeCostumeStreamDeck) if Saving.settings["newUser"]: _on_load_dialog_file_selected("default") @@ -156,9 +153,6 @@ func _process(delta): followShadow() func followShadow(): - shadow.visible = false # Disabled drop shadow - return - shadow.visible = is_instance_valid(Global.heldSprite) if !shadow.visible: return @@ -177,9 +171,6 @@ func isFileSystemOpen(): if obj.visible: if obj == replaceDialog: return true - # Don't clear held sprite when selecting mask - if obj == fileDialog and isSelectingMask: - return true Global.heldSprite = null return true return false @@ -297,20 +288,7 @@ func _on_add_button_pressed(): #Runs when selecting image in File Dialog func _on_file_dialog_file_selected(path): - if isSelectingMask: - # Handle mask selection - if Global.heldSprite != null: - Global.heldSprite.setMaskTexture(path) - Global.spriteEdit.updateMaskDisplay(path) - isSelectingMask = false - else: - # Handle normal sprite addition - add_image(path) - -#Opens File Dialog for mask selection -func openMaskSelection(): - isSelectingMask = true - fileDialog.visible = true + add_image(path) func _on_save_button_pressed(): $SaveDialog.visible = true @@ -385,14 +363,6 @@ func _on_load_dialog_file_selected(path): if data[item].has("toggle"): sprite.toggle = data[item]["toggle"] - # Load mask properties - if data[item].has("mask_texture_path"): - sprite.mask_texture_path = data[item]["mask_texture_path"] - if data[item].has("use_mask"): - sprite.use_mask = data[item]["use_mask"] - if data[item].has("mask_opacity"): - sprite.mask_opacity = data[item]["mask_opacity"] - origin.add_child(sprite) sprite.position = str_to_var(data[item]["pos"]) @@ -454,11 +424,6 @@ func _on_save_dialog_file_selected(path): data[id]["toggle"] = child.toggle - # Save mask properties - data[id]["mask_texture_path"] = child.mask_texture_path - data[id]["use_mask"] = child.use_mask - data[id]["mask_opacity"] = child.mask_opacity - id += 1 Saving.settings["lastAvatar"] = path @@ -582,7 +547,7 @@ func moveSpriteMenu(delta): var size = get_viewport().get_visible_rect().size - var windowLength = 1800 + var windowLength = 1400 $ViewerArrows/Arrows.position.y = size.y - 25 @@ -639,7 +604,7 @@ func _on_background_input_capture_bg_key_pressed(node, keys_pressed): var has_ctrl = keys_pressed.has(KEY_CTRL) and keys_pressed[KEY_CTRL] var has_shift = keys_pressed.has(KEY_SHIFT) and keys_pressed[KEY_SHIFT] var has_alt = keys_pressed.has(KEY_ALT) and keys_pressed[KEY_ALT] - var meta_pressed = keys_pressed.has(KEY_META) and keys_pressed[KEY_META] # Command key on macOS + var has_meta = keys_pressed.has(KEY_META) and keys_pressed[KEY_META] # Command key on macOS # Build modifier prefix once if has_ctrl: @@ -648,7 +613,7 @@ func _on_background_input_capture_bg_key_pressed(node, keys_pressed): modifiers.append("Shift") if has_alt: modifiers.append("Alt") - if meta_pressed: + if has_meta: modifiers.append("Cmd") # Command key on macOS var modifier_prefix = "" diff --git a/main_scenes/main.tscn b/main_scenes/main.tscn index 5c83c79..adec62c 100644 --- a/main_scenes/main.tscn +++ b/main_scenes/main.tscn @@ -14744,5 +14744,5 @@ z_index = -4096 [connection signal="visibility_changed" from="ReplaceDialog" to="." method="_on_replace_dialog_visibility_changed"] [connection signal="file_selected" from="SaveDialog" to="." method="_on_save_dialog_file_selected"] [connection signal="file_selected" from="LoadDialog" to="." method="_on_load_dialog_file_selected"] -[connection signal="bg_key_pressed" from="BackgroundInputCapture" to="." method="_on_background_input_capture_bg_key_pressed"] [connection signal="bg_key_pressed" from="BackgroundInputCapture" to="." method="bgInputSprite"] +[connection signal="bg_key_pressed" from="BackgroundInputCapture" to="." method="_on_background_input_capture_bg_key_pressed"] diff --git a/project.godot b/project.godot index 40f85b4..ed8db17 100644 --- a/project.godot +++ b/project.godot @@ -148,6 +148,4 @@ textures/canvas_textures/default_texture_filter=0 textures/canvas_textures/default_texture_repeat=1 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" -shading/overrides/force_vertex_shading=true -shading/overrides/force_lambert_over_burley=true environment/defaults/default_clear_color=Color(0.376471, 0.376471, 0.376471, 1) diff --git a/shader/wobble.gdshader b/shader/wobble.gdshader index 1207836..aa0fa34 100644 --- a/shader/wobble.gdshader +++ b/shader/wobble.gdshader @@ -1,21 +1,11 @@ shader_type canvas_item; -uniform sampler2D noise_texture: source_color, repeat_enable; -uniform float distortion_strengh: hint_range(0, 0.1) = 0.01; +uniform sampler2D noise_texture:repeat_enable; +uniform float distortion_strengh: hint_range(0, 0.1) = 1.0; uniform float speed: hint_range(0.1, 10) = 1.0; -uniform bool use_noise_texture: hint_default_true = false; void fragment() { - vec2 uv_offset = vec2(0.0); - - if (use_noise_texture) { - vec4 noise_pixel = texture(noise_texture, UV + floor(TIME * speed) / 3.0); - uv_offset = (noise_pixel.rg * 2.0 - 1.0) * distortion_strengh; - } else { - // Fallback procedural noise when no texture is provided - float noise = sin(UV.x * 20.0 + TIME * speed) * cos(UV.y * 20.0 + TIME * speed * 0.7); - uv_offset = vec2(noise) * distortion_strengh; - } - + vec4 noise_pixel = texture(noise_texture, UV + floor(TIME*speed)/3.0); + vec2 uv_offset = (noise_pixel.rg * 2.0 - 1.0) * distortion_strengh; COLOR = texture(TEXTURE, UV + uv_offset); } \ No newline at end of file diff --git a/shader/wobble.gdshader.uid b/shader/wobble.gdshader.uid index fbfb14a..6a1efb3 100644 --- a/shader/wobble.gdshader.uid +++ b/shader/wobble.gdshader.uid @@ -1 +1 @@ -uid://4a1uhohwy43l +uid://b342og0l0k1p diff --git a/ui_scenes/selectedSprite/mask.gdshader b/ui_scenes/selectedSprite/mask.gdshader deleted file mode 100644 index 74d84fa..0000000 --- a/ui_scenes/selectedSprite/mask.gdshader +++ /dev/null @@ -1,23 +0,0 @@ -shader_type canvas_item; - -uniform sampler2D mask_texture : source_color; -uniform bool use_mask = false; -uniform float mask_opacity : hint_range(0.0, 1.0) = 1.0; - -void fragment() { - // Get the original sprite color - vec4 sprite_color = texture(TEXTURE, UV); - - if (use_mask) { - // Sample the mask texture - vec4 mask_sample = texture(mask_texture, UV); - - // Use the mask's alpha channel to determine visibility - float mask_alpha = mask_sample.a * mask_opacity; - - // Apply the mask by multiplying the sprite's alpha with the mask alpha - sprite_color.a *= mask_alpha; - } - - COLOR = sprite_color; -} diff --git a/ui_scenes/selectedSprite/mask.gdshader.uid b/ui_scenes/selectedSprite/mask.gdshader.uid deleted file mode 100644 index 4c00b3a..0000000 --- a/ui_scenes/selectedSprite/mask.gdshader.uid +++ /dev/null @@ -1 +0,0 @@ -uid://btd72itp0cy6b diff --git a/ui_scenes/selectedSprite/outline.gdshader b/ui_scenes/selectedSprite/outline.gdshader index c5c04b1..b4cee71 100644 --- a/ui_scenes/selectedSprite/outline.gdshader +++ b/ui_scenes/selectedSprite/outline.gdshader @@ -1,8 +1,17 @@ shader_type canvas_item; -uniform vec4 outline_color : source_color = vec4(1.0, 0.0, 0.0, 0.3); +uniform float speed; + +uniform sampler2D backImg: repeat_enable; + +uniform sampler2D palette; +uniform float palette_speed = 0.1; void fragment(){ - vec4 tex = texture(TEXTURE, UV); - COLOR = vec4(outline_color.rgb, tex.a * outline_color.a); + + vec2 scroll = vec2(1.0,0.0) * TIME * speed; + vec4 tex = texture(TEXTURE, (UV)); + float palette_swap = mod(tex.r - TIME * palette_speed, 1.0); + COLOR = vec4(texture(palette, vec2(palette_swap, 0)).rgb, tex.a); + } \ No newline at end of file diff --git a/ui_scenes/selectedSprite/spriteObject.gd b/ui_scenes/selectedSprite/spriteObject.gd index 21aa2a2..b0686b6 100644 --- a/ui_scenes/selectedSprite/spriteObject.gd +++ b/ui_scenes/selectedSprite/spriteObject.gd @@ -77,12 +77,6 @@ var ignoreBounce = false var frames = 1 var animSpeed = 0 -#Masking -var mask_texture_path = "" -var mask_texture = null -var use_mask = false -var mask_opacity = 1.0 - var remadePolygon = false var clipped = false @@ -125,9 +119,6 @@ func _ready(): sprite.texture = tex - # Initialize masking - setupMasking() - var bitmap = BitMap.new() bitmap.create_from_image_alpha(imageData) @@ -418,53 +409,3 @@ func visToggle(keys): func makeVis(): $WobbleOrigin/DragOrigin.visible = true - -## Setup masking system -func setupMasking(): - if use_mask and mask_texture_path != "": - loadMaskTexture() - updateMaskShader() - -## Load mask texture from file path -func loadMaskTexture(): - if mask_texture_path == "": - return - - var img = Image.new() - var err = img.load(mask_texture_path) - if err != OK: - print_debug("Failed to load mask texture: " + mask_texture_path) - return - - mask_texture = ImageTexture.create_from_image(img) - -## Apply or remove mask shader -func updateMaskShader(): - if use_mask and mask_texture != null: - # Create mask material with shader - var mask_shader = load("res://ui_scenes/selectedSprite/mask.gdshader") - var mask_material = ShaderMaterial.new() - mask_material.shader = mask_shader - mask_material.set_shader_parameter("mask_texture", mask_texture) - mask_material.set_shader_parameter("use_mask", true) - mask_material.set_shader_parameter("mask_opacity", mask_opacity) - - sprite.material = mask_material - else: - # Remove mask material - sprite.material = null - -## Set mask texture from external source -func setMaskTexture(texture_path: String, opacity: float = 1.0): - mask_texture_path = texture_path - mask_opacity = opacity - use_mask = true - loadMaskTexture() - updateMaskShader() - -## Remove masking -func removeMask(): - use_mask = false - mask_texture = null - mask_texture_path = "" - updateMaskShader() diff --git a/ui_scenes/settings/settings_menu.gd b/ui_scenes/settings/settings_menu.gd index 3034eed..d4b34d3 100644 --- a/ui_scenes/settings/settings_menu.gd +++ b/ui_scenes/settings/settings_menu.gd @@ -204,8 +204,8 @@ func _on_costume_check_toggled(button_pressed): ## @param button_pressed: bool - Whether StreamDeck should be enabled func _on_stream_deck_check_toggled(button_pressed): Saving.settings["useStreamDeck"] = button_pressed - if get_node_or_null("/root/ElgatoStreamDeck"): - get_node("/root/ElgatoStreamDeck").refresh_connection() + if ElgatoStreamDeck: + ElgatoStreamDeck.refresh_connection() Global.pushUpdate("StreamDeck integration " + ("enabled" if button_pressed else "disabled") + ".") ## Handle experimental microphone loudness toggle diff --git a/ui_scenes/spriteEditMenu/sprite_viewer.gd b/ui_scenes/spriteEditMenu/sprite_viewer.gd index e5caab8..fe4d250 100644 --- a/ui_scenes/spriteEditMenu/sprite_viewer.gd +++ b/ui_scenes/spriteEditMenu/sprite_viewer.gd @@ -75,15 +75,6 @@ func setImage(): $VisToggle/setToggle/Label.text = "toggle: \"" + Global.heldSprite.toggle + "\"" - # Update masking controls - $Masking/useMaskCheckbox.button_pressed = Global.heldSprite.use_mask - $Masking/maskOpacityLabel.text = "mask opacity: " + str(Global.heldSprite.mask_opacity) - $Masking/maskOpacity.value = Global.heldSprite.mask_opacity - if Global.heldSprite.mask_texture_path.is_empty(): - $Masking/maskPathLabel.text = "mask: (none)" - else: - $Masking/maskPathLabel.text = "mask: " + Global.heldSprite.mask_texture_path.get_file() - changeRotLimit() setLayerButtons() @@ -373,25 +364,8 @@ func _on_delete_pressed(): func _on_set_toggle_pressed(): $VisToggle/setToggle/Label.text = "toggle: AWAITING INPUT" await Global.main.fatfuckingballs - -## Masking signal handlers -func _on_use_mask_checkbox_toggled(button_pressed): - Global.heldSprite.use_mask = button_pressed - Global.heldSprite.updateMaskShader() - -func _on_mask_opacity_value_changed(value): - Global.heldSprite.mask_opacity = value - $Masking/maskOpacityLabel.text = "mask opacity: " + str(value) - Global.heldSprite.updateMaskShader() - -func _on_select_mask_pressed(): - Global.main.openMaskSelection() - -func updateMaskDisplay(path: String): - $Masking/maskPathLabel.text = "mask: " + path.get_file() - $Masking/useMaskCheckbox.button_pressed = true - -func _on_clear_mask_pressed(): - Global.heldSprite.removeMask() - $Masking/maskPathLabel.text = "mask: (none)" - $Masking/useMaskCheckbox.button_pressed = false + + var keys = await Global.main.spriteVisToggles + var key = keys[0] + Global.heldSprite.toggle = key + $VisToggle/setToggle/Label.text = "toggle: \"" + Global.heldSprite.toggle + "\"" diff --git a/ui_scenes/spriteEditMenu/sprite_viewer.tscn b/ui_scenes/spriteEditMenu/sprite_viewer.tscn index 455f516..f3b4a4b 100644 --- a/ui_scenes/spriteEditMenu/sprite_viewer.tscn +++ b/ui_scenes/spriteEditMenu/sprite_viewer.tscn @@ -29,7 +29,7 @@ [ext_resource type="Texture2D" uid="uid://gflmeocxfnrq" path="res://ui_scenes/settings/deleteHotkey.png" id="27_fgu6g"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_21kva"] -size = Vector2(245, 1596.5) +size = Vector2(245, 1341) [sub_resource type="ShaderMaterial" id="ShaderMaterial_hxmah"] shader = ExtResource("3_ky0lu") @@ -14285,7 +14285,7 @@ script = ExtResource("1_hp0e3") z_index = -2 [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] -position = Vector2(122.5, 725) +position = Vector2(122.5, 670.5) shape = SubResource("RectangleShape2D_21kva") [node name="Border" type="Sprite2D" parent="."] @@ -14910,66 +14910,6 @@ position = Vector2(-2, -2) texture = ExtResource("27_fgu6g") centered = false -[node name="Masking" type="Node2D" parent="."] -position = Vector2(0, 1360.83) - -[node name="animationBox" type="Sprite2D" parent="Masking"] -position = Vector2(125, 92.4052) -scale = Vector2(1, 0.905768) -texture = ExtResource("15_wqi8b") - -[node name="maskingLabel" type="Label" parent="Masking"] -offset_left = 20.0 -offset_right = 120.0 -offset_bottom = 26.0 -text = "MASKING" -horizontal_alignment = 1 - -[node name="useMaskCheckbox" type="CheckBox" parent="Masking"] -offset_left = 20.0 -offset_top = 30.0 -offset_right = 200.0 -offset_bottom = 54.0 -text = "Use Mask" - -[node name="maskOpacityLabel" type="Label" parent="Masking"] -offset_left = 20.0 -offset_top = 60.0 -offset_right = 200.0 -offset_bottom = 86.0 -text = "mask opacity: 1.0" - -[node name="maskOpacity" type="HSlider" parent="Masking"] -offset_left = 20.0 -offset_top = 90.0 -offset_right = 200.0 -offset_bottom = 106.0 -max_value = 1.0 -step = 0.01 -value = 1.0 - -[node name="maskPathLabel" type="Label" parent="Masking"] -offset_left = 20.0 -offset_top = 120.0 -offset_right = 400.0 -offset_bottom = 146.0 -text = "mask: (none)" -autowrap_mode = 2 - -[node name="selectMask" type="Button" parent="Masking"] -offset_left = 20.0 -offset_top = 150.0 -offset_right = 120.0 -offset_bottom = 181.0 -text = "Select Mask" - -[node name="clearMask" type="Button" parent="Masking"] -offset_left = 130.0 -offset_top = 150.0 -offset_right = 220.0 -offset_bottom = 181.0 -text = "Clear Mask" - [connection signal="pressed" from="Buttons/Speaking/speaking" to="." method="_on_speaking_pressed"] [connection signal="pressed" from="Buttons/Blinking/blinking" to="." method="_on_blinking_pressed"] [connection signal="pressed" from="Buttons/Trash/trash" to="." method="_on_trash_pressed"] @@ -15001,7 +14941,3 @@ text = "Clear Mask" [connection signal="pressed" from="Layers/Layer10/layerButton10" to="." method="_on_layer_button_10_pressed"] [connection signal="pressed" from="VisToggle/setToggle" to="." method="_on_set_toggle_pressed"] [connection signal="pressed" from="VisToggle/setToggle/delete" to="." method="_on_delete_pressed"] -[connection signal="toggled" from="Masking/useMaskCheckbox" to="." method="_on_use_mask_checkbox_toggled"] -[connection signal="value_changed" from="Masking/maskOpacity" to="." method="_on_mask_opacity_value_changed"] -[connection signal="pressed" from="Masking/selectMask" to="." method="_on_select_mask_pressed"] -[connection signal="pressed" from="Masking/clearMask" to="." method="_on_clear_mask_pressed"]