mirror of
https://github.com/litruv/PNGTuber-Plus.git
synced 2026-07-24 02:26:02 +10:00
wobble sync groups !build
This commit is contained in:
@@ -94,6 +94,9 @@ var affectChildrenOpacity = false
|
||||
#Vis toggle
|
||||
var toggle = "null"
|
||||
|
||||
#Wobble Sync Group
|
||||
var wobbleSyncGroup = ""
|
||||
|
||||
func _ready():
|
||||
|
||||
Global.main.spriteVisToggles.connect(visToggle)
|
||||
@@ -171,6 +174,8 @@ func _ready():
|
||||
|
||||
setClip(clipped)
|
||||
|
||||
# Always initialize opacity shader
|
||||
updateShaderOpacity()
|
||||
|
||||
if Global.filtering:
|
||||
sprite.texture_filter = 2
|
||||
@@ -235,6 +240,16 @@ func _process(delta):
|
||||
grabArea.visible = false
|
||||
originSprite.visible = false
|
||||
|
||||
# Disable grabArea input and detection when dialogs are open
|
||||
if Global.main and Global.main.fileSystemOpen:
|
||||
grabArea.input_pickable = false
|
||||
grabArea.monitoring = false
|
||||
grabArea.monitorable = false
|
||||
else:
|
||||
grabArea.input_pickable = true
|
||||
grabArea.monitoring = true
|
||||
grabArea.monitorable = true
|
||||
|
||||
var glob = dragger.global_position
|
||||
if ignoreBounce:
|
||||
glob.y -= Global.main.bounceChange
|
||||
@@ -282,7 +297,12 @@ func talkBlink():
|
||||
# Only handle talk/blink/edit visibility with modulate
|
||||
# Opacity slider effects are handled by shader
|
||||
sprite.self_modulate.a = 1.0 # Always keep original texture alpha for clipping
|
||||
var previousAlpha = sprite.modulate.a
|
||||
sprite.modulate.a = baseAlpha # Only apply talk/blink/edit visibility
|
||||
|
||||
# Update shader if modulate alpha changed (for editor dimming)
|
||||
if previousAlpha != baseAlpha:
|
||||
updateShaderOpacity()
|
||||
|
||||
func calculateParentOpacityMultiplier():
|
||||
var multiplier = 1.0
|
||||
@@ -296,7 +316,40 @@ func calculateParentOpacityMultiplier():
|
||||
|
||||
return multiplier
|
||||
|
||||
## Update wobble parameters and sync to group if needed
|
||||
func updateWobbleParameter(parameter: String, value: float):
|
||||
print("DEBUG: updateWobbleParameter called - parameter: ", parameter, ", value: ", value, ", sprite ID: ", id)
|
||||
print("DEBUG: Current wobbleSyncGroup: '", wobbleSyncGroup, "'")
|
||||
|
||||
# Update this sprite's parameter first
|
||||
match parameter:
|
||||
"xFrq": xFrq = value
|
||||
"xAmp": xAmp = value
|
||||
"yFrq": yFrq = value
|
||||
"yAmp": yAmp = value
|
||||
"rFrq": rFrq = value
|
||||
"rAmp": rAmp = value
|
||||
|
||||
print("DEBUG: Parameter updated on sprite. New values - xFrq:", xFrq, " xAmp:", xAmp, " yFrq:", yFrq, " yAmp:", yAmp, " rFrq:", rFrq, " rAmp:", rAmp)
|
||||
|
||||
# If this sprite is in a sync group, update the entire group
|
||||
if wobbleSyncGroup != "" and WobbleSyncManager:
|
||||
print("DEBUG: Sprite is in sync group '", wobbleSyncGroup, "' - updating group wobble parameters")
|
||||
WobbleSyncManager.updateGroupWobble(wobbleSyncGroup, xFrq, xAmp, yFrq, yAmp, rFrq, rAmp)
|
||||
|
||||
# Don't refresh UI immediately - let the sync process complete first
|
||||
# The wobble sync control will handle UI updates when needed
|
||||
else:
|
||||
print("DEBUG: Sprite not in sync group or WobbleSyncManager not available")
|
||||
|
||||
## Check if this sprite is synced to a group
|
||||
func isSynced() -> bool:
|
||||
return wobbleSyncGroup != ""
|
||||
|
||||
func delete():
|
||||
# Clean up from wobble sync groups
|
||||
if wobbleSyncGroup != "" and WobbleSyncManager:
|
||||
WobbleSyncManager.onSpriteDeleted(id)
|
||||
queue_free()
|
||||
|
||||
func _physics_process(delta):
|
||||
@@ -460,17 +513,17 @@ func updateShaderOpacity():
|
||||
# Calculate total opacity from user settings and parent hierarchy
|
||||
var totalOpacity = spriteOpacity * calculateParentOpacityMultiplier()
|
||||
|
||||
if totalOpacity >= 1.0:
|
||||
# No shader needed for 100% opacity
|
||||
sprite.material = null
|
||||
else:
|
||||
# Create or update shader material for opacity less than 100%
|
||||
if opacityMaterial == null:
|
||||
opacityMaterial = ShaderMaterial.new()
|
||||
opacityMaterial.shader = opacityShader
|
||||
|
||||
opacityMaterial.set_shader_parameter("opacity", totalOpacity)
|
||||
sprite.material = opacityMaterial
|
||||
# Also factor in the modulate alpha for editor dimming/onion skinning
|
||||
var editorAlpha = sprite.modulate.a
|
||||
var finalOpacity = totalOpacity * editorAlpha
|
||||
|
||||
# Always apply the opacity shader to ensure it's loaded
|
||||
if opacityMaterial == null:
|
||||
opacityMaterial = ShaderMaterial.new()
|
||||
opacityMaterial.shader = opacityShader
|
||||
|
||||
opacityMaterial.set_shader_parameter("opacity", finalOpacity)
|
||||
sprite.material = opacityMaterial
|
||||
|
||||
func updateChildrenOpacityRecursively():
|
||||
var linkedSprites = getAllLinkedSprites()
|
||||
|
||||
@@ -201,8 +201,9 @@ 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 ElgatoStreamDeck:
|
||||
ElgatoStreamDeck.refresh_connection()
|
||||
var streamdeck_node = get_node_or_null("/root/ElgatoStreamDeck")
|
||||
if streamdeck_node != null:
|
||||
streamdeck_node.refresh_connection()
|
||||
Global.pushUpdate("StreamDeck integration " + ("enabled" if button_pressed else "disabled") + ".")
|
||||
|
||||
## Handle experimental microphone loudness toggle
|
||||
|
||||
@@ -9,11 +9,16 @@ extends Node2D
|
||||
|
||||
|
||||
@onready var coverCollider = $Area2D/CollisionShape2D
|
||||
|
||||
@onready var wobbleSyncControl = null # Will be assigned in _ready()
|
||||
|
||||
func _ready():
|
||||
Global.spriteEdit = self
|
||||
|
||||
# Find the wobble sync control node
|
||||
wobbleSyncControl = find_child("WobbleSyncControl")
|
||||
if wobbleSyncControl == null:
|
||||
print("Warning: WobbleSyncControl node not found in sprite viewer")
|
||||
|
||||
func setImage():
|
||||
if Global.heldSprite == null:
|
||||
return
|
||||
@@ -83,6 +88,16 @@ func setImage():
|
||||
|
||||
setLayerButtons()
|
||||
|
||||
# Update wobble sync control
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.setSprite(Global.heldSprite)
|
||||
# Force a refresh to ensure dropdown is populated
|
||||
await get_tree().process_frame
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
# Update wobble control states based on sync status
|
||||
updateWobbleControlStates()
|
||||
|
||||
if Global.heldSprite.parentId == null:
|
||||
$Buttons/Unlink.visible = false
|
||||
parentSpin.visible = false
|
||||
@@ -98,6 +113,30 @@ func setImage():
|
||||
parentSpin.pixel_size = 1.5 / nodes[0].imageData.get_size().y
|
||||
parentSpin.hframes = nodes[0].frames
|
||||
parentSpin.visible = true
|
||||
|
||||
## Update wobble control states based on sync status
|
||||
func updateWobbleControlStates():
|
||||
if Global.heldSprite == null:
|
||||
return
|
||||
|
||||
var isSynced = Global.heldSprite.isSynced()
|
||||
|
||||
# Keep wobble controls enabled even when synced (they edit group settings)
|
||||
$WobbleControl/xFrq.editable = true
|
||||
$WobbleControl/xAmp.editable = true
|
||||
$WobbleControl/yFrq.editable = true
|
||||
$WobbleControl/yAmp.editable = true
|
||||
$WobbleControl/rFrq.editable = true
|
||||
$WobbleControl/rAmp.editable = true
|
||||
|
||||
# Visual feedback for sync state - slight tint to indicate group editing
|
||||
var tint = Color(1.0, 1.0, 0.9) if isSynced else Color.WHITE
|
||||
$WobbleControl/xFrq.modulate = tint
|
||||
$WobbleControl/xAmp.modulate = tint
|
||||
$WobbleControl/yFrq.modulate = tint
|
||||
$WobbleControl/yAmp.modulate = tint
|
||||
$WobbleControl/rFrq.modulate = tint
|
||||
$WobbleControl/rAmp.modulate = tint
|
||||
|
||||
func _process(delta):
|
||||
|
||||
@@ -131,31 +170,55 @@ func _on_drag_slider_value_changed(value):
|
||||
|
||||
|
||||
func _on_x_frq_value_changed(value):
|
||||
print("DEBUG: _on_x_frq_value_changed called with value: ", value)
|
||||
$WobbleControl/xFrqLabel.text = "x frequency: " + str(value)
|
||||
Global.heldSprite.xFrq = value
|
||||
Global.heldSprite.updateWobbleParameter("xFrq", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
|
||||
func _on_x_amp_value_changed(value):
|
||||
print("DEBUG: _on_x_amp_value_changed called with value: ", value)
|
||||
$WobbleControl/xAmpLabel.text = "x amplitude: " + str(value)
|
||||
Global.heldSprite.xAmp = value
|
||||
Global.heldSprite.updateWobbleParameter("xAmp", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
|
||||
func _on_y_frq_value_changed(value):
|
||||
print("DEBUG: _on_y_frq_value_changed called with value: ", value)
|
||||
$WobbleControl/yFrqLabel.text = "y frequency: " + str(value)
|
||||
Global.heldSprite.yFrq = value
|
||||
Global.heldSprite.updateWobbleParameter("yFrq", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
func _on_y_amp_value_changed(value):
|
||||
print("DEBUG: _on_y_amp_value_changed called with value: ", value)
|
||||
$WobbleControl/yAmpLabel.text = "y amplitude: " + str(value)
|
||||
Global.heldSprite.yAmp = value
|
||||
Global.heldSprite.updateWobbleParameter("yAmp", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
|
||||
func _on_r_frq_value_changed(value):
|
||||
print("DEBUG: _on_r_frq_value_changed called with value: ", value)
|
||||
$WobbleControl/rFrqLabel.text = "rotation frequency: " + str(value)
|
||||
Global.heldSprite.rFrq = value
|
||||
Global.heldSprite.updateWobbleParameter("rFrq", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
func _on_r_amp_value_changed(value):
|
||||
print("DEBUG: _on_r_amp_value_changed called with value: ", value)
|
||||
$WobbleControl/rAmpLabel.text = "rotation amplitude: " + str(value) + "%"
|
||||
Global.heldSprite.rAmp = value
|
||||
Global.heldSprite.updateWobbleParameter("rAmp", value)
|
||||
# Refresh wobble sync control after parameter change
|
||||
if wobbleSyncControl:
|
||||
wobbleSyncControl.updateUI()
|
||||
|
||||
|
||||
func _on_r_drag_value_changed(value):
|
||||
@@ -180,6 +243,10 @@ func _on_blinking_pressed():
|
||||
|
||||
|
||||
func _on_trash_pressed():
|
||||
# Clean up wobble sync group membership before deleting
|
||||
if Global.heldSprite.wobbleSyncGroup != "" and WobbleSyncManager:
|
||||
WobbleSyncManager.onSpriteDeleted(Global.heldSprite.id)
|
||||
|
||||
Global.heldSprite.queue_free()
|
||||
Global.heldSprite = null
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[gd_scene load_steps=75 format=4 uid="uid://d3anahesvdgfh"]
|
||||
[gd_scene load_steps=76 format=4 uid="uid://d3anahesvdgfh"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://4tbpehro4x5p" path="res://ui_scenes/spriteEditMenu/border.png" id="1_b54o8"]
|
||||
[ext_resource type="Script" uid="uid://bgoaqt86bc73p" path="res://ui_scenes/spriteEditMenu/sprite_viewer.gd" id="1_hp0e3"]
|
||||
[ext_resource type="Shader" uid="uid://bfxkb7p0y73yn" path="res://ui_scenes/spriteEditMenu/sprite_viewer.gdshader" id="3_ky0lu"]
|
||||
[ext_resource type="Texture2D" uid="uid://xxhqegm7rq6n" path="res://ui_scenes/button sprites/add.png" id="3_tjnto"]
|
||||
[ext_resource type="PackedScene" uid="uid://bkwf3j2pdspxw" path="res://ui_scenes/spriteEditMenu/wobble_sync_control.tscn" id="3_wobble_sync"]
|
||||
[ext_resource type="Texture2D" uid="uid://bd68uiemrcy5v" path="res://ui_scenes/spriteEditMenu/speaking.png" id="4_shsbk"]
|
||||
[ext_resource type="Texture2D" uid="uid://doxw3dy86i2e4" path="res://ui_scenes/spriteEditMenu/blink.png" id="5_ed14x"]
|
||||
[ext_resource type="Texture2D" uid="uid://dn5hs0pfutv1l" path="res://ui_scenes/spriteEditMenu/trash.png" id="6_304pj"]
|
||||
@@ -29,7 +30,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, 1455)
|
||||
size = Vector2(245, 1550)
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hxmah"]
|
||||
shader = ExtResource("3_ky0lu")
|
||||
@@ -14285,7 +14286,7 @@ script = ExtResource("1_hp0e3")
|
||||
z_index = -2
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||
position = Vector2(122.5, 727.5)
|
||||
position = Vector2(122.5, 775)
|
||||
shape = SubResource("RectangleShape2D_21kva")
|
||||
|
||||
[node name="Border" type="Sprite2D" parent="."]
|
||||
@@ -14469,11 +14470,11 @@ scrollable = false
|
||||
|
||||
[node name="WobbleControl" type="Node2D" parent="."]
|
||||
z_index = 1
|
||||
position = Vector2(-3, 486)
|
||||
position = Vector2(-3, 491)
|
||||
|
||||
[node name="animationBox" type="Sprite2D" parent="WobbleControl"]
|
||||
position = Vector2(125, 384.5)
|
||||
scale = Vector2(1, 1.25769)
|
||||
position = Vector2(125, 431)
|
||||
scale = Vector2(1, 1.65769)
|
||||
texture = ExtResource("15_wqi8b")
|
||||
|
||||
[node name="xFrqLabel" type="Label" parent="WobbleControl"]
|
||||
@@ -14489,7 +14490,7 @@ offset_top = 263.0
|
||||
offset_right = 235.0
|
||||
offset_bottom = 283.0
|
||||
theme = SubResource("Theme_mrbyn")
|
||||
max_value = 0.1
|
||||
max_value = 1.0
|
||||
step = 0.001
|
||||
scrollable = false
|
||||
|
||||
@@ -14522,7 +14523,7 @@ offset_top = 364.0
|
||||
offset_right = 235.0
|
||||
offset_bottom = 384.0
|
||||
theme = SubResource("Theme_mrbyn")
|
||||
max_value = 0.1
|
||||
max_value = 1.0
|
||||
step = 0.001
|
||||
scrollable = false
|
||||
|
||||
@@ -14555,7 +14556,7 @@ offset_top = 465.0
|
||||
offset_right = 235.0
|
||||
offset_bottom = 485.0
|
||||
theme = SubResource("Theme_mrbyn")
|
||||
max_value = 0.1
|
||||
max_value = 1.0
|
||||
step = 0.001
|
||||
scrollable = false
|
||||
|
||||
@@ -14574,6 +14575,12 @@ offset_bottom = 528.0
|
||||
theme = SubResource("Theme_mrbyn")
|
||||
scrollable = false
|
||||
|
||||
[node name="WobbleSyncControl" parent="WobbleControl" instance=ExtResource("3_wobble_sync")]
|
||||
offset_left = 12.0
|
||||
offset_top = 559.0
|
||||
offset_right = 235.0
|
||||
offset_bottom = 624.0
|
||||
|
||||
[node name="Rotation" type="Node2D" parent="."]
|
||||
position = Vector2(-1, 224)
|
||||
|
||||
@@ -14613,7 +14620,7 @@ scrollable = false
|
||||
|
||||
[node name="RotationalLimits" type="Node2D" parent="."]
|
||||
z_index = -1
|
||||
position = Vector2(0, 435)
|
||||
position = Vector2(0, 532)
|
||||
|
||||
[node name="RotBack" type="Sprite2D" parent="RotationalLimits"]
|
||||
clip_children = 2
|
||||
@@ -14762,7 +14769,7 @@ offset_bottom = 1166.0
|
||||
theme = SubResource("Theme_mrbyn")
|
||||
|
||||
[node name="Layers" type="Node2D" parent="."]
|
||||
position = Vector2(0, 443)
|
||||
position = Vector2(0, 538)
|
||||
|
||||
[node name="Layer1" type="Sprite2D" parent="Layers"]
|
||||
position = Vector2(23, 878)
|
||||
@@ -14899,7 +14906,7 @@ position = Vector2(23, 878)
|
||||
texture = ExtResource("20_px0dt")
|
||||
|
||||
[node name="VisToggle" type="Node2D" parent="."]
|
||||
position = Vector2(11, 1404)
|
||||
position = Vector2(11, 1496)
|
||||
|
||||
[node name="setToggle" type="Button" parent="VisToggle"]
|
||||
custom_minimum_size = Vector2(0, 37.125)
|
||||
|
||||
207
ui_scenes/spriteEditMenu/wobble_sync_control.gd
Normal file
207
ui_scenes/spriteEditMenu/wobble_sync_control.gd
Normal file
@@ -0,0 +1,207 @@
|
||||
extends Control
|
||||
|
||||
## WobbleSyncControl - UI component for managing wobble sync groups
|
||||
## Designed to integrate into the sprite editor panel
|
||||
|
||||
@onready var groupDropdown = $VBoxContainer/GroupRow/GroupDropdown
|
||||
@onready var syncIndicator = $VBoxContainer/SyncIndicator
|
||||
@onready var createGroupDialog = $CreateGroupDialog
|
||||
@onready var groupNameInput = $CreateGroupDialog/VBoxContainer/LineEdit
|
||||
|
||||
var currentSprite = null
|
||||
var updating_dropdown = false # Flag to prevent recursive calls
|
||||
|
||||
signal group_changed(sprite_id: int, group_name: String)
|
||||
|
||||
func _ready():
|
||||
# Wait for autoload to be ready
|
||||
await get_tree().process_frame
|
||||
|
||||
# Connect UI signals - no add button to connect
|
||||
groupDropdown.item_selected.connect(_on_group_dropdown_selected)
|
||||
createGroupDialog.confirmed.connect(_on_create_group_confirmed)
|
||||
createGroupDialog.canceled.connect(_on_create_group_cancelled)
|
||||
|
||||
# Connect to wobble sync manager signals
|
||||
if WobbleSyncManager:
|
||||
WobbleSyncManager.group_created.connect(_on_group_created)
|
||||
WobbleSyncManager.group_deleted.connect(_on_group_deleted)
|
||||
|
||||
# Setup create group dialog
|
||||
createGroupDialog.title = "Create Wobble Sync Group"
|
||||
createGroupDialog.size = Vector2(300, 150)
|
||||
createGroupDialog.unresizable = false
|
||||
createGroupDialog.transient = true # Prevent click-through
|
||||
createGroupDialog.exclusive = true # Make modal
|
||||
createGroupDialog.popup_window = false # Keep as embedded dialog
|
||||
createGroupDialog.always_on_top = true
|
||||
|
||||
updateUI()
|
||||
|
||||
## Update the UI based on current sprite selection
|
||||
func updateUI():
|
||||
updateGroupDropdown()
|
||||
updateSyncIndicator()
|
||||
|
||||
## Update the group dropdown with available options
|
||||
func updateGroupDropdown():
|
||||
updating_dropdown = true # Prevent recursive calls
|
||||
|
||||
groupDropdown.clear()
|
||||
|
||||
# Add "None" option
|
||||
groupDropdown.add_item("None")
|
||||
|
||||
# Add existing groups
|
||||
if WobbleSyncManager:
|
||||
var groups = WobbleSyncManager.getGroupNames()
|
||||
print("DEBUG: updateGroupDropdown - available groups: ", groups)
|
||||
for group_name in groups:
|
||||
groupDropdown.add_item(group_name)
|
||||
else:
|
||||
print("DEBUG: updateGroupDropdown - WobbleSyncManager not available")
|
||||
|
||||
# Add "Create New..." option
|
||||
groupDropdown.add_separator()
|
||||
groupDropdown.add_item("Create New...")
|
||||
|
||||
# Select current group if sprite is synced
|
||||
if currentSprite != null and currentSprite.wobbleSyncGroup != "":
|
||||
print("DEBUG: updateGroupDropdown - sprite has group '", currentSprite.wobbleSyncGroup, "'")
|
||||
var group_index = -1
|
||||
for i in range(groupDropdown.get_item_count()):
|
||||
if groupDropdown.get_item_text(i) == currentSprite.wobbleSyncGroup:
|
||||
group_index = i
|
||||
break
|
||||
|
||||
if group_index != -1:
|
||||
print("DEBUG: updateGroupDropdown - selecting group at index ", group_index)
|
||||
groupDropdown.selected = group_index
|
||||
else:
|
||||
print("DEBUG: updateGroupDropdown - group '", currentSprite.wobbleSyncGroup, "' not found in dropdown")
|
||||
groupDropdown.selected = 0 # Select "None"
|
||||
else:
|
||||
print("DEBUG: updateGroupDropdown - sprite has no group, selecting 'None'")
|
||||
groupDropdown.selected = 0 # Select "None"
|
||||
|
||||
updating_dropdown = false
|
||||
|
||||
## Update the sync indicator
|
||||
func updateSyncIndicator():
|
||||
if currentSprite == null:
|
||||
syncIndicator.visible = false
|
||||
return
|
||||
|
||||
if currentSprite.isSynced():
|
||||
syncIndicator.visible = true
|
||||
syncIndicator.text = "⚡ Synced to \"" + currentSprite.wobbleSyncGroup + "\""
|
||||
else:
|
||||
syncIndicator.visible = false
|
||||
|
||||
## Set the current sprite to manage
|
||||
func setSprite(sprite):
|
||||
print("DEBUG: WobbleSyncControl.setSprite called with sprite ID: ", sprite.id if sprite else "null")
|
||||
currentSprite = sprite
|
||||
if currentSprite:
|
||||
print("DEBUG: Current sprite wobbleSyncGroup: '", currentSprite.wobbleSyncGroup, "'")
|
||||
print("DEBUG: Current sprite isSynced(): ", currentSprite.isSynced())
|
||||
updateUI()
|
||||
|
||||
## Get available groups for the dropdown (excluding "None" and "Create New...")
|
||||
func getAvailableGroups() -> Array:
|
||||
var groups = []
|
||||
for i in range(1, groupDropdown.get_item_count() - 2): # Skip "None" and "Create New..."
|
||||
groups.append(groupDropdown.get_item_text(i))
|
||||
return groups
|
||||
|
||||
## Handle group dropdown selection
|
||||
func _on_group_dropdown_selected(index: int):
|
||||
if currentSprite == null or updating_dropdown:
|
||||
return
|
||||
|
||||
var selected_text = groupDropdown.get_item_text(index)
|
||||
print("DEBUG: Dropdown selected: '", selected_text, "' at index ", index)
|
||||
|
||||
match selected_text:
|
||||
"None":
|
||||
# Remove sprite from any group
|
||||
if currentSprite.wobbleSyncGroup != "" and WobbleSyncManager:
|
||||
print("DEBUG: Removing sprite ID ", currentSprite.id, " from group '", currentSprite.wobbleSyncGroup, "'")
|
||||
WobbleSyncManager.removeSpriteFromAllGroups(currentSprite.id)
|
||||
Global.pushUpdate("Removed sprite from wobble sync group")
|
||||
|
||||
"Create New...":
|
||||
print("DEBUG: User selected 'Create New...' from dropdown")
|
||||
# Show create group dialog
|
||||
groupNameInput.text = ""
|
||||
groupNameInput.placeholder_text = "Enter group name..."
|
||||
createGroupDialog.popup_centered_clamped(Vector2i(300, 150))
|
||||
groupNameInput.grab_focus()
|
||||
# Reset dropdown to current selection
|
||||
updateGroupDropdown()
|
||||
|
||||
_:
|
||||
# Join selected group
|
||||
if WobbleSyncManager and WobbleSyncManager.hasGroup(selected_text):
|
||||
print("DEBUG: Adding sprite ID ", currentSprite.id, " to group '", selected_text, "'")
|
||||
WobbleSyncManager.addSpriteToGroup(currentSprite.id, selected_text)
|
||||
# Refresh sprite editor to show updated wobble values
|
||||
if Global.spriteEdit:
|
||||
Global.spriteEdit.setImage()
|
||||
else:
|
||||
print("DEBUG: Group '", selected_text, "' not found or WobbleSyncManager not available")
|
||||
|
||||
updateSyncIndicator()
|
||||
|
||||
## Handle create group dialog confirmation
|
||||
func _on_create_group_confirmed():
|
||||
var group_name = groupNameInput.text.strip_edges()
|
||||
print("DEBUG: Create group confirmed with name: '", group_name, "'")
|
||||
|
||||
if group_name == "":
|
||||
print("DEBUG: Group name is empty")
|
||||
Global.pushUpdate("Group name cannot be empty")
|
||||
return
|
||||
|
||||
if WobbleSyncManager and WobbleSyncManager.hasGroup(group_name):
|
||||
print("DEBUG: Group '", group_name, "' already exists")
|
||||
Global.pushUpdate("Group \"" + group_name + "\" already exists")
|
||||
return
|
||||
|
||||
# Create group with current sprite
|
||||
if currentSprite != null and WobbleSyncManager:
|
||||
print("DEBUG: Creating group '", group_name, "' with sprite ID ", currentSprite.id)
|
||||
if WobbleSyncManager.createGroup(group_name, currentSprite.id):
|
||||
print("DEBUG: Group created successfully")
|
||||
createGroupDialog.hide()
|
||||
updateUI()
|
||||
# Refresh sprite editor to show sync status
|
||||
if Global.spriteEdit:
|
||||
Global.spriteEdit.setImage()
|
||||
else:
|
||||
print("DEBUG: Failed to create group")
|
||||
else:
|
||||
print("DEBUG: No current sprite to add to group")
|
||||
|
||||
## Handle create group dialog cancellation
|
||||
func _on_create_group_cancelled():
|
||||
createGroupDialog.hide()
|
||||
updateGroupDropdown() # Reset dropdown to current selection
|
||||
|
||||
## Handle group creation signal from manager
|
||||
func _on_group_created(group_name: String):
|
||||
updateGroupDropdown()
|
||||
|
||||
## Handle group deletion signal from manager
|
||||
func _on_group_deleted(group_name: String):
|
||||
updateGroupDropdown()
|
||||
updateSyncIndicator()
|
||||
|
||||
## Check if current sprite can have wobble syncing applied
|
||||
func canSync() -> bool:
|
||||
return currentSprite != null
|
||||
|
||||
## Force refresh the UI - useful after loading saves
|
||||
func forceRefresh():
|
||||
print("DEBUG: WobbleSyncControl.forceRefresh called")
|
||||
updateUI()
|
||||
1
ui_scenes/spriteEditMenu/wobble_sync_control.gd.uid
Normal file
1
ui_scenes/spriteEditMenu/wobble_sync_control.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ykov43vxml0k
|
||||
59
ui_scenes/spriteEditMenu/wobble_sync_control.tscn
Normal file
59
ui_scenes/spriteEditMenu/wobble_sync_control.tscn
Normal file
@@ -0,0 +1,59 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bkwf3j2pdspxw"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ykov43vxml0k" path="res://ui_scenes/spriteEditMenu/wobble_sync_control.gd" id="1_k8h4v"]
|
||||
|
||||
[node name="WobbleSyncControl" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_k8h4v")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="GroupRow" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="GroupLabel" type="Label" parent="VBoxContainer/GroupRow"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Group:"
|
||||
|
||||
[node name="GroupDropdown" type="OptionButton" parent="VBoxContainer/GroupRow"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="SyncIndicator" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "⚡ Synced to \"Group Name\""
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="CreateGroupDialog" type="ConfirmationDialog" parent="."]
|
||||
process_mode = 3
|
||||
title = "Create Wobble Sync Group"
|
||||
size = Vector2i(300, 150)
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="CreateGroupDialog"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 8.0
|
||||
offset_top = 8.0
|
||||
offset_right = -8.0
|
||||
offset_bottom = -49.0
|
||||
|
||||
[node name="Label" type="Label" parent="CreateGroupDialog/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Enter name for new wobble sync group:"
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="CreateGroupDialog/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
placeholder_text = "Group name..."
|
||||
Reference in New Issue
Block a user