mirror of
https://github.com/litruv/PNGTuber-Plus.git
synced 2026-07-24 10:36:01 +10:00
Compare commits
4 Commits
v2025.07.2
...
v2025.07.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 95476cfd57 | |||
| 722fed9b94 | |||
| e8620611df | |||
| 85a208a729 |
@@ -15,7 +15,7 @@ Added a proper opacity slider for sprites, with an "affect children" toggle. Cli
|
||||

|
||||
|
||||
|
||||
### <EFBFBD> Blend Modes
|
||||
### 🎨 Blend Modes
|
||||
|
||||
Photoshop-style blend modes for sprites! Choose from Normal, Multiply, Screen, Overlay, Soft Light, Hard Light, Color Dodge, Color Burn, Darken, Lighten, Add, and Subtract. Perfect for lighting effects, shadows, or artistic styling.
|
||||
|
||||
@@ -23,7 +23,7 @@ Photoshop-style blend modes for sprites! Choose from Normal, Multiply, Screen, O
|
||||
* Works alongside opacity controls
|
||||
|
||||
|
||||
### <EFBFBD>🌀 Rotation Wobble
|
||||
### 🌀 Rotation Wobble
|
||||
|
||||
Sprites can now do a subtle (or chaotic) rotational wobble. Frequency + amplitude sliders included.
|
||||
|
||||
|
||||
Binary file not shown.
@@ -280,7 +280,6 @@ func blinking():
|
||||
blinkTick = -12
|
||||
|
||||
func epicFail(err):
|
||||
print(fail)
|
||||
if fail == null:
|
||||
return
|
||||
|
||||
|
||||
@@ -12,10 +12,8 @@ signal sprite_joined_group(sprite_id: int, group_name: String)
|
||||
signal sprite_left_group(sprite_id: int, group_name: String)
|
||||
|
||||
func _ready():
|
||||
print("DEBUG: WobbleSyncManager._ready() called")
|
||||
print("DEBUG: WobbleSyncManager autoload initialized successfully")
|
||||
print("DEBUG: Initial syncGroups: ", syncGroups)
|
||||
print("DEBUG: Initial spriteGroupMembership: ", spriteGroupMembership)
|
||||
# Manager initialization complete
|
||||
pass
|
||||
|
||||
class WobbleSyncGroup:
|
||||
var name: String
|
||||
@@ -32,8 +30,6 @@ class WobbleSyncGroup:
|
||||
|
||||
## Set wobble parameters for the entire group
|
||||
func setWobbleParameters(x_frq: float, x_amp: float, y_frq: float, y_amp: float, r_frq: float, r_amp: float, manager_ref):
|
||||
print("DEBUG: WobbleSyncGroup.setWobbleParameters called for group '", name, "' with ", memberSprites.size(), " members")
|
||||
print("DEBUG: Member sprite IDs: ", memberSprites)
|
||||
xFrq = x_frq
|
||||
xAmp = x_amp
|
||||
yFrq = y_frq
|
||||
@@ -43,13 +39,10 @@ class WobbleSyncGroup:
|
||||
|
||||
# Update all member sprites using the manager reference
|
||||
var sprites = manager_ref.get_tree().get_nodes_in_group("saved")
|
||||
print("DEBUG: Found ", sprites.size(), " total sprites in 'saved' group")
|
||||
|
||||
var updated_count = 0
|
||||
for sprite in sprites:
|
||||
print("DEBUG: Checking sprite ID ", sprite.id, " (type: ", typeof(sprite.id), ") against member list")
|
||||
if sprite.id in memberSprites:
|
||||
print("DEBUG: Updating sprite ID ", sprite.id, " with new wobble values (no scaling - values stored as-is)")
|
||||
# Preserve the sprite's group membership
|
||||
var current_group = sprite.wobbleSyncGroup
|
||||
sprite.xFrq = xFrq
|
||||
@@ -61,19 +54,13 @@ class WobbleSyncGroup:
|
||||
# Restore group membership in case it got cleared
|
||||
sprite.wobbleSyncGroup = current_group
|
||||
updated_count += 1
|
||||
else:
|
||||
print("DEBUG: Sprite ID ", sprite.id, " not in member list")
|
||||
|
||||
print("DEBUG: Updated ", updated_count, " sprites in group '", name, "'")
|
||||
|
||||
## Add sprite to this group
|
||||
func addSprite(sprite_id): # Remove type constraint to handle float IDs
|
||||
print("DEBUG: WobbleSyncGroup.addSprite called with sprite_id: ", sprite_id, " (type: ", typeof(sprite_id), ")")
|
||||
if sprite_id not in memberSprites:
|
||||
memberSprites.append(sprite_id)
|
||||
print("DEBUG: Added sprite to memberSprites. Current members: ", memberSprites)
|
||||
else:
|
||||
print("DEBUG: Sprite already in memberSprites")
|
||||
pass # Sprite already in group
|
||||
|
||||
## Remove sprite from this group
|
||||
func removeSprite(sprite_id): # Remove type constraint
|
||||
@@ -144,10 +131,8 @@ func deleteGroup(group_name: String):
|
||||
|
||||
## Add sprite to a group
|
||||
func addSpriteToGroup(sprite_id, group_name: String) -> bool: # Remove type constraint
|
||||
print("DEBUG: addSpriteToGroup called with sprite_id: ", sprite_id, " (type: ", typeof(sprite_id), "), group: '", group_name, "'")
|
||||
|
||||
if not syncGroups.has(group_name):
|
||||
print("DEBUG: Group '", group_name, "' not found")
|
||||
return false
|
||||
|
||||
# Remove sprite from any existing group first
|
||||
@@ -156,12 +141,10 @@ func addSpriteToGroup(sprite_id, group_name: String) -> bool: # Remove type con
|
||||
var group = syncGroups[group_name]
|
||||
group.addSprite(sprite_id)
|
||||
spriteGroupMembership[sprite_id] = group_name
|
||||
print("DEBUG: Added sprite ", sprite_id, " to group '", group_name, "'. Group now has ", group.memberSprites.size(), " members")
|
||||
|
||||
# Sync the sprite's wobble parameters to the group
|
||||
var sprite = getSpriteById(sprite_id)
|
||||
if sprite:
|
||||
print("DEBUG: Found sprite object, syncing wobble parameters to group values")
|
||||
sprite.wobbleSyncGroup = group_name
|
||||
sprite.xFrq = group.xFrq
|
||||
sprite.xAmp = group.xAmp
|
||||
@@ -176,24 +159,19 @@ func addSpriteToGroup(sprite_id, group_name: String) -> bool: # Remove type con
|
||||
|
||||
## Remove sprite from a specific group
|
||||
func removeSpriteFromGroup(sprite_id, group_name: String): # Remove type constraint
|
||||
print("DEBUG: removeSpriteFromGroup called for sprite ID: ", sprite_id, " (type: ", typeof(sprite_id), "), group: '", group_name, "'")
|
||||
if not syncGroups.has(group_name):
|
||||
print("DEBUG: Group '", group_name, "' not found")
|
||||
return
|
||||
|
||||
var group = syncGroups[group_name]
|
||||
print("DEBUG: Group before removal has ", group.memberSprites.size(), " members: ", group.memberSprites)
|
||||
group.removeSprite(sprite_id)
|
||||
spriteGroupMembership.erase(sprite_id)
|
||||
print("DEBUG: Group after removal has ", group.memberSprites.size(), " members: ", group.memberSprites)
|
||||
|
||||
# Clear the sprite's sync group reference
|
||||
var sprite = getSpriteById(sprite_id)
|
||||
if sprite:
|
||||
print("DEBUG: Clearing sprite's wobbleSyncGroup property")
|
||||
sprite.wobbleSyncGroup = ""
|
||||
else:
|
||||
print("DEBUG: Could not find sprite object for ID: ", sprite_id)
|
||||
pass # Sprite not found
|
||||
|
||||
sprite_left_group.emit(sprite_id, group_name)
|
||||
|
||||
@@ -205,27 +183,19 @@ func removeSpriteFromGroup(sprite_id, group_name: String): # Remove type constr
|
||||
|
||||
## Remove sprite from all groups
|
||||
func removeSpriteFromAllGroups(sprite_id): # Remove type constraint
|
||||
print("DEBUG: removeSpriteFromAllGroups called for sprite ID: ", sprite_id)
|
||||
if spriteGroupMembership.has(sprite_id):
|
||||
var group_name = spriteGroupMembership[sprite_id]
|
||||
print("DEBUG: Found sprite in group '", group_name, "', removing...")
|
||||
removeSpriteFromGroup(sprite_id, group_name)
|
||||
else:
|
||||
print("DEBUG: Sprite not found in any group membership")
|
||||
pass # Sprite not in any group
|
||||
|
||||
## Update wobble parameters for a group
|
||||
func updateGroupWobble(group_name: String, x_frq: float, x_amp: float, y_frq: float, y_amp: float, r_frq: float, r_amp: float):
|
||||
print("DEBUG: updateGroupWobble called for group '", group_name, "' with values - xFrq:", x_frq, " xAmp:", x_amp, " yFrq:", y_frq, " yAmp:", y_amp, " rFrq:", r_frq, " rAmp:", r_amp)
|
||||
|
||||
if not syncGroups.has(group_name):
|
||||
print("DEBUG: Group '", group_name, "' not found in syncGroups!")
|
||||
print("DEBUG: Available groups: ", syncGroups.keys())
|
||||
print("DEBUG: This suggests the avatar's wobble sync groups were never loaded from the save file!")
|
||||
print("DEBUG: Either the save file doesn't contain wobbleSyncGroups, or the loading process didn't run.")
|
||||
return
|
||||
|
||||
var group = syncGroups[group_name]
|
||||
print("DEBUG: Found group, calling setWobbleParameters on group with ", group.memberSprites.size(), " members")
|
||||
group.setWobbleParameters(x_frq, x_amp, y_frq, y_amp, r_frq, r_amp, self)
|
||||
|
||||
## Get sprite's current group name
|
||||
@@ -234,14 +204,10 @@ func getSpriteGroupName(sprite_id: int) -> String:
|
||||
|
||||
## Get all group names
|
||||
func getGroupNames() -> Array:
|
||||
print("DEBUG: getGroupNames called. syncGroups has ", syncGroups.size(), " groups: ", syncGroups.keys())
|
||||
print("DEBUG: getGroupNames - syncGroups reference: ", syncGroups)
|
||||
print("DEBUG: getGroupNames - self reference: ", self)
|
||||
return syncGroups.keys()
|
||||
|
||||
## Test function to manually load wobble sync groups
|
||||
func testManualLoad():
|
||||
print("DEBUG: testManualLoad called - creating test data...")
|
||||
var test_data = {
|
||||
"ears": {
|
||||
"name": "ears",
|
||||
@@ -254,9 +220,7 @@ func testManualLoad():
|
||||
"memberSprites": [3291286625.0]
|
||||
}
|
||||
}
|
||||
print("DEBUG: Calling loadSaveData with test data...")
|
||||
await loadSaveData(test_data)
|
||||
print("DEBUG: testManualLoad completed. syncGroups now has: ", syncGroups.size(), " groups")
|
||||
|
||||
## Check if a group exists
|
||||
func hasGroup(group_name: String) -> bool:
|
||||
@@ -305,91 +269,52 @@ func getSaveData() -> Dictionary:
|
||||
|
||||
## Load save data for all groups
|
||||
func loadSaveData(save_data: Dictionary):
|
||||
print("DEBUG: ========================")
|
||||
print("DEBUG: WobbleSyncManager.loadSaveData called with save_data: ", save_data)
|
||||
print("DEBUG: save_data type: ", typeof(save_data))
|
||||
print("DEBUG: save_data.keys(): ", save_data.keys())
|
||||
print("DEBUG: save_data.size(): ", save_data.size())
|
||||
print("DEBUG: self reference: ", self)
|
||||
print("DEBUG: syncGroups before clear: ", syncGroups)
|
||||
|
||||
# Check if save_data is valid
|
||||
if save_data == null or typeof(save_data) != TYPE_DICTIONARY:
|
||||
print("DEBUG: ERROR - Invalid save_data provided")
|
||||
return
|
||||
|
||||
if save_data.size() == 0:
|
||||
print("DEBUG: WARNING - Empty save_data provided")
|
||||
return
|
||||
|
||||
# Clear existing groups
|
||||
print("DEBUG: Clearing existing syncGroups (had ", syncGroups.size(), " groups)")
|
||||
syncGroups.clear()
|
||||
spriteGroupMembership.clear()
|
||||
print("DEBUG: Cleared existing data. syncGroups now has ", syncGroups.size(), " groups")
|
||||
|
||||
# Load groups from save data
|
||||
var loaded_groups = 0
|
||||
print("DEBUG: Starting group loading loop...")
|
||||
for group_name in save_data.keys():
|
||||
print("DEBUG: ---- Processing group '", group_name, "' (attempt ", loaded_groups + 1, ") ----")
|
||||
var group_data = save_data[group_name]
|
||||
print("DEBUG: Group data type: ", typeof(group_data))
|
||||
print("DEBUG: Group data: ", group_data)
|
||||
|
||||
if typeof(group_data) == TYPE_DICTIONARY:
|
||||
print("DEBUG: Creating WobbleSyncGroup instance...")
|
||||
var group = WobbleSyncGroup.new(group_name)
|
||||
print("DEBUG: Created new WobbleSyncGroup instance for '", group_name, "'")
|
||||
print("DEBUG: Calling fromSaveData...")
|
||||
group.fromSaveData(group_data)
|
||||
print("DEBUG: Called fromSaveData on group '", group_name, "'")
|
||||
print("DEBUG: Adding to syncGroups dictionary...")
|
||||
syncGroups[group_name] = group
|
||||
loaded_groups += 1
|
||||
print("DEBUG: Added group '", group_name, "' to syncGroups. Total groups now: ", syncGroups.size())
|
||||
print("DEBUG: syncGroups.keys() now: ", syncGroups.keys())
|
||||
print("DEBUG: Group memberSprites: ", group.memberSprites)
|
||||
|
||||
# Update sprite group membership
|
||||
print("DEBUG: Updating sprite group membership...")
|
||||
for sprite_id in group.memberSprites:
|
||||
spriteGroupMembership[sprite_id] = group_name
|
||||
print("DEBUG: Added sprite ", sprite_id, " to spriteGroupMembership for group '", group_name, "'")
|
||||
print("DEBUG: ---- Finished processing group '", group_name, "' ----")
|
||||
else:
|
||||
print("DEBUG: ERROR - Group data for '", group_name, "' is not a Dictionary, skipping")
|
||||
pass # Invalid group data
|
||||
|
||||
print("DEBUG: ========================")
|
||||
print("DEBUG: GROUP LOADING COMPLETE")
|
||||
print("DEBUG: Loaded ", loaded_groups, " groups total")
|
||||
print("DEBUG: Final syncGroups after loading: ", syncGroups.keys())
|
||||
print("DEBUG: Final syncGroups size: ", syncGroups.size())
|
||||
print("DEBUG: Final syncGroups contents: ", syncGroups)
|
||||
print("DEBUG: Final spriteGroupMembership: ", spriteGroupMembership)
|
||||
print("DEBUG: ========================")
|
||||
|
||||
# If no groups were loaded, clear any orphaned group references on sprites
|
||||
if syncGroups.size() == 0:
|
||||
print("DEBUG: No groups loaded, clearing orphaned sprite group references")
|
||||
var sprites = get_tree().get_nodes_in_group("saved")
|
||||
for sprite in sprites:
|
||||
if sprite.wobbleSyncGroup != "":
|
||||
print("DEBUG: Clearing orphaned group reference '", sprite.wobbleSyncGroup, "' from sprite ID ", sprite.id)
|
||||
sprite.wobbleSyncGroup = ""
|
||||
else:
|
||||
print("DEBUG: Groups loaded successfully, syncing sprite parameters...")
|
||||
# Apply wobble parameters to sprites with better timing
|
||||
await get_tree().process_frame # Wait for sprites to be loaded
|
||||
await get_tree().process_frame # Extra frame to ensure everything is ready
|
||||
|
||||
for group_name in syncGroups.keys():
|
||||
var group = syncGroups[group_name]
|
||||
print("DEBUG: Syncing parameters for group '", group_name, "' with ", group.memberSprites.size(), " members")
|
||||
for sprite_id in group.memberSprites:
|
||||
var sprite = getSpriteById(sprite_id)
|
||||
if sprite:
|
||||
print("DEBUG: Syncing sprite ID ", sprite_id, " to group '", group_name, "'")
|
||||
sprite.wobbleSyncGroup = group_name
|
||||
sprite.xFrq = group.xFrq
|
||||
sprite.xAmp = group.xAmp
|
||||
@@ -403,50 +328,9 @@ func loadSaveData(save_data: Dictionary):
|
||||
if sprite.has_method("updateShaderOpacity"):
|
||||
sprite.updateShaderOpacity()
|
||||
else:
|
||||
print("DEBUG: ERROR - Could not find sprite with ID ", sprite_id)
|
||||
pass # Sprite not found
|
||||
|
||||
print("DEBUG: ========================")
|
||||
print("DEBUG: loadSaveData FUNCTION COMPLETE")
|
||||
print("DEBUG: Final verification - syncGroups has ", syncGroups.size(), " groups: ", syncGroups.keys())
|
||||
print("DEBUG: ========================")
|
||||
|
||||
## Called when a sprite is deleted to clean up references
|
||||
func onSpriteDeleted(sprite_id): # Remove type constraint
|
||||
removeSpriteFromAllGroups(sprite_id)
|
||||
|
||||
## Debug function to check data consistency
|
||||
func checkDataConsistency():
|
||||
print("=== WOBBLE SYNC DATA CONSISTENCY CHECK ===")
|
||||
|
||||
# Check each group's member sprites
|
||||
for group_name in syncGroups.keys():
|
||||
var group = syncGroups[group_name]
|
||||
print("Group '", group_name, "' has ", group.memberSprites.size(), " members: ", group.memberSprites)
|
||||
|
||||
for sprite_id in group.memberSprites:
|
||||
# Check if sprite exists
|
||||
var sprite = getSpriteById(sprite_id)
|
||||
if sprite == null:
|
||||
print(" ERROR: Sprite ID ", sprite_id, " in group but sprite object not found!")
|
||||
else:
|
||||
# Check if sprite's wobbleSyncGroup matches
|
||||
if sprite.wobbleSyncGroup != group_name:
|
||||
print(" ERROR: Sprite ID ", sprite_id, " in group '", group_name, "' but sprite.wobbleSyncGroup = '", sprite.wobbleSyncGroup, "'")
|
||||
else:
|
||||
print(" OK: Sprite ID ", sprite_id, " consistent")
|
||||
|
||||
# Check if membership mapping is correct
|
||||
if not spriteGroupMembership.has(sprite_id) or spriteGroupMembership[sprite_id] != group_name:
|
||||
print(" ERROR: Sprite ID ", sprite_id, " in group but spriteGroupMembership is wrong!")
|
||||
|
||||
# Check membership mapping for orphaned entries
|
||||
for sprite_id in spriteGroupMembership.keys():
|
||||
var group_name = spriteGroupMembership[sprite_id]
|
||||
if not syncGroups.has(group_name):
|
||||
print("ERROR: Sprite ID ", sprite_id, " mapped to non-existent group '", group_name, "'")
|
||||
else:
|
||||
var group = syncGroups[group_name]
|
||||
if sprite_id not in group.memberSprites:
|
||||
print("ERROR: Sprite ID ", sprite_id, " mapped to group '", group_name, "' but not in group's member list")
|
||||
|
||||
print("=== END CONSISTENCY CHECK ===")
|
||||
|
||||
Binary file not shown.
@@ -75,6 +75,7 @@ func _ready():
|
||||
Global.main = self
|
||||
Global.fail = $Failed
|
||||
|
||||
var newUser = Saving.settings["newUser"]
|
||||
|
||||
Global.connect("startSpeaking",onSpeak)
|
||||
|
||||
@@ -83,22 +84,14 @@ func _ready():
|
||||
if streamdeck_node != null:
|
||||
streamdeck_node.on_key_down.connect(changeCostumeStreamDeck)
|
||||
|
||||
if Saving.settings["newUser"]:
|
||||
print("DEBUG: MAIN._ready() - New user detected, loading default avatar")
|
||||
_on_load_dialog_file_selected("default")
|
||||
Saving.settings["newUser"] = false
|
||||
saveLoaded = true
|
||||
if newUser:
|
||||
loadDefaultAvatar()
|
||||
else:
|
||||
print("DEBUG: MAIN._ready() - Existing user, loading last avatar")
|
||||
var lastAvatar = Saving.settings["lastAvatar"]
|
||||
print("DEBUG: lastAvatar setting: ", lastAvatar, " (type: ", typeof(lastAvatar), ")")
|
||||
# Ensure lastAvatar is a string, not a Dictionary
|
||||
if typeof(lastAvatar) == TYPE_STRING and lastAvatar != "":
|
||||
print("DEBUG: Loading avatar from: ", lastAvatar)
|
||||
_on_load_dialog_file_selected(lastAvatar)
|
||||
var lastAvatar = Saving.settings.get("lastAvatar", "")
|
||||
if lastAvatar != null and lastAvatar != "" and typeof(lastAvatar) == TYPE_STRING and FileAccess.file_exists(lastAvatar):
|
||||
loadAvatar(lastAvatar)
|
||||
else:
|
||||
print("WARNING: lastAvatar setting is invalid, loading default instead")
|
||||
_on_load_dialog_file_selected("default")
|
||||
loadDefaultAvatar()
|
||||
|
||||
$ControlPanel/volumeSlider.value = Saving.settings["volume"]
|
||||
$ControlPanel/sensitiveSlider.value = Saving.settings["sense"]
|
||||
@@ -425,54 +418,35 @@ func _on_load_button_pressed():
|
||||
|
||||
#LOAD AVATAR
|
||||
func _on_load_dialog_file_selected(path):
|
||||
print("DEBUG: _on_load_dialog_file_selected called with path: ", path, " (type: ", typeof(path), ")")
|
||||
|
||||
# Handle case where path might be a Dictionary instead of string
|
||||
if typeof(path) == TYPE_DICTIONARY:
|
||||
print("ERROR: Expected string path but got Dictionary: ", path)
|
||||
push_error("Expected string path but got Dictionary: " + str(path))
|
||||
return
|
||||
|
||||
print("DEBUG: About to read save data from: ", path)
|
||||
var data = Saving.read_save(path)
|
||||
print("DEBUG: Save data read. Data type: ", typeof(data), ", null check: ", data == null)
|
||||
|
||||
if data == null:
|
||||
print("DEBUG: Save data is null, returning")
|
||||
return
|
||||
|
||||
print("DEBUG: Save data keys: ", data.keys() if typeof(data) == TYPE_DICTIONARY else "not a dictionary")
|
||||
print("DEBUG: Save data size: ", data.size() if typeof(data) == TYPE_DICTIONARY else "not a dictionary")
|
||||
|
||||
# Check the structure of the first few items
|
||||
if typeof(data) == TYPE_DICTIONARY:
|
||||
var count = 0
|
||||
for key in data.keys():
|
||||
if count < 3: # Just show first 3 items for debugging
|
||||
print("DEBUG: data[", key, "] = ", data[key])
|
||||
print("DEBUG: data[", key, "] type = ", typeof(data[key]))
|
||||
if typeof(data[key]) == TYPE_DICTIONARY and data[key].has("path"):
|
||||
print("DEBUG: data[", key, "][\"path\"] = ", data[key]["path"])
|
||||
else:
|
||||
print("DEBUG: data[", key, "] doesn't have 'path' key or isn't a dictionary")
|
||||
count += 1
|
||||
|
||||
origin.queue_free()
|
||||
var new = Node2D.new()
|
||||
$OriginMotion.add_child(new)
|
||||
origin = new
|
||||
|
||||
for item in data:
|
||||
print("DEBUG: Processing item: ", item, ", data type: ", typeof(data[item]))
|
||||
if typeof(data[item]) != TYPE_DICTIONARY:
|
||||
print("DEBUG: Skipping item ", item, " - not a dictionary")
|
||||
continue
|
||||
|
||||
if not data[item].has("path"):
|
||||
print("DEBUG: Skipping item ", item, " - no 'path' key. Keys: ", data[item].keys())
|
||||
continue
|
||||
|
||||
var sprite = spriteObject.instantiate()
|
||||
sprite.path = data[item]["path"]
|
||||
|
||||
# Load display name (with backward compatibility)
|
||||
if data[item].has("displayName"):
|
||||
sprite.displayName = data[item]["displayName"]
|
||||
|
||||
sprite.id = data[item]["identification"]
|
||||
sprite.parentId = data[item]["parentId"]
|
||||
|
||||
@@ -503,9 +477,9 @@ func _on_load_dialog_file_selected(path):
|
||||
|
||||
if data[item].has("costumeLayers"):
|
||||
sprite.costumeLayers = str_to_var(data[item]["costumeLayers"]).duplicate()
|
||||
if sprite.costumeLayers.size() < 8:
|
||||
for i in range(5):
|
||||
sprite.costumeLayers.append(1)
|
||||
# Ensure we have exactly 10 costume layers
|
||||
while sprite.costumeLayers.size() < 10:
|
||||
sprite.costumeLayers.append(1)
|
||||
|
||||
if data[item].has("stretchAmount"):
|
||||
sprite.stretchAmount = data[item]["stretchAmount"]
|
||||
@@ -542,23 +516,8 @@ func _on_load_dialog_file_selected(path):
|
||||
Global.spriteList.updateData()
|
||||
|
||||
# Load wobble sync groups
|
||||
print("DEBUG: About to check for wobble sync groups...")
|
||||
print("DEBUG: data type: ", typeof(data), ", data.keys(): ", data.keys() if typeof(data) == TYPE_DICTIONARY else "not a dictionary")
|
||||
print("DEBUG: data.has('wobbleSyncGroups'): ", data.has("wobbleSyncGroups"))
|
||||
print("DEBUG: WobbleSyncManager exists: ", WobbleSyncManager != null)
|
||||
if WobbleSyncManager != null:
|
||||
print("DEBUG: WobbleSyncManager type: ", typeof(WobbleSyncManager))
|
||||
|
||||
# Show save data content related to wobble sync
|
||||
if data.has("wobbleSyncGroups"):
|
||||
print("DEBUG: wobbleSyncGroups data found: ", data["wobbleSyncGroups"])
|
||||
else:
|
||||
print("DEBUG: No wobbleSyncGroups found in save data")
|
||||
|
||||
if data.has("wobbleSyncGroups") and WobbleSyncManager:
|
||||
print("DEBUG: Loading wobble sync groups. Data: ", data["wobbleSyncGroups"])
|
||||
await WobbleSyncManager.loadSaveData(data["wobbleSyncGroups"])
|
||||
print("DEBUG: Finished loading wobble sync groups")
|
||||
# Refresh wobble sync UI after groups are loaded
|
||||
if Global.spriteEdit and Global.spriteEdit.wobbleSyncControl:
|
||||
Global.spriteEdit.wobbleSyncControl.updateUI()
|
||||
@@ -568,14 +527,6 @@ func _on_load_dialog_file_selected(path):
|
||||
# Force refresh in case timing issues
|
||||
await get_tree().process_frame
|
||||
Global.spriteEdit.wobbleSyncControl.forceRefresh()
|
||||
else:
|
||||
print("DEBUG: Not loading wobble sync groups - missing data or manager")
|
||||
|
||||
# Final debug check
|
||||
if WobbleSyncManager:
|
||||
print("DEBUG: Final check - WobbleSyncManager has ", WobbleSyncManager.getGroupNames().size(), " groups: ", WobbleSyncManager.getGroupNames())
|
||||
else:
|
||||
print("DEBUG: No wobble sync groups to load. has key: ", data.has("wobbleSyncGroups"), ", WobbleSyncManager: ", WobbleSyncManager != null)
|
||||
|
||||
# Update opacity shaders for all loaded sprites after wobble sync data is applied
|
||||
await get_tree().process_frame # Wait for all sprites to be fully initialized
|
||||
@@ -587,7 +538,15 @@ func _on_load_dialog_file_selected(path):
|
||||
Global.pushUpdate("Loaded avatar at: " + path)
|
||||
|
||||
onWindowSizeChange()
|
||||
|
||||
|
||||
## Load the default avatar data
|
||||
func loadDefaultAvatar():
|
||||
_on_load_dialog_file_selected("default")
|
||||
|
||||
## Load avatar from a specific file path
|
||||
func loadAvatar(path: String):
|
||||
_on_load_dialog_file_selected(path)
|
||||
|
||||
#SAVE AVATAR
|
||||
func _on_save_dialog_file_selected(path):
|
||||
var data = {}
|
||||
@@ -599,6 +558,7 @@ func _on_save_dialog_file_selected(path):
|
||||
data[id] = {}
|
||||
data[id]["type"] = "sprite"
|
||||
data[id]["path"] = child.path
|
||||
data[id]["displayName"] = child.displayName
|
||||
data[id]["imageData"] = Marshalls.raw_to_base64(child.imageData.save_png_to_buffer())
|
||||
data[id]["identification"] = child.id
|
||||
data[id]["parentId"] = child.parentId
|
||||
@@ -758,9 +718,11 @@ func changeCostumeStreamDeck(id: String):
|
||||
"9":changeCostume(9)
|
||||
"10":changeCostume(10)
|
||||
|
||||
func changeCostume(newCostume):
|
||||
func changeCostume(newCostume, preserve_selection: bool = false):
|
||||
costume = newCostume
|
||||
Global.heldSprite = null
|
||||
# Only clear heldSprite for actual costume changes, not layer updates
|
||||
if not preserve_selection:
|
||||
Global.heldSprite = null
|
||||
var nodes = get_tree().get_nodes_in_group("saved")
|
||||
for sprite in nodes:
|
||||
if sprite.costumeLayers[newCostume-1] == 1:
|
||||
@@ -783,7 +745,7 @@ func moveSpriteMenu(delta):
|
||||
|
||||
var size = get_viewport().get_visible_rect().size
|
||||
|
||||
var windowLength = 1800
|
||||
var windowLength = 2000
|
||||
|
||||
$ViewerArrows/Arrows.position.y = size.y - 25
|
||||
|
||||
|
||||
@@ -14357,26 +14357,38 @@ offset_bottom = -51.0
|
||||
text = "Zoom : 100%"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="VersionLabels" type="Node2D" parent="ControlPanel"]
|
||||
position = Vector2(-284, 59)
|
||||
[node name="VersionLabels" type="Control" parent="ControlPanel"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -870.0
|
||||
offset_top = -107.0
|
||||
offset_right = -610.0
|
||||
offset_bottom = -7.0
|
||||
grow_vertical = 0
|
||||
|
||||
[node name="Label" type="Label" parent="ControlPanel/VersionLabels"]
|
||||
offset_left = -713.0
|
||||
offset_top = -94.0
|
||||
offset_right = -575.0
|
||||
offset_bottom = -60.0
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="ControlPanel/VersionLabels"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_top = -100.0
|
||||
offset_right = 138.0
|
||||
offset_bottom = 1.0
|
||||
grow_vertical = 0
|
||||
|
||||
[node name="Label" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "PNGTuber Plus"
|
||||
label_settings = SubResource("LabelSettings_w0f1f")
|
||||
|
||||
[node name="Label2" type="Label" parent="ControlPanel/VersionLabels"]
|
||||
offset_left = -713.0
|
||||
offset_top = -123.0
|
||||
offset_right = -575.0
|
||||
offset_bottom = -89.0
|
||||
[node name="Label2" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "kaiakairos'"
|
||||
label_settings = SubResource("LabelSettings_qg0do")
|
||||
|
||||
[node name="versionNo" type="Label" parent="ControlPanel/VersionLabels/Label2"]
|
||||
[node name="versionNo" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer/Label2"]
|
||||
layout_mode = 0
|
||||
offset_left = 104.0
|
||||
offset_top = 11.0
|
||||
@@ -14385,15 +14397,13 @@ offset_bottom = 54.0
|
||||
text = "v1.4.5"
|
||||
label_settings = SubResource("LabelSettings_xvf50")
|
||||
|
||||
[node name="Label3" type="Label" parent="ControlPanel/VersionLabels"]
|
||||
offset_left = -566.0
|
||||
offset_top = -93.0
|
||||
offset_right = -428.0
|
||||
offset_bottom = -59.0
|
||||
[node name="Label3" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Litruv Edition"
|
||||
label_settings = SubResource("LabelSettings_qg0do")
|
||||
|
||||
[node name="EditControls" type="Node2D" parent="."]
|
||||
visible = false
|
||||
z_index = 4090
|
||||
script = ExtResource("17_bf1ic")
|
||||
|
||||
|
||||
@@ -50,11 +50,6 @@ window/vsync/vsync_mode=0
|
||||
|
||||
project/assembly_name="PNGTuberPlus"
|
||||
|
||||
[editor]
|
||||
|
||||
version_control/plugin_name=""
|
||||
version_control/autoload_on_startup=false
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/godot-streamdeck-addon/plugin.cfg")
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
extends Node
|
||||
|
||||
## Test script for wobble sync groups - run this to verify the system is working
|
||||
|
||||
func _ready():
|
||||
# Wait a frame for everything to initialize
|
||||
await get_tree().process_frame
|
||||
|
||||
print("=== Wobble Sync Groups Test ===")
|
||||
|
||||
# Test creating a group
|
||||
var success = WobbleSyncManager.createGroup("TestGroup")
|
||||
print("Create group 'TestGroup': ", success)
|
||||
|
||||
# Test getting group names
|
||||
var groups = WobbleSyncManager.getGroupNames()
|
||||
print("Available groups: ", groups)
|
||||
|
||||
# Test group existence
|
||||
print("Group 'TestGroup' exists: ", WobbleSyncManager.hasGroup("TestGroup"))
|
||||
print("Group 'NonExistent' exists: ", WobbleSyncManager.hasGroup("NonExistent"))
|
||||
|
||||
# Clean up test group
|
||||
WobbleSyncManager.deleteGroup("TestGroup")
|
||||
print("Deleted test group")
|
||||
|
||||
groups = WobbleSyncManager.getGroupNames()
|
||||
print("Groups after deletion: ", groups)
|
||||
|
||||
print("=== Test Complete ===")
|
||||
@@ -1 +0,0 @@
|
||||
uid://ca66ai4v1k0sw
|
||||
BIN
ui_scenes/button sprites/checkmark.png
Normal file
BIN
ui_scenes/button sprites/checkmark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
34
ui_scenes/button sprites/checkmark.png.import
Normal file
34
ui_scenes/button sprites/checkmark.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://41u8egcau00i"
|
||||
path="res://.godot/imported/checkmark.png-7bf604eba3017c173b17bad2b166951a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://ui_scenes/button sprites/checkmark.png"
|
||||
dest_files=["res://.godot/imported/checkmark.png-7bf604eba3017c173b17bad2b166951a.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@@ -1,82 +0,0 @@
|
||||
## Example implementation showing how to replace legacy wobble controls
|
||||
## with the new WobbleControlPanel component
|
||||
extends Node2D
|
||||
|
||||
## This demonstrates the integration approach for the sprite viewer
|
||||
|
||||
## Legacy slider references (to be replaced)
|
||||
@onready var legacy_wobble_control = $LegacyWobbleControl
|
||||
|
||||
## New component system
|
||||
@onready var wobble_panel: WobbleControlPanel = $WobbleControlPanel
|
||||
var slider_manager: SliderManager
|
||||
|
||||
func _ready():
|
||||
# Initialize slider management
|
||||
slider_manager = SliderManager.new(self)
|
||||
|
||||
# Set up the wobble panel
|
||||
if wobble_panel:
|
||||
# The panel will automatically configure its sliders
|
||||
print("WobbleControlPanel initialized")
|
||||
|
||||
# Hide legacy controls when using new system
|
||||
if legacy_wobble_control:
|
||||
legacy_wobble_control.visible = false
|
||||
|
||||
## Updated setImage function using new components
|
||||
func setImage_new_system():
|
||||
if Global.heldSprite == null:
|
||||
return
|
||||
|
||||
print("Setting image with new component system")
|
||||
|
||||
# Update wobble panel with current sprite
|
||||
if wobble_panel:
|
||||
wobble_panel.set_target_sprite(Global.heldSprite)
|
||||
wobble_panel.update_from_sprite()
|
||||
|
||||
# Update sync feedback
|
||||
updateWobbleControlStates_new_system()
|
||||
|
||||
## Updated wobble control states using new system
|
||||
func updateWobbleControlStates_new_system():
|
||||
if Global.heldSprite == null:
|
||||
return
|
||||
|
||||
if wobble_panel:
|
||||
wobble_panel.update_sync_feedback()
|
||||
|
||||
## Migration helper - gradually replace sections
|
||||
func migrate_to_new_system():
|
||||
print("Migrating wobble controls to new component system...")
|
||||
|
||||
# Step 1: Hide old controls
|
||||
if has_node("WobbleControl"):
|
||||
$WobbleControl.visible = false
|
||||
|
||||
# Step 2: Show new panel
|
||||
if wobble_panel:
|
||||
wobble_panel.visible = true
|
||||
|
||||
# Step 3: Update with current sprite
|
||||
if Global.heldSprite:
|
||||
setImage_new_system()
|
||||
|
||||
print("Migration complete!")
|
||||
|
||||
## Demonstration of component benefits
|
||||
func demonstrate_consistency():
|
||||
print("=== Component System Benefits ===")
|
||||
|
||||
if wobble_panel:
|
||||
print("All wobble sliders have consistent:")
|
||||
print("- Visual styling")
|
||||
print("- Value formatting")
|
||||
print("- Label positioning")
|
||||
print("- Signal handling")
|
||||
print("- Sync state feedback")
|
||||
|
||||
print("Components are easily reusable across scenes")
|
||||
print("Centralized management through SliderManager")
|
||||
print("Type-safe with proper class inheritance")
|
||||
@@ -1 +0,0 @@
|
||||
uid://btcluxe7swh2j
|
||||
@@ -1,35 +0,0 @@
|
||||
[gd_scene load_steps=3 format=4 uid="uid://cm4n7yap2k8q1"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui_scenes/components/ComponentMigrationExample.gd" id="1_migration_script"]
|
||||
[ext_resource type="PackedScene" uid="uid://bp2q8r4l6k9m3" path="res://ui_scenes/components/WobbleControlPanel.tscn" id="2_wobble_panel"]
|
||||
|
||||
[node name="ComponentMigrationExample" type="Node2D"]
|
||||
script = ExtResource("1_migration_script")
|
||||
|
||||
[node name="Background" type="ColorRect" parent="."]
|
||||
offset_right = 300.0
|
||||
offset_bottom = 400.0
|
||||
color = Color(0.2, 0.2, 0.2, 1)
|
||||
|
||||
[node name="Title" type="Label" parent="."]
|
||||
offset_left = 10.0
|
||||
offset_top = 10.0
|
||||
offset_right = 290.0
|
||||
offset_bottom = 35.0
|
||||
text = "New Component System Demo"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="WobbleControlPanel" parent="." instance=ExtResource("2_wobble_panel")]
|
||||
offset_left = 10.0
|
||||
offset_top = 50.0
|
||||
offset_right = 290.0
|
||||
offset_bottom = 350.0
|
||||
|
||||
[node name="Instructions" type="Label" parent="."]
|
||||
offset_left = 10.0
|
||||
offset_top = 360.0
|
||||
offset_right = 290.0
|
||||
offset_bottom = 390.0
|
||||
text = "These sliders automatically sync with sprites"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
@@ -61,7 +61,6 @@ func _on_parameter_value_changed(new_value: float):
|
||||
if not target_sprite or sprite_property == "":
|
||||
return
|
||||
|
||||
print("DEBUG: ParameterSlider ", sprite_property, " changed to: ", new_value)
|
||||
|
||||
target_sprite.set(sprite_property, new_value)
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ func _on_wobble_value_changed(new_value: float):
|
||||
if not target_sprite or parameter_name == "":
|
||||
return
|
||||
|
||||
print("DEBUG: WobbleSlider ", parameter_name, " changed to: ", new_value)
|
||||
target_sprite.updateWobbleParameter(parameter_name, new_value)
|
||||
|
||||
# Update visual feedback for sync status
|
||||
|
||||
@@ -6,6 +6,8 @@ var type = "sprite"
|
||||
var imageData = null
|
||||
var tex = null
|
||||
@export var path = ""
|
||||
## Custom display name for the sprite (separate from file path)
|
||||
var displayName = ""
|
||||
|
||||
var loadedImageData = null
|
||||
|
||||
@@ -319,8 +321,6 @@ func calculateParentOpacityMultiplier():
|
||||
|
||||
## 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:
|
||||
@@ -331,17 +331,15 @@ func updateWobbleParameter(parameter: String, value: float):
|
||||
"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")
|
||||
pass # Individual sprite update - no sync needed
|
||||
|
||||
## Check if this sprite is synced to a group
|
||||
func isSynced() -> bool:
|
||||
|
||||
@@ -211,7 +211,6 @@ func _on_stream_deck_check_toggled(button_pressed):
|
||||
func _on_experimental_mic_loudness_toggle(checked):
|
||||
Global.experimentalMicLoudness = checked
|
||||
Saving.settings["experimentalMicLoudness"] = checked
|
||||
print("Experimental mic loudness: ", checked)
|
||||
|
||||
|
||||
func _process(delta):
|
||||
|
||||
@@ -24,8 +24,6 @@ func _ready():
|
||||
|
||||
# Find the wobble sync control node
|
||||
wobbleSyncControl = find_child("WobbleSyncControl")
|
||||
if wobbleSyncControl == null:
|
||||
print("Warning: WobbleSyncControl node not found in sprite viewer")
|
||||
|
||||
# Set up blend mode dropdown
|
||||
setupBlendModeDropdown()
|
||||
@@ -355,8 +353,11 @@ func changeRotLimit():
|
||||
|
||||
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay.rotation_degrees = Global.heldSprite.rLimitMin
|
||||
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay2.rotation_degrees = Global.heldSprite.rLimitMax
|
||||
|
||||
|
||||
func setLayerButtons():
|
||||
if Global.heldSprite == null:
|
||||
return
|
||||
|
||||
var a = Global.heldSprite.costumeLayers.duplicate()
|
||||
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1.frame = 1-a[0]
|
||||
@@ -370,6 +371,10 @@ func setLayerButtons():
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9.frame = 1-a[8]
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10.frame = 1-a[9]
|
||||
|
||||
# Update checkmarks to show current costume layer
|
||||
updateLayerCheckmarks()
|
||||
|
||||
# Update sprite visibility for all sprites based on current costume
|
||||
var nodes = get_tree().get_nodes_in_group("saved")
|
||||
for sprite in nodes:
|
||||
if sprite.costumeLayers[Global.main.costume - 1] == 1:
|
||||
@@ -378,7 +383,45 @@ func setLayerButtons():
|
||||
else:
|
||||
sprite.visible = false
|
||||
sprite.changeCollision(false)
|
||||
|
||||
|
||||
# Update the sprite list to reflect visibility changes
|
||||
Global.spriteList.updateAllVisible()
|
||||
|
||||
func updateLayerCheckmarks():
|
||||
# Hide all checkmarks first
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1/Checkmark1.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer2Container/Layer2/Checkmark2.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer3Container/Layer3/Checkmark3.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer4Container/Layer4/Checkmark4.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer5Container/Layer5/Checkmark5.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer6Container/Layer6/Checkmark6.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer7Container/Layer7/Checkmark7.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer8Container/Layer8/Checkmark8.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9/Checkmark9.visible = false
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10/Checkmark10.visible = false
|
||||
|
||||
# Show checkmark for current costume layer
|
||||
match Global.main.costume:
|
||||
1:
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1/Checkmark1.visible = true
|
||||
2:
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer2Container/Layer2/Checkmark2.visible = true
|
||||
3:
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer3Container/Layer3/Checkmark3.visible = true
|
||||
4:
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer4Container/Layer4/Checkmark4.visible = true
|
||||
5:
|
||||
$VBoxContainer/LayersSection/HBoxContainer/Layer5Container/Layer5/Checkmark5.visible = true
|
||||
6:
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer6Container/Layer6/Checkmark6.visible = true
|
||||
7:
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer7Container/Layer7/Checkmark7.visible = true
|
||||
8:
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer8Container/Layer8/Checkmark8.visible = true
|
||||
9:
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9/Checkmark9.visible = true
|
||||
10:
|
||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10/Checkmark10.visible = true
|
||||
|
||||
|
||||
func _on_layer_button_1_pressed():
|
||||
@@ -478,6 +521,11 @@ func layerSelected():
|
||||
newPos = $VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9.position
|
||||
10:
|
||||
newPos = $VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10.position
|
||||
|
||||
# Update selection indicator position if it exists
|
||||
var select_node = get_node_or_null("VBoxContainer/LayersSection/Select")
|
||||
if select_node:
|
||||
select_node.position = newPos
|
||||
|
||||
|
||||
func _on_clip_linked_toggled(button_pressed):
|
||||
@@ -494,7 +542,7 @@ func _on_delete_pressed():
|
||||
Global.heldSprite.makeVis()
|
||||
|
||||
func _on_set_toggle_pressed():
|
||||
$VBoxContainer/BoxContainer/setToggle/Labelbel.text = "toggle: AWAITING INPUT"
|
||||
$VBoxContainer/BoxContainer/setToggle/Label.text = "toggle: AWAITING INPUT"
|
||||
await Global.main.fatfuckingballs
|
||||
|
||||
var keys = await Global.main.spriteVisToggles
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=77 format=4 uid="uid://d3anahesvdgfh"]
|
||||
[gd_scene load_steps=78 format=4 uid="uid://d3anahesvdgfh"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bgoaqt86bc73p" path="res://ui_scenes/spriteEditMenu/sprite_viewer.gd" id="1_hp0e3"]
|
||||
[ext_resource type="FontFile" uid="uid://ukj8gv8ucqsg" path="res://font/goober_pixel.ttf" id="2_da8lk"]
|
||||
@@ -27,11 +27,12 @@
|
||||
[ext_resource type="Texture2D" uid="uid://drcl08v4k3laj" path="res://ui_scenes/spriteEditMenu/layerButtons/8.png" id="22_041y0"]
|
||||
[ext_resource type="Texture2D" uid="uid://byyf5t56u3fq8" path="res://ui_scenes/spriteEditMenu/layerButtons/9.png" id="23_wja1u"]
|
||||
[ext_resource type="Texture2D" uid="uid://dxxj6jvajo37s" path="res://ui_scenes/spriteEditMenu/layerButtons/10.png" id="24_1m26d"]
|
||||
[ext_resource type="Texture2D" uid="uid://41u8egcau00i" path="res://ui_scenes/button sprites/checkmark.png" id="25_checkmark"]
|
||||
[ext_resource type="Texture2D" uid="uid://23rqddatjku3" path="res://ui_scenes/mouse/tooltipBox.png" id="26_8cfad"]
|
||||
[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, 1597)
|
||||
size = Vector2(261, 1794)
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hxmah"]
|
||||
shader = ExtResource("3_ky0lu")
|
||||
@@ -14290,7 +14291,7 @@ script = ExtResource("1_hp0e3")
|
||||
z_index = -2
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||
position = Vector2(122.5, 798.5)
|
||||
position = Vector2(130.5, 899)
|
||||
shape = SubResource("RectangleShape2D_21kva")
|
||||
|
||||
[node name="NinePatchRect" type="NinePatchRect" parent="."]
|
||||
@@ -14783,7 +14784,6 @@ size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="Layer1" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer1Container"]
|
||||
z_as_relative = false
|
||||
position = Vector2(22, 22)
|
||||
texture = ExtResource("15_scank")
|
||||
hframes = 2
|
||||
@@ -14796,6 +14796,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark1" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer2Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14815,6 +14820,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark2" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer2Container/Layer2"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer3Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14834,6 +14844,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark3" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer3Container/Layer3"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer4Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14853,6 +14868,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark4" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer4Container/Layer4"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer5Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14872,6 +14892,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark5" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer5Container/Layer5"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/LayersSection"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 5
|
||||
@@ -14895,6 +14920,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark6" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer2/Layer6Container/Layer6"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer7Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14914,6 +14944,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark7" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer2/Layer7Container/Layer7"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer8Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14933,6 +14968,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark8" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer2/Layer8Container/Layer8"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer9Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14952,6 +14992,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark9" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="Layer10Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||
custom_minimum_size = Vector2(44, 44)
|
||||
layout_mode = 2
|
||||
@@ -14971,6 +15016,11 @@ offset_bottom = 22.0
|
||||
theme = SubResource("Theme_ig6qj")
|
||||
flat = true
|
||||
|
||||
[node name="Checkmark10" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10"]
|
||||
visible = false
|
||||
position = Vector2(14, 12)
|
||||
texture = ExtResource("25_checkmark")
|
||||
|
||||
[node name="BoxContainer" type="BoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
@@ -15024,5 +15074,15 @@ centered = false
|
||||
[connection signal="pressed" from="VBoxContainer/Buttons/TrashWrapper/Trash/trash" to="." method="_on_trash_pressed"]
|
||||
[connection signal="toggled" from="VBoxContainer/RenderingSection/ClipLinked" to="." method="_on_clip_linked_toggled"]
|
||||
[connection signal="toggled" from="VBoxContainer/PhysicsSection/BounceVelocity" to="." method="_on_check_box_toggled"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1/layerButton1" to="." method="_on_layer_button_1_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer/Layer2Container/Layer2/layerButton2" to="." method="_on_layer_button_2_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer/Layer3Container/Layer3/layerButton3" to="." method="_on_layer_button_3_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer/Layer4Container/Layer4/layerButton4" to="." method="_on_layer_button_4_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer/Layer5Container/Layer5/layerButton5" to="." method="_on_layer_button_5_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer2/Layer6Container/Layer6/layerButton6" to="." method="_on_layer_button_6_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer2/Layer7Container/Layer7/layerButton7" to="." method="_on_layer_button_7_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer2/Layer8Container/Layer8/layerButton8" to="." method="_on_layer_button_8_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9/layerButton9" to="." method="_on_layer_button_9_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10/layerButton10" to="." method="_on_layer_button_10_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/BoxContainer/setToggle" to="." method="_on_set_toggle_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/BoxContainer/setToggle/delete" to="." method="_on_delete_pressed"]
|
||||
|
||||
@@ -55,11 +55,10 @@ func updateGroupDropdown():
|
||||
# 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")
|
||||
pass # WobbleSyncManager not available
|
||||
|
||||
# Add "Create New..." option
|
||||
groupDropdown.add_separator()
|
||||
@@ -67,7 +66,6 @@ func updateGroupDropdown():
|
||||
|
||||
# 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:
|
||||
@@ -75,13 +73,10 @@ func updateGroupDropdown():
|
||||
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
|
||||
@@ -100,11 +95,9 @@ func updateSyncIndicator():
|
||||
|
||||
## 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())
|
||||
pass # Sprite is valid
|
||||
updateUI()
|
||||
|
||||
## Get available groups for the dropdown (excluding "None" and "Create New...")
|
||||
@@ -120,18 +113,15 @@ func _on_group_dropdown_selected(index: int):
|
||||
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..."
|
||||
@@ -143,45 +133,39 @@ func _on_group_dropdown_selected(index: int):
|
||||
_:
|
||||
# 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")
|
||||
|
||||
pass # Group doesn't exist
|
||||
|
||||
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")
|
||||
pass # Failed to create group
|
||||
else:
|
||||
print("DEBUG: No current sprite to add to group")
|
||||
pass # No sprite or WobbleSyncManager not available
|
||||
|
||||
## Handle create group dialog cancellation
|
||||
func _on_create_group_cancelled():
|
||||
@@ -203,5 +187,4 @@ func canSync() -> bool:
|
||||
|
||||
## Force refresh the UI - useful after loading saves
|
||||
func forceRefresh():
|
||||
print("DEBUG: WobbleSyncControl.forceRefresh called")
|
||||
updateUI()
|
||||
|
||||
@@ -2,9 +2,9 @@ extends NinePatchRect
|
||||
|
||||
@onready var spritePreview = $SpritePreview/Sprite2D
|
||||
@onready var outline = $Selected
|
||||
|
||||
|
||||
@onready var fade = $Fade
|
||||
@onready var button = $Button
|
||||
@onready var label = $Label
|
||||
|
||||
var sprite = null
|
||||
var parent = null
|
||||
@@ -14,9 +14,23 @@ var indent = 0
|
||||
var childrenTags = []
|
||||
var parentTag = null
|
||||
|
||||
## Context menu for right-click actions
|
||||
var context_menu: PopupMenu = null
|
||||
## Line edit for renaming
|
||||
var rename_edit: LineEdit = null
|
||||
## Track if we're currently in rename mode
|
||||
var is_renaming: bool = false
|
||||
|
||||
func _ready():
|
||||
var count = spritePath.get_slice_count("/") - 1
|
||||
$Label.text = spritePath.get_slice("/",count)
|
||||
# Use displayName if available, otherwise fallback to path
|
||||
var display_text = ""
|
||||
if sprite.displayName != "":
|
||||
display_text = sprite.displayName
|
||||
else:
|
||||
var count = spritePath.get_slice_count("/") - 1
|
||||
display_text = spritePath.get_slice("/",count)
|
||||
|
||||
label.text = display_text
|
||||
$Line2D.visible = false
|
||||
|
||||
spritePreview.texture = sprite.sprite.texture
|
||||
@@ -25,6 +39,115 @@ func _ready():
|
||||
spritePreview.scale = Vector2(1,1) * (60.0/displaySize)
|
||||
spritePreview.offset = sprite.sprite.offset
|
||||
|
||||
# Set up right-click detection
|
||||
button.gui_input.connect(_on_button_gui_input)
|
||||
|
||||
# Create context menu
|
||||
_setup_context_menu()
|
||||
|
||||
## Set up the right-click context menu
|
||||
func _setup_context_menu():
|
||||
context_menu = PopupMenu.new()
|
||||
add_child(context_menu)
|
||||
|
||||
# Add rename option
|
||||
context_menu.add_item("Rename", 0)
|
||||
context_menu.id_pressed.connect(_on_context_menu_selected)
|
||||
|
||||
# Wait for menu to be ready, then adjust size
|
||||
context_menu.ready.connect(_adjust_menu_size)
|
||||
|
||||
## Adjust the context menu size to be more compact
|
||||
func _adjust_menu_size():
|
||||
if context_menu:
|
||||
# Let the menu calculate its natural size first
|
||||
await get_tree().process_frame
|
||||
context_menu.reset_size() # Reset to content-based size
|
||||
|
||||
## Handle GUI input events on the button
|
||||
func _on_button_gui_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
|
||||
# Show context menu at cursor position
|
||||
var global_pos = get_global_mouse_position()
|
||||
context_menu.position = Vector2i(global_pos)
|
||||
context_menu.popup()
|
||||
|
||||
## Handle context menu selections
|
||||
func _on_context_menu_selected(id: int):
|
||||
match id:
|
||||
0: # Rename
|
||||
_start_rename()
|
||||
|
||||
## Start the rename process
|
||||
func _start_rename():
|
||||
if is_renaming:
|
||||
return
|
||||
|
||||
is_renaming = true
|
||||
|
||||
# Create line edit for renaming
|
||||
rename_edit = LineEdit.new()
|
||||
add_child(rename_edit)
|
||||
|
||||
# Position and size the line edit over the label
|
||||
rename_edit.position = label.position
|
||||
rename_edit.size = label.size
|
||||
rename_edit.text = label.text
|
||||
|
||||
# Hide the original label
|
||||
label.visible = false
|
||||
|
||||
# Focus the line edit and select all text
|
||||
rename_edit.grab_focus()
|
||||
rename_edit.select_all()
|
||||
|
||||
# Connect signals
|
||||
rename_edit.text_submitted.connect(_on_rename_submitted)
|
||||
rename_edit.focus_exited.connect(_on_rename_focus_lost)
|
||||
|
||||
## Handle rename submission (Enter key)
|
||||
func _on_rename_submitted(new_name: String):
|
||||
if rename_edit != null:
|
||||
_finish_rename(new_name)
|
||||
|
||||
## Handle losing focus (clicking elsewhere)
|
||||
func _on_rename_focus_lost():
|
||||
if rename_edit != null:
|
||||
_finish_rename(rename_edit.text)
|
||||
|
||||
## Finish the rename process
|
||||
func _finish_rename(new_name: String):
|
||||
if not is_renaming:
|
||||
return
|
||||
|
||||
is_renaming = false
|
||||
|
||||
# Clean up the line edit
|
||||
if rename_edit:
|
||||
rename_edit.queue_free()
|
||||
rename_edit = null
|
||||
|
||||
# Show the label again
|
||||
label.visible = true
|
||||
|
||||
# Validate and apply the new name
|
||||
new_name = new_name.strip_edges()
|
||||
if new_name != "" and new_name != label.text:
|
||||
_apply_rename(new_name)
|
||||
|
||||
## Apply the rename to the sprite
|
||||
func _apply_rename(new_name: String):
|
||||
# Update the display name (without file extension)
|
||||
label.text = new_name
|
||||
sprite.displayName = new_name # Store display name separately
|
||||
|
||||
# Update the global sprite list
|
||||
Global.spriteList.updateData()
|
||||
|
||||
# Show feedback to user
|
||||
Global.pushUpdate("Renamed sprite to: " + new_name)
|
||||
|
||||
|
||||
func updateChildren():
|
||||
for child in childrenTags:
|
||||
|
||||
Reference in New Issue
Block a user