mirror of
https://github.com/litruv/PNGTuber-Plus.git
synced 2026-07-26 03:26: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.
|
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
|
* Works alongside opacity controls
|
||||||
|
|
||||||
|
|
||||||
### <EFBFBD>🌀 Rotation Wobble
|
### 🌀 Rotation Wobble
|
||||||
|
|
||||||
Sprites can now do a subtle (or chaotic) rotational wobble. Frequency + amplitude sliders included.
|
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
|
blinkTick = -12
|
||||||
|
|
||||||
func epicFail(err):
|
func epicFail(err):
|
||||||
print(fail)
|
|
||||||
if fail == null:
|
if fail == null:
|
||||||
return
|
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)
|
signal sprite_left_group(sprite_id: int, group_name: String)
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
print("DEBUG: WobbleSyncManager._ready() called")
|
# Manager initialization complete
|
||||||
print("DEBUG: WobbleSyncManager autoload initialized successfully")
|
pass
|
||||||
print("DEBUG: Initial syncGroups: ", syncGroups)
|
|
||||||
print("DEBUG: Initial spriteGroupMembership: ", spriteGroupMembership)
|
|
||||||
|
|
||||||
class WobbleSyncGroup:
|
class WobbleSyncGroup:
|
||||||
var name: String
|
var name: String
|
||||||
@@ -32,8 +30,6 @@ class WobbleSyncGroup:
|
|||||||
|
|
||||||
## Set wobble parameters for the entire group
|
## 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):
|
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
|
xFrq = x_frq
|
||||||
xAmp = x_amp
|
xAmp = x_amp
|
||||||
yFrq = y_frq
|
yFrq = y_frq
|
||||||
@@ -43,13 +39,10 @@ class WobbleSyncGroup:
|
|||||||
|
|
||||||
# Update all member sprites using the manager reference
|
# Update all member sprites using the manager reference
|
||||||
var sprites = manager_ref.get_tree().get_nodes_in_group("saved")
|
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
|
var updated_count = 0
|
||||||
for sprite in sprites:
|
for sprite in sprites:
|
||||||
print("DEBUG: Checking sprite ID ", sprite.id, " (type: ", typeof(sprite.id), ") against member list")
|
|
||||||
if sprite.id in memberSprites:
|
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
|
# Preserve the sprite's group membership
|
||||||
var current_group = sprite.wobbleSyncGroup
|
var current_group = sprite.wobbleSyncGroup
|
||||||
sprite.xFrq = xFrq
|
sprite.xFrq = xFrq
|
||||||
@@ -61,19 +54,13 @@ class WobbleSyncGroup:
|
|||||||
# Restore group membership in case it got cleared
|
# Restore group membership in case it got cleared
|
||||||
sprite.wobbleSyncGroup = current_group
|
sprite.wobbleSyncGroup = current_group
|
||||||
updated_count += 1
|
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
|
## Add sprite to this group
|
||||||
func addSprite(sprite_id): # Remove type constraint to handle float IDs
|
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:
|
if sprite_id not in memberSprites:
|
||||||
memberSprites.append(sprite_id)
|
memberSprites.append(sprite_id)
|
||||||
print("DEBUG: Added sprite to memberSprites. Current members: ", memberSprites)
|
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Sprite already in memberSprites")
|
pass # Sprite already in group
|
||||||
|
|
||||||
## Remove sprite from this group
|
## Remove sprite from this group
|
||||||
func removeSprite(sprite_id): # Remove type constraint
|
func removeSprite(sprite_id): # Remove type constraint
|
||||||
@@ -144,10 +131,8 @@ func deleteGroup(group_name: String):
|
|||||||
|
|
||||||
## Add sprite to a group
|
## Add sprite to a group
|
||||||
func addSpriteToGroup(sprite_id, group_name: String) -> bool: # Remove type constraint
|
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):
|
if not syncGroups.has(group_name):
|
||||||
print("DEBUG: Group '", group_name, "' not found")
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# Remove sprite from any existing group first
|
# 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]
|
var group = syncGroups[group_name]
|
||||||
group.addSprite(sprite_id)
|
group.addSprite(sprite_id)
|
||||||
spriteGroupMembership[sprite_id] = group_name
|
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
|
# Sync the sprite's wobble parameters to the group
|
||||||
var sprite = getSpriteById(sprite_id)
|
var sprite = getSpriteById(sprite_id)
|
||||||
if sprite:
|
if sprite:
|
||||||
print("DEBUG: Found sprite object, syncing wobble parameters to group values")
|
|
||||||
sprite.wobbleSyncGroup = group_name
|
sprite.wobbleSyncGroup = group_name
|
||||||
sprite.xFrq = group.xFrq
|
sprite.xFrq = group.xFrq
|
||||||
sprite.xAmp = group.xAmp
|
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
|
## Remove sprite from a specific group
|
||||||
func removeSpriteFromGroup(sprite_id, group_name: String): # Remove type constraint
|
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):
|
if not syncGroups.has(group_name):
|
||||||
print("DEBUG: Group '", group_name, "' not found")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
var group = syncGroups[group_name]
|
var group = syncGroups[group_name]
|
||||||
print("DEBUG: Group before removal has ", group.memberSprites.size(), " members: ", group.memberSprites)
|
|
||||||
group.removeSprite(sprite_id)
|
group.removeSprite(sprite_id)
|
||||||
spriteGroupMembership.erase(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
|
# Clear the sprite's sync group reference
|
||||||
var sprite = getSpriteById(sprite_id)
|
var sprite = getSpriteById(sprite_id)
|
||||||
if sprite:
|
if sprite:
|
||||||
print("DEBUG: Clearing sprite's wobbleSyncGroup property")
|
|
||||||
sprite.wobbleSyncGroup = ""
|
sprite.wobbleSyncGroup = ""
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Could not find sprite object for ID: ", sprite_id)
|
pass # Sprite not found
|
||||||
|
|
||||||
sprite_left_group.emit(sprite_id, group_name)
|
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
|
## Remove sprite from all groups
|
||||||
func removeSpriteFromAllGroups(sprite_id): # Remove type constraint
|
func removeSpriteFromAllGroups(sprite_id): # Remove type constraint
|
||||||
print("DEBUG: removeSpriteFromAllGroups called for sprite ID: ", sprite_id)
|
|
||||||
if spriteGroupMembership.has(sprite_id):
|
if spriteGroupMembership.has(sprite_id):
|
||||||
var group_name = spriteGroupMembership[sprite_id]
|
var group_name = spriteGroupMembership[sprite_id]
|
||||||
print("DEBUG: Found sprite in group '", group_name, "', removing...")
|
|
||||||
removeSpriteFromGroup(sprite_id, group_name)
|
removeSpriteFromGroup(sprite_id, group_name)
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Sprite not found in any group membership")
|
pass # Sprite not in any group
|
||||||
|
|
||||||
## Update wobble parameters for a 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):
|
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):
|
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
|
return
|
||||||
|
|
||||||
var group = syncGroups[group_name]
|
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)
|
group.setWobbleParameters(x_frq, x_amp, y_frq, y_amp, r_frq, r_amp, self)
|
||||||
|
|
||||||
## Get sprite's current group name
|
## Get sprite's current group name
|
||||||
@@ -234,14 +204,10 @@ func getSpriteGroupName(sprite_id: int) -> String:
|
|||||||
|
|
||||||
## Get all group names
|
## Get all group names
|
||||||
func getGroupNames() -> Array:
|
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()
|
return syncGroups.keys()
|
||||||
|
|
||||||
## Test function to manually load wobble sync groups
|
## Test function to manually load wobble sync groups
|
||||||
func testManualLoad():
|
func testManualLoad():
|
||||||
print("DEBUG: testManualLoad called - creating test data...")
|
|
||||||
var test_data = {
|
var test_data = {
|
||||||
"ears": {
|
"ears": {
|
||||||
"name": "ears",
|
"name": "ears",
|
||||||
@@ -254,9 +220,7 @@ func testManualLoad():
|
|||||||
"memberSprites": [3291286625.0]
|
"memberSprites": [3291286625.0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("DEBUG: Calling loadSaveData with test data...")
|
|
||||||
await loadSaveData(test_data)
|
await loadSaveData(test_data)
|
||||||
print("DEBUG: testManualLoad completed. syncGroups now has: ", syncGroups.size(), " groups")
|
|
||||||
|
|
||||||
## Check if a group exists
|
## Check if a group exists
|
||||||
func hasGroup(group_name: String) -> bool:
|
func hasGroup(group_name: String) -> bool:
|
||||||
@@ -305,91 +269,52 @@ func getSaveData() -> Dictionary:
|
|||||||
|
|
||||||
## Load save data for all groups
|
## Load save data for all groups
|
||||||
func loadSaveData(save_data: Dictionary):
|
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
|
# Check if save_data is valid
|
||||||
if save_data == null or typeof(save_data) != TYPE_DICTIONARY:
|
if save_data == null or typeof(save_data) != TYPE_DICTIONARY:
|
||||||
print("DEBUG: ERROR - Invalid save_data provided")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if save_data.size() == 0:
|
if save_data.size() == 0:
|
||||||
print("DEBUG: WARNING - Empty save_data provided")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Clear existing groups
|
# Clear existing groups
|
||||||
print("DEBUG: Clearing existing syncGroups (had ", syncGroups.size(), " groups)")
|
|
||||||
syncGroups.clear()
|
syncGroups.clear()
|
||||||
spriteGroupMembership.clear()
|
spriteGroupMembership.clear()
|
||||||
print("DEBUG: Cleared existing data. syncGroups now has ", syncGroups.size(), " groups")
|
|
||||||
|
|
||||||
# Load groups from save data
|
# Load groups from save data
|
||||||
var loaded_groups = 0
|
var loaded_groups = 0
|
||||||
print("DEBUG: Starting group loading loop...")
|
|
||||||
for group_name in save_data.keys():
|
for group_name in save_data.keys():
|
||||||
print("DEBUG: ---- Processing group '", group_name, "' (attempt ", loaded_groups + 1, ") ----")
|
|
||||||
var group_data = save_data[group_name]
|
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:
|
if typeof(group_data) == TYPE_DICTIONARY:
|
||||||
print("DEBUG: Creating WobbleSyncGroup instance...")
|
|
||||||
var group = WobbleSyncGroup.new(group_name)
|
var group = WobbleSyncGroup.new(group_name)
|
||||||
print("DEBUG: Created new WobbleSyncGroup instance for '", group_name, "'")
|
|
||||||
print("DEBUG: Calling fromSaveData...")
|
|
||||||
group.fromSaveData(group_data)
|
group.fromSaveData(group_data)
|
||||||
print("DEBUG: Called fromSaveData on group '", group_name, "'")
|
|
||||||
print("DEBUG: Adding to syncGroups dictionary...")
|
|
||||||
syncGroups[group_name] = group
|
syncGroups[group_name] = group
|
||||||
loaded_groups += 1
|
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
|
# Update sprite group membership
|
||||||
print("DEBUG: Updating sprite group membership...")
|
|
||||||
for sprite_id in group.memberSprites:
|
for sprite_id in group.memberSprites:
|
||||||
spriteGroupMembership[sprite_id] = group_name
|
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:
|
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 no groups were loaded, clear any orphaned group references on sprites
|
||||||
if syncGroups.size() == 0:
|
if syncGroups.size() == 0:
|
||||||
print("DEBUG: No groups loaded, clearing orphaned sprite group references")
|
|
||||||
var sprites = get_tree().get_nodes_in_group("saved")
|
var sprites = get_tree().get_nodes_in_group("saved")
|
||||||
for sprite in sprites:
|
for sprite in sprites:
|
||||||
if sprite.wobbleSyncGroup != "":
|
if sprite.wobbleSyncGroup != "":
|
||||||
print("DEBUG: Clearing orphaned group reference '", sprite.wobbleSyncGroup, "' from sprite ID ", sprite.id)
|
|
||||||
sprite.wobbleSyncGroup = ""
|
sprite.wobbleSyncGroup = ""
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Groups loaded successfully, syncing sprite parameters...")
|
|
||||||
# Apply wobble parameters to sprites with better timing
|
# Apply wobble parameters to sprites with better timing
|
||||||
await get_tree().process_frame # Wait for sprites to be loaded
|
await get_tree().process_frame # Wait for sprites to be loaded
|
||||||
await get_tree().process_frame # Extra frame to ensure everything is ready
|
await get_tree().process_frame # Extra frame to ensure everything is ready
|
||||||
|
|
||||||
for group_name in syncGroups.keys():
|
for group_name in syncGroups.keys():
|
||||||
var group = syncGroups[group_name]
|
var group = syncGroups[group_name]
|
||||||
print("DEBUG: Syncing parameters for group '", group_name, "' with ", group.memberSprites.size(), " members")
|
|
||||||
for sprite_id in group.memberSprites:
|
for sprite_id in group.memberSprites:
|
||||||
var sprite = getSpriteById(sprite_id)
|
var sprite = getSpriteById(sprite_id)
|
||||||
if sprite:
|
if sprite:
|
||||||
print("DEBUG: Syncing sprite ID ", sprite_id, " to group '", group_name, "'")
|
|
||||||
sprite.wobbleSyncGroup = group_name
|
sprite.wobbleSyncGroup = group_name
|
||||||
sprite.xFrq = group.xFrq
|
sprite.xFrq = group.xFrq
|
||||||
sprite.xAmp = group.xAmp
|
sprite.xAmp = group.xAmp
|
||||||
@@ -403,50 +328,9 @@ func loadSaveData(save_data: Dictionary):
|
|||||||
if sprite.has_method("updateShaderOpacity"):
|
if sprite.has_method("updateShaderOpacity"):
|
||||||
sprite.updateShaderOpacity()
|
sprite.updateShaderOpacity()
|
||||||
else:
|
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
|
## Called when a sprite is deleted to clean up references
|
||||||
func onSpriteDeleted(sprite_id): # Remove type constraint
|
func onSpriteDeleted(sprite_id): # Remove type constraint
|
||||||
removeSpriteFromAllGroups(sprite_id)
|
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.main = self
|
||||||
Global.fail = $Failed
|
Global.fail = $Failed
|
||||||
|
|
||||||
|
var newUser = Saving.settings["newUser"]
|
||||||
|
|
||||||
Global.connect("startSpeaking",onSpeak)
|
Global.connect("startSpeaking",onSpeak)
|
||||||
|
|
||||||
@@ -83,22 +84,14 @@ func _ready():
|
|||||||
if streamdeck_node != null:
|
if streamdeck_node != null:
|
||||||
streamdeck_node.on_key_down.connect(changeCostumeStreamDeck)
|
streamdeck_node.on_key_down.connect(changeCostumeStreamDeck)
|
||||||
|
|
||||||
if Saving.settings["newUser"]:
|
if newUser:
|
||||||
print("DEBUG: MAIN._ready() - New user detected, loading default avatar")
|
loadDefaultAvatar()
|
||||||
_on_load_dialog_file_selected("default")
|
|
||||||
Saving.settings["newUser"] = false
|
|
||||||
saveLoaded = true
|
|
||||||
else:
|
else:
|
||||||
print("DEBUG: MAIN._ready() - Existing user, loading last avatar")
|
var lastAvatar = Saving.settings.get("lastAvatar", "")
|
||||||
var lastAvatar = Saving.settings["lastAvatar"]
|
if lastAvatar != null and lastAvatar != "" and typeof(lastAvatar) == TYPE_STRING and FileAccess.file_exists(lastAvatar):
|
||||||
print("DEBUG: lastAvatar setting: ", lastAvatar, " (type: ", typeof(lastAvatar), ")")
|
loadAvatar(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)
|
|
||||||
else:
|
else:
|
||||||
print("WARNING: lastAvatar setting is invalid, loading default instead")
|
loadDefaultAvatar()
|
||||||
_on_load_dialog_file_selected("default")
|
|
||||||
|
|
||||||
$ControlPanel/volumeSlider.value = Saving.settings["volume"]
|
$ControlPanel/volumeSlider.value = Saving.settings["volume"]
|
||||||
$ControlPanel/sensitiveSlider.value = Saving.settings["sense"]
|
$ControlPanel/sensitiveSlider.value = Saving.settings["sense"]
|
||||||
@@ -425,54 +418,35 @@ func _on_load_button_pressed():
|
|||||||
|
|
||||||
#LOAD AVATAR
|
#LOAD AVATAR
|
||||||
func _on_load_dialog_file_selected(path):
|
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
|
# Handle case where path might be a Dictionary instead of string
|
||||||
if typeof(path) == TYPE_DICTIONARY:
|
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
|
return
|
||||||
|
|
||||||
print("DEBUG: About to read save data from: ", path)
|
|
||||||
var data = Saving.read_save(path)
|
var data = Saving.read_save(path)
|
||||||
print("DEBUG: Save data read. Data type: ", typeof(data), ", null check: ", data == null)
|
|
||||||
|
|
||||||
if data == null:
|
if data == null:
|
||||||
print("DEBUG: Save data is null, returning")
|
|
||||||
return
|
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()
|
origin.queue_free()
|
||||||
var new = Node2D.new()
|
var new = Node2D.new()
|
||||||
$OriginMotion.add_child(new)
|
$OriginMotion.add_child(new)
|
||||||
origin = new
|
origin = new
|
||||||
|
|
||||||
for item in data:
|
for item in data:
|
||||||
print("DEBUG: Processing item: ", item, ", data type: ", typeof(data[item]))
|
|
||||||
if typeof(data[item]) != TYPE_DICTIONARY:
|
if typeof(data[item]) != TYPE_DICTIONARY:
|
||||||
print("DEBUG: Skipping item ", item, " - not a dictionary")
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not data[item].has("path"):
|
if not data[item].has("path"):
|
||||||
print("DEBUG: Skipping item ", item, " - no 'path' key. Keys: ", data[item].keys())
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var sprite = spriteObject.instantiate()
|
var sprite = spriteObject.instantiate()
|
||||||
sprite.path = data[item]["path"]
|
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.id = data[item]["identification"]
|
||||||
sprite.parentId = data[item]["parentId"]
|
sprite.parentId = data[item]["parentId"]
|
||||||
|
|
||||||
@@ -503,9 +477,9 @@ func _on_load_dialog_file_selected(path):
|
|||||||
|
|
||||||
if data[item].has("costumeLayers"):
|
if data[item].has("costumeLayers"):
|
||||||
sprite.costumeLayers = str_to_var(data[item]["costumeLayers"]).duplicate()
|
sprite.costumeLayers = str_to_var(data[item]["costumeLayers"]).duplicate()
|
||||||
if sprite.costumeLayers.size() < 8:
|
# Ensure we have exactly 10 costume layers
|
||||||
for i in range(5):
|
while sprite.costumeLayers.size() < 10:
|
||||||
sprite.costumeLayers.append(1)
|
sprite.costumeLayers.append(1)
|
||||||
|
|
||||||
if data[item].has("stretchAmount"):
|
if data[item].has("stretchAmount"):
|
||||||
sprite.stretchAmount = data[item]["stretchAmount"]
|
sprite.stretchAmount = data[item]["stretchAmount"]
|
||||||
@@ -542,23 +516,8 @@ func _on_load_dialog_file_selected(path):
|
|||||||
Global.spriteList.updateData()
|
Global.spriteList.updateData()
|
||||||
|
|
||||||
# Load wobble sync groups
|
# 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:
|
if data.has("wobbleSyncGroups") and WobbleSyncManager:
|
||||||
print("DEBUG: Loading wobble sync groups. Data: ", data["wobbleSyncGroups"])
|
|
||||||
await WobbleSyncManager.loadSaveData(data["wobbleSyncGroups"])
|
await WobbleSyncManager.loadSaveData(data["wobbleSyncGroups"])
|
||||||
print("DEBUG: Finished loading wobble sync groups")
|
|
||||||
# Refresh wobble sync UI after groups are loaded
|
# Refresh wobble sync UI after groups are loaded
|
||||||
if Global.spriteEdit and Global.spriteEdit.wobbleSyncControl:
|
if Global.spriteEdit and Global.spriteEdit.wobbleSyncControl:
|
||||||
Global.spriteEdit.wobbleSyncControl.updateUI()
|
Global.spriteEdit.wobbleSyncControl.updateUI()
|
||||||
@@ -568,14 +527,6 @@ func _on_load_dialog_file_selected(path):
|
|||||||
# Force refresh in case timing issues
|
# Force refresh in case timing issues
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
Global.spriteEdit.wobbleSyncControl.forceRefresh()
|
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
|
# 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
|
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)
|
Global.pushUpdate("Loaded avatar at: " + path)
|
||||||
|
|
||||||
onWindowSizeChange()
|
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
|
#SAVE AVATAR
|
||||||
func _on_save_dialog_file_selected(path):
|
func _on_save_dialog_file_selected(path):
|
||||||
var data = {}
|
var data = {}
|
||||||
@@ -599,6 +558,7 @@ func _on_save_dialog_file_selected(path):
|
|||||||
data[id] = {}
|
data[id] = {}
|
||||||
data[id]["type"] = "sprite"
|
data[id]["type"] = "sprite"
|
||||||
data[id]["path"] = child.path
|
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]["imageData"] = Marshalls.raw_to_base64(child.imageData.save_png_to_buffer())
|
||||||
data[id]["identification"] = child.id
|
data[id]["identification"] = child.id
|
||||||
data[id]["parentId"] = child.parentId
|
data[id]["parentId"] = child.parentId
|
||||||
@@ -758,9 +718,11 @@ func changeCostumeStreamDeck(id: String):
|
|||||||
"9":changeCostume(9)
|
"9":changeCostume(9)
|
||||||
"10":changeCostume(10)
|
"10":changeCostume(10)
|
||||||
|
|
||||||
func changeCostume(newCostume):
|
func changeCostume(newCostume, preserve_selection: bool = false):
|
||||||
costume = newCostume
|
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")
|
var nodes = get_tree().get_nodes_in_group("saved")
|
||||||
for sprite in nodes:
|
for sprite in nodes:
|
||||||
if sprite.costumeLayers[newCostume-1] == 1:
|
if sprite.costumeLayers[newCostume-1] == 1:
|
||||||
@@ -783,7 +745,7 @@ func moveSpriteMenu(delta):
|
|||||||
|
|
||||||
var size = get_viewport().get_visible_rect().size
|
var size = get_viewport().get_visible_rect().size
|
||||||
|
|
||||||
var windowLength = 1800
|
var windowLength = 2000
|
||||||
|
|
||||||
$ViewerArrows/Arrows.position.y = size.y - 25
|
$ViewerArrows/Arrows.position.y = size.y - 25
|
||||||
|
|
||||||
|
|||||||
@@ -14357,26 +14357,38 @@ offset_bottom = -51.0
|
|||||||
text = "Zoom : 100%"
|
text = "Zoom : 100%"
|
||||||
horizontal_alignment = 2
|
horizontal_alignment = 2
|
||||||
|
|
||||||
[node name="VersionLabels" type="Node2D" parent="ControlPanel"]
|
[node name="VersionLabels" type="Control" parent="ControlPanel"]
|
||||||
position = Vector2(-284, 59)
|
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"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="ControlPanel/VersionLabels"]
|
||||||
offset_left = -713.0
|
layout_mode = 1
|
||||||
offset_top = -94.0
|
anchors_preset = 2
|
||||||
offset_right = -575.0
|
anchor_top = 1.0
|
||||||
offset_bottom = -60.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"
|
text = "PNGTuber Plus"
|
||||||
label_settings = SubResource("LabelSettings_w0f1f")
|
label_settings = SubResource("LabelSettings_w0f1f")
|
||||||
|
|
||||||
[node name="Label2" type="Label" parent="ControlPanel/VersionLabels"]
|
[node name="Label2" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer"]
|
||||||
offset_left = -713.0
|
layout_mode = 2
|
||||||
offset_top = -123.0
|
|
||||||
offset_right = -575.0
|
|
||||||
offset_bottom = -89.0
|
|
||||||
text = "kaiakairos'"
|
text = "kaiakairos'"
|
||||||
label_settings = SubResource("LabelSettings_qg0do")
|
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
|
layout_mode = 0
|
||||||
offset_left = 104.0
|
offset_left = 104.0
|
||||||
offset_top = 11.0
|
offset_top = 11.0
|
||||||
@@ -14385,15 +14397,13 @@ offset_bottom = 54.0
|
|||||||
text = "v1.4.5"
|
text = "v1.4.5"
|
||||||
label_settings = SubResource("LabelSettings_xvf50")
|
label_settings = SubResource("LabelSettings_xvf50")
|
||||||
|
|
||||||
[node name="Label3" type="Label" parent="ControlPanel/VersionLabels"]
|
[node name="Label3" type="Label" parent="ControlPanel/VersionLabels/VBoxContainer"]
|
||||||
offset_left = -566.0
|
layout_mode = 2
|
||||||
offset_top = -93.0
|
|
||||||
offset_right = -428.0
|
|
||||||
offset_bottom = -59.0
|
|
||||||
text = "Litruv Edition"
|
text = "Litruv Edition"
|
||||||
label_settings = SubResource("LabelSettings_qg0do")
|
label_settings = SubResource("LabelSettings_qg0do")
|
||||||
|
|
||||||
[node name="EditControls" type="Node2D" parent="."]
|
[node name="EditControls" type="Node2D" parent="."]
|
||||||
|
visible = false
|
||||||
z_index = 4090
|
z_index = 4090
|
||||||
script = ExtResource("17_bf1ic")
|
script = ExtResource("17_bf1ic")
|
||||||
|
|
||||||
|
|||||||
@@ -50,11 +50,6 @@ window/vsync/vsync_mode=0
|
|||||||
|
|
||||||
project/assembly_name="PNGTuberPlus"
|
project/assembly_name="PNGTuberPlus"
|
||||||
|
|
||||||
[editor]
|
|
||||||
|
|
||||||
version_control/plugin_name=""
|
|
||||||
version_control/autoload_on_startup=false
|
|
||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PackedStringArray("res://addons/godot-streamdeck-addon/plugin.cfg")
|
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 == "":
|
if not target_sprite or sprite_property == "":
|
||||||
return
|
return
|
||||||
|
|
||||||
print("DEBUG: ParameterSlider ", sprite_property, " changed to: ", new_value)
|
|
||||||
|
|
||||||
target_sprite.set(sprite_property, 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 == "":
|
if not target_sprite or parameter_name == "":
|
||||||
return
|
return
|
||||||
|
|
||||||
print("DEBUG: WobbleSlider ", parameter_name, " changed to: ", new_value)
|
|
||||||
target_sprite.updateWobbleParameter(parameter_name, new_value)
|
target_sprite.updateWobbleParameter(parameter_name, new_value)
|
||||||
|
|
||||||
# Update visual feedback for sync status
|
# Update visual feedback for sync status
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ var type = "sprite"
|
|||||||
var imageData = null
|
var imageData = null
|
||||||
var tex = null
|
var tex = null
|
||||||
@export var path = ""
|
@export var path = ""
|
||||||
|
## Custom display name for the sprite (separate from file path)
|
||||||
|
var displayName = ""
|
||||||
|
|
||||||
var loadedImageData = null
|
var loadedImageData = null
|
||||||
|
|
||||||
@@ -319,8 +321,6 @@ func calculateParentOpacityMultiplier():
|
|||||||
|
|
||||||
## Update wobble parameters and sync to group if needed
|
## Update wobble parameters and sync to group if needed
|
||||||
func updateWobbleParameter(parameter: String, value: float):
|
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
|
# Update this sprite's parameter first
|
||||||
match parameter:
|
match parameter:
|
||||||
@@ -331,17 +331,15 @@ func updateWobbleParameter(parameter: String, value: float):
|
|||||||
"rFrq": rFrq = value
|
"rFrq": rFrq = value
|
||||||
"rAmp": rAmp = 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 this sprite is in a sync group, update the entire group
|
||||||
if wobbleSyncGroup != "" and WobbleSyncManager:
|
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)
|
WobbleSyncManager.updateGroupWobble(wobbleSyncGroup, xFrq, xAmp, yFrq, yAmp, rFrq, rAmp)
|
||||||
|
|
||||||
# Don't refresh UI immediately - let the sync process complete first
|
# Don't refresh UI immediately - let the sync process complete first
|
||||||
# The wobble sync control will handle UI updates when needed
|
# The wobble sync control will handle UI updates when needed
|
||||||
else:
|
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
|
## Check if this sprite is synced to a group
|
||||||
func isSynced() -> bool:
|
func isSynced() -> bool:
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ func _on_stream_deck_check_toggled(button_pressed):
|
|||||||
func _on_experimental_mic_loudness_toggle(checked):
|
func _on_experimental_mic_loudness_toggle(checked):
|
||||||
Global.experimentalMicLoudness = checked
|
Global.experimentalMicLoudness = checked
|
||||||
Saving.settings["experimentalMicLoudness"] = checked
|
Saving.settings["experimentalMicLoudness"] = checked
|
||||||
print("Experimental mic loudness: ", checked)
|
|
||||||
|
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ func _ready():
|
|||||||
|
|
||||||
# Find the wobble sync control node
|
# Find the wobble sync control node
|
||||||
wobbleSyncControl = find_child("WobbleSyncControl")
|
wobbleSyncControl = find_child("WobbleSyncControl")
|
||||||
if wobbleSyncControl == null:
|
|
||||||
print("Warning: WobbleSyncControl node not found in sprite viewer")
|
|
||||||
|
|
||||||
# Set up blend mode dropdown
|
# Set up blend mode dropdown
|
||||||
setupBlendModeDropdown()
|
setupBlendModeDropdown()
|
||||||
@@ -355,8 +353,11 @@ func changeRotLimit():
|
|||||||
|
|
||||||
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay.rotation_degrees = Global.heldSprite.rLimitMin
|
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay.rotation_degrees = Global.heldSprite.rLimitMin
|
||||||
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay2.rotation_degrees = Global.heldSprite.rLimitMax
|
$VBoxContainer/RotationalLimitsSection/RotBack/RotLineDisplay2.rotation_degrees = Global.heldSprite.rLimitMax
|
||||||
|
|
||||||
func setLayerButtons():
|
func setLayerButtons():
|
||||||
|
if Global.heldSprite == null:
|
||||||
|
return
|
||||||
|
|
||||||
var a = Global.heldSprite.costumeLayers.duplicate()
|
var a = Global.heldSprite.costumeLayers.duplicate()
|
||||||
|
|
||||||
$VBoxContainer/LayersSection/HBoxContainer/Layer1Container/Layer1.frame = 1-a[0]
|
$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/Layer9Container/Layer9.frame = 1-a[8]
|
||||||
$VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10.frame = 1-a[9]
|
$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")
|
var nodes = get_tree().get_nodes_in_group("saved")
|
||||||
for sprite in nodes:
|
for sprite in nodes:
|
||||||
if sprite.costumeLayers[Global.main.costume - 1] == 1:
|
if sprite.costumeLayers[Global.main.costume - 1] == 1:
|
||||||
@@ -378,7 +383,45 @@ func setLayerButtons():
|
|||||||
else:
|
else:
|
||||||
sprite.visible = false
|
sprite.visible = false
|
||||||
sprite.changeCollision(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():
|
func _on_layer_button_1_pressed():
|
||||||
@@ -478,6 +521,11 @@ func layerSelected():
|
|||||||
newPos = $VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9.position
|
newPos = $VBoxContainer/LayersSection/HBoxContainer2/Layer9Container/Layer9.position
|
||||||
10:
|
10:
|
||||||
newPos = $VBoxContainer/LayersSection/HBoxContainer2/Layer10Container/Layer10.position
|
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):
|
func _on_clip_linked_toggled(button_pressed):
|
||||||
@@ -494,7 +542,7 @@ func _on_delete_pressed():
|
|||||||
Global.heldSprite.makeVis()
|
Global.heldSprite.makeVis()
|
||||||
|
|
||||||
func _on_set_toggle_pressed():
|
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
|
await Global.main.fatfuckingballs
|
||||||
|
|
||||||
var keys = await Global.main.spriteVisToggles
|
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="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"]
|
[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://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://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://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://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"]
|
[ext_resource type="Texture2D" uid="uid://gflmeocxfnrq" path="res://ui_scenes/settings/deleteHotkey.png" id="27_fgu6g"]
|
||||||
|
|
||||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_21kva"]
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_21kva"]
|
||||||
size = Vector2(245, 1597)
|
size = Vector2(261, 1794)
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hxmah"]
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hxmah"]
|
||||||
shader = ExtResource("3_ky0lu")
|
shader = ExtResource("3_ky0lu")
|
||||||
@@ -14290,7 +14291,7 @@ script = ExtResource("1_hp0e3")
|
|||||||
z_index = -2
|
z_index = -2
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||||
position = Vector2(122.5, 798.5)
|
position = Vector2(130.5, 899)
|
||||||
shape = SubResource("RectangleShape2D_21kva")
|
shape = SubResource("RectangleShape2D_21kva")
|
||||||
|
|
||||||
[node name="NinePatchRect" type="NinePatchRect" parent="."]
|
[node name="NinePatchRect" type="NinePatchRect" parent="."]
|
||||||
@@ -14783,7 +14784,6 @@ size_flags_horizontal = 0
|
|||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
|
|
||||||
[node name="Layer1" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer1Container"]
|
[node name="Layer1" type="Sprite2D" parent="VBoxContainer/LayersSection/HBoxContainer/Layer1Container"]
|
||||||
z_as_relative = false
|
|
||||||
position = Vector2(22, 22)
|
position = Vector2(22, 22)
|
||||||
texture = ExtResource("15_scank")
|
texture = ExtResource("15_scank")
|
||||||
hframes = 2
|
hframes = 2
|
||||||
@@ -14796,6 +14796,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer2Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14815,6 +14820,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer3Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14834,6 +14844,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer4Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14853,6 +14868,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer5Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14872,6 +14892,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/LayersSection"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 5
|
theme_override_constants/separation = 5
|
||||||
@@ -14895,6 +14920,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer7Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14914,6 +14944,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer8Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14933,6 +14968,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer9Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14952,6 +14992,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="Layer10Container" type="Control" parent="VBoxContainer/LayersSection/HBoxContainer2"]
|
||||||
custom_minimum_size = Vector2(44, 44)
|
custom_minimum_size = Vector2(44, 44)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -14971,6 +15016,11 @@ offset_bottom = 22.0
|
|||||||
theme = SubResource("Theme_ig6qj")
|
theme = SubResource("Theme_ig6qj")
|
||||||
flat = true
|
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"]
|
[node name="BoxContainer" type="BoxContainer" parent="VBoxContainer"]
|
||||||
layout_mode = 2
|
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="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/RenderingSection/ClipLinked" to="." method="_on_clip_linked_toggled"]
|
||||||
[connection signal="toggled" from="VBoxContainer/PhysicsSection/BounceVelocity" to="." method="_on_check_box_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" to="." method="_on_set_toggle_pressed"]
|
||||||
[connection signal="pressed" from="VBoxContainer/BoxContainer/setToggle/delete" to="." method="_on_delete_pressed"]
|
[connection signal="pressed" from="VBoxContainer/BoxContainer/setToggle/delete" to="." method="_on_delete_pressed"]
|
||||||
|
|||||||
@@ -55,11 +55,10 @@ func updateGroupDropdown():
|
|||||||
# Add existing groups
|
# Add existing groups
|
||||||
if WobbleSyncManager:
|
if WobbleSyncManager:
|
||||||
var groups = WobbleSyncManager.getGroupNames()
|
var groups = WobbleSyncManager.getGroupNames()
|
||||||
print("DEBUG: updateGroupDropdown - available groups: ", groups)
|
|
||||||
for group_name in groups:
|
for group_name in groups:
|
||||||
groupDropdown.add_item(group_name)
|
groupDropdown.add_item(group_name)
|
||||||
else:
|
else:
|
||||||
print("DEBUG: updateGroupDropdown - WobbleSyncManager not available")
|
pass # WobbleSyncManager not available
|
||||||
|
|
||||||
# Add "Create New..." option
|
# Add "Create New..." option
|
||||||
groupDropdown.add_separator()
|
groupDropdown.add_separator()
|
||||||
@@ -67,7 +66,6 @@ func updateGroupDropdown():
|
|||||||
|
|
||||||
# Select current group if sprite is synced
|
# Select current group if sprite is synced
|
||||||
if currentSprite != null and currentSprite.wobbleSyncGroup != "":
|
if currentSprite != null and currentSprite.wobbleSyncGroup != "":
|
||||||
print("DEBUG: updateGroupDropdown - sprite has group '", currentSprite.wobbleSyncGroup, "'")
|
|
||||||
var group_index = -1
|
var group_index = -1
|
||||||
for i in range(groupDropdown.get_item_count()):
|
for i in range(groupDropdown.get_item_count()):
|
||||||
if groupDropdown.get_item_text(i) == currentSprite.wobbleSyncGroup:
|
if groupDropdown.get_item_text(i) == currentSprite.wobbleSyncGroup:
|
||||||
@@ -75,13 +73,10 @@ func updateGroupDropdown():
|
|||||||
break
|
break
|
||||||
|
|
||||||
if group_index != -1:
|
if group_index != -1:
|
||||||
print("DEBUG: updateGroupDropdown - selecting group at index ", group_index)
|
|
||||||
groupDropdown.selected = group_index
|
groupDropdown.selected = group_index
|
||||||
else:
|
else:
|
||||||
print("DEBUG: updateGroupDropdown - group '", currentSprite.wobbleSyncGroup, "' not found in dropdown")
|
|
||||||
groupDropdown.selected = 0 # Select "None"
|
groupDropdown.selected = 0 # Select "None"
|
||||||
else:
|
else:
|
||||||
print("DEBUG: updateGroupDropdown - sprite has no group, selecting 'None'")
|
|
||||||
groupDropdown.selected = 0 # Select "None"
|
groupDropdown.selected = 0 # Select "None"
|
||||||
|
|
||||||
updating_dropdown = false
|
updating_dropdown = false
|
||||||
@@ -100,11 +95,9 @@ func updateSyncIndicator():
|
|||||||
|
|
||||||
## Set the current sprite to manage
|
## Set the current sprite to manage
|
||||||
func setSprite(sprite):
|
func setSprite(sprite):
|
||||||
print("DEBUG: WobbleSyncControl.setSprite called with sprite ID: ", sprite.id if sprite else "null")
|
|
||||||
currentSprite = sprite
|
currentSprite = sprite
|
||||||
if currentSprite:
|
if currentSprite:
|
||||||
print("DEBUG: Current sprite wobbleSyncGroup: '", currentSprite.wobbleSyncGroup, "'")
|
pass # Sprite is valid
|
||||||
print("DEBUG: Current sprite isSynced(): ", currentSprite.isSynced())
|
|
||||||
updateUI()
|
updateUI()
|
||||||
|
|
||||||
## Get available groups for the dropdown (excluding "None" and "Create New...")
|
## Get available groups for the dropdown (excluding "None" and "Create New...")
|
||||||
@@ -120,18 +113,15 @@ func _on_group_dropdown_selected(index: int):
|
|||||||
return
|
return
|
||||||
|
|
||||||
var selected_text = groupDropdown.get_item_text(index)
|
var selected_text = groupDropdown.get_item_text(index)
|
||||||
print("DEBUG: Dropdown selected: '", selected_text, "' at index ", index)
|
|
||||||
|
|
||||||
match selected_text:
|
match selected_text:
|
||||||
"None":
|
"None":
|
||||||
# Remove sprite from any group
|
# Remove sprite from any group
|
||||||
if currentSprite.wobbleSyncGroup != "" and WobbleSyncManager:
|
if currentSprite.wobbleSyncGroup != "" and WobbleSyncManager:
|
||||||
print("DEBUG: Removing sprite ID ", currentSprite.id, " from group '", currentSprite.wobbleSyncGroup, "'")
|
|
||||||
WobbleSyncManager.removeSpriteFromAllGroups(currentSprite.id)
|
WobbleSyncManager.removeSpriteFromAllGroups(currentSprite.id)
|
||||||
Global.pushUpdate("Removed sprite from wobble sync group")
|
Global.pushUpdate("Removed sprite from wobble sync group")
|
||||||
|
|
||||||
"Create New...":
|
"Create New...":
|
||||||
print("DEBUG: User selected 'Create New...' from dropdown")
|
|
||||||
# Show create group dialog
|
# Show create group dialog
|
||||||
groupNameInput.text = ""
|
groupNameInput.text = ""
|
||||||
groupNameInput.placeholder_text = "Enter group name..."
|
groupNameInput.placeholder_text = "Enter group name..."
|
||||||
@@ -143,45 +133,39 @@ func _on_group_dropdown_selected(index: int):
|
|||||||
_:
|
_:
|
||||||
# Join selected group
|
# Join selected group
|
||||||
if WobbleSyncManager and WobbleSyncManager.hasGroup(selected_text):
|
if WobbleSyncManager and WobbleSyncManager.hasGroup(selected_text):
|
||||||
print("DEBUG: Adding sprite ID ", currentSprite.id, " to group '", selected_text, "'")
|
|
||||||
WobbleSyncManager.addSpriteToGroup(currentSprite.id, selected_text)
|
WobbleSyncManager.addSpriteToGroup(currentSprite.id, selected_text)
|
||||||
# Refresh sprite editor to show updated wobble values
|
# Refresh sprite editor to show updated wobble values
|
||||||
if Global.spriteEdit:
|
if Global.spriteEdit:
|
||||||
Global.spriteEdit.setImage()
|
Global.spriteEdit.setImage()
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Group '", selected_text, "' not found or WobbleSyncManager not available")
|
pass # Group doesn't exist
|
||||||
|
|
||||||
updateSyncIndicator()
|
updateSyncIndicator()
|
||||||
|
|
||||||
## Handle create group dialog confirmation
|
## Handle create group dialog confirmation
|
||||||
func _on_create_group_confirmed():
|
func _on_create_group_confirmed():
|
||||||
var group_name = groupNameInput.text.strip_edges()
|
var group_name = groupNameInput.text.strip_edges()
|
||||||
print("DEBUG: Create group confirmed with name: '", group_name, "'")
|
|
||||||
|
|
||||||
if group_name == "":
|
if group_name == "":
|
||||||
print("DEBUG: Group name is empty")
|
|
||||||
Global.pushUpdate("Group name cannot be empty")
|
Global.pushUpdate("Group name cannot be empty")
|
||||||
return
|
return
|
||||||
|
|
||||||
if WobbleSyncManager and WobbleSyncManager.hasGroup(group_name):
|
if WobbleSyncManager and WobbleSyncManager.hasGroup(group_name):
|
||||||
print("DEBUG: Group '", group_name, "' already exists")
|
|
||||||
Global.pushUpdate("Group \"" + group_name + "\" already exists")
|
Global.pushUpdate("Group \"" + group_name + "\" already exists")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create group with current sprite
|
# Create group with current sprite
|
||||||
if currentSprite != null and WobbleSyncManager:
|
if currentSprite != null and WobbleSyncManager:
|
||||||
print("DEBUG: Creating group '", group_name, "' with sprite ID ", currentSprite.id)
|
|
||||||
if WobbleSyncManager.createGroup(group_name, currentSprite.id):
|
if WobbleSyncManager.createGroup(group_name, currentSprite.id):
|
||||||
print("DEBUG: Group created successfully")
|
|
||||||
createGroupDialog.hide()
|
createGroupDialog.hide()
|
||||||
updateUI()
|
updateUI()
|
||||||
# Refresh sprite editor to show sync status
|
# Refresh sprite editor to show sync status
|
||||||
if Global.spriteEdit:
|
if Global.spriteEdit:
|
||||||
Global.spriteEdit.setImage()
|
Global.spriteEdit.setImage()
|
||||||
else:
|
else:
|
||||||
print("DEBUG: Failed to create group")
|
pass # Failed to create group
|
||||||
else:
|
else:
|
||||||
print("DEBUG: No current sprite to add to group")
|
pass # No sprite or WobbleSyncManager not available
|
||||||
|
|
||||||
## Handle create group dialog cancellation
|
## Handle create group dialog cancellation
|
||||||
func _on_create_group_cancelled():
|
func _on_create_group_cancelled():
|
||||||
@@ -203,5 +187,4 @@ func canSync() -> bool:
|
|||||||
|
|
||||||
## Force refresh the UI - useful after loading saves
|
## Force refresh the UI - useful after loading saves
|
||||||
func forceRefresh():
|
func forceRefresh():
|
||||||
print("DEBUG: WobbleSyncControl.forceRefresh called")
|
|
||||||
updateUI()
|
updateUI()
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ extends NinePatchRect
|
|||||||
|
|
||||||
@onready var spritePreview = $SpritePreview/Sprite2D
|
@onready var spritePreview = $SpritePreview/Sprite2D
|
||||||
@onready var outline = $Selected
|
@onready var outline = $Selected
|
||||||
|
|
||||||
|
|
||||||
@onready var fade = $Fade
|
@onready var fade = $Fade
|
||||||
|
@onready var button = $Button
|
||||||
|
@onready var label = $Label
|
||||||
|
|
||||||
var sprite = null
|
var sprite = null
|
||||||
var parent = null
|
var parent = null
|
||||||
@@ -14,9 +14,23 @@ var indent = 0
|
|||||||
var childrenTags = []
|
var childrenTags = []
|
||||||
var parentTag = null
|
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():
|
func _ready():
|
||||||
var count = spritePath.get_slice_count("/") - 1
|
# Use displayName if available, otherwise fallback to path
|
||||||
$Label.text = spritePath.get_slice("/",count)
|
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
|
$Line2D.visible = false
|
||||||
|
|
||||||
spritePreview.texture = sprite.sprite.texture
|
spritePreview.texture = sprite.sprite.texture
|
||||||
@@ -25,6 +39,115 @@ func _ready():
|
|||||||
spritePreview.scale = Vector2(1,1) * (60.0/displaySize)
|
spritePreview.scale = Vector2(1,1) * (60.0/displaySize)
|
||||||
spritePreview.offset = sprite.sprite.offset
|
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():
|
func updateChildren():
|
||||||
for child in childrenTags:
|
for child in childrenTags:
|
||||||
|
|||||||
Reference in New Issue
Block a user