FunkPanion/scripts/xmle/form_handler.gd

513 lines
17 KiB
GDScript

extends Node
@onready var anims_tree = $"HSplitContainer/VSplitContainer/Animations"
@onready var frames_tree = $"HSplitContainer/VSplitContainer/Frames"
@onready var region_viewport = $"HSplitContainer/Region/RegionView/Viewport"
@onready var rg_oskin_prev_char = $"HSplitContainer/Region/RegionView/Viewport/ReferenceRect/OSPrevCharacter"
@onready var rg_oskin_next_char = $"HSplitContainer/Region/RegionView/Viewport/ReferenceRect/OSNextCharacter"
@onready var frame_count = $"HSplitContainer/VSplitContainer/Animations/frame_count"
@onready var sprite_size = $"HSplitContainer/VSplitContainer/Animations/sprite_size"
@onready var region_pos = $"HSplitContainer/Region/Controls/region_pos"
@onready var region_size = $"HSplitContainer/Region/Controls/region_size"
@onready var sprite_offset = $"HSplitContainer/Region/Controls/sprite_offset"
@onready var align_all = $"HSplitContainer/VSplitContainer/Frames/align_all"
@onready var oskin = $"HSplitContainer/VSplitContainer/Frames/oskin"
@onready var menu = $"../Menu/HBoxContainer"
@onready var close_icon = load("res://assets/icons/close.png")
@onready var frames_open_icon = load("res://assets/icons/frames_open.png")
@onready var frame_open_icon = load("res://assets/icons/frame_open.png")
@onready var arrow_up_icon = load("res://assets/icons/arrow_up.png")
@onready var arrow_down_icon = load("res://assets/icons/arrow_down.png")
var spritesheet_parser: SpritesheetParser = SpritesheetParser.new()
var preview_image:ImageTexture
var process_image:Image
var spritesheet_animations:Array = []
var spritesheet_size:Vector2i = Vector2i.ZERO
var spritesheet_frames:int = 0
var selected_animation:int = 0
var selected_frame:int = 0
var image_path = GlobalConfig.spritesheet_image
var data_path = GlobalConfig.spritesheet_data
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
region_viewport.size_changed.connect(func():
frame.position = (region_viewport.size / 2) - Vector2i(frame.size / 2)
)
link_range_to_callable(frame_count, func(val: int):
for animation in spritesheet_animations:
spritesheet_frames = val
if selected_frame >= spritesheet_frames:
selected_frame = spritesheet_frames - 1
animation.frames.resize(spritesheet_frames)
set_frames_tree()
, spritesheet_frames)
link_pos_to_callable_e(sprite_size, func(_val: int):
spritesheet_size = get_vector(sprite_size)
set_region_view()
)
link_pos_to_callable_e(region_pos, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("pos", get_vector(region_pos))
set_region_view()
)
link_pos_to_callable_e(region_size, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("size", get_vector(region_size))
set_region_view()
update_current_frame_child()
)
link_pos_to_callable_e(sprite_offset, func(_val: int):
if ts_dont_change_internal: return
set_property_on_current_frame("frame_pos", get_vector(sprite_offset))
set_region_view()
)
var rs_autocrop:Button = region_size.get_node("autocrop")
rs_autocrop.pressed.connect(func():
var pos = get_property_on_current_frame("pos")
var size = get_property_on_current_frame("size")
var cropped_image = process_image.get_region(Rect2i(pos, size))
var flood_fill_result = cropped_image.get_used_rect()
set_property_on_current_frame("pos", flood_fill_result.position + pos)
set_property_on_current_frame("size", flood_fill_result.size)
update_current_frame_child()
set_region_view()
set_three_stooges()
)
var aa_autocrop:Button = align_all.get_node("autocrop")
aa_autocrop.pressed.connect(func():
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
for cur_frame in cur_anim.frames:
if cur_frame == null: continue
var cropped_image = process_image.get_region(Rect2i(cur_frame.pos, cur_frame.size))
var flood_fill_result = cropped_image.get_used_rect()
cur_frame.pos = (flood_fill_result.position + cur_frame.pos).max(cur_frame.pos)
cur_frame.size = flood_fill_result.size.min(cur_frame.size)
set_frames_tree()
set_region_view()
set_three_stooges()
)
var so_preset:MenuButton = sprite_offset.get_node("preset")
var sopre_pop:PopupMenu = so_preset.get_popup()
sopre_pop.index_pressed.connect(func(idx: int):
var frame_size = get_property_on_current_frame("size")
if frame_size == null: return
set_property_on_current_frame("frame_pos", align_to_vector(idx, frame_size, spritesheet_size))
set_region_view()
set_three_stooges()
)
var aa_preset:MenuButton = align_all.get_node("preset")
var aapre_pop:PopupMenu = aa_preset.get_popup()
aapre_pop.index_pressed.connect(func(idx: int):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
for cur_frame in cur_anim.frames:
if cur_frame == null: continue
cur_frame.frame_pos = align_to_vector(idx, cur_frame.size, spritesheet_size)
set_region_view()
set_three_stooges()
)
var oskin_prev:CheckBox = oskin.get_node("prev")
var oskin_next:CheckBox = oskin.get_node("next")
oskin_prev.toggled.connect(func(on:bool):
rg_oskin_prev_char.visible = on
)
oskin_next.toggled.connect(func(on:bool):
rg_oskin_next_char.visible = on
)
var load = menu.get_node("Load")
load.load_image.connect(func(path):
image_path = path
init_form_image()
)
load.load_xml.connect(func(path):
data_path = path
init_form_xml()
)
var save = menu.get_node("Save")
save.pressed.connect(func():
var xml = spritesheet_parser.spritesheet_to_xml(spritesheet_animations, spritesheet_size, image_path)
save.save(xml)
)
fuck_with_frames_tree()
fuck_with_anims_tree()
init_form_image()
init_form_xml()
func init_form_xml() -> void:
spritesheet_parser.parse_spritesheet(data_path)
spritesheet_size = spritesheet_parser.max_dimensions
spritesheet_animations = []
spritesheet_frames = 0
for animation in spritesheet_parser.spritesheet:
var frames = spritesheet_parser.spritesheet[animation]
for fr_ame in frames:
fr_ame.frame_pos = -fr_ame.frame_pos
fr_ame.erase("frame_size")
spritesheet_frames = max(frames.size(), spritesheet_frames)
spritesheet_animations.append({
name = animation,
frames = frames
})
for animation in spritesheet_animations:
animation.frames.resize(spritesheet_frames)
var ct:Range = frame_count.get_node("value")
ct.value = spritesheet_frames
set_vector(sprite_size, spritesheet_size)
set_frames_tree()
set_anims_tree()
func init_form_image() -> void:
process_image = SpritesheetParser.load_image(image_path)
preview_image = ImageTexture.create_from_image(process_image)
fuck_with_region_view()
func align_to_vector(idx:int, cs:Vector2i, ps:Vector2i) -> Vector2i:
var vector = Vector2i.ZERO
match idx:
1, 4, 7:
vector.x = (ps.x / 2) - (cs.x / 2)
2, 5, 8:
vector.x = ps.x - cs.x
match idx:
3, 4, 5:
vector.y = (ps.y / 2) - (cs.y / 2)
6, 7, 8:
vector.y = ps.y - cs.y
return vector
func link_range_to_callable(obj:BoxContainer, callable:Callable, value) -> void:
var input:Range = obj.get_node("value")
input.value = value
input.value_changed.connect(callable)
func set_vector(obj:BoxContainer, vector:Vector2) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value = vector.x
y.value = vector.y
func get_vector(obj:BoxContainer) -> Vector2:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
return Vector2(x.value, y.value)
func link_pos_to_callable(obj:BoxContainer, callable:Callable, value:Vector2i) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value = value.x
y.value = value.y
x.value_changed.connect(callable)
y.value_changed.connect(callable)
func link_pos_to_callable_e(obj:BoxContainer, callable:Callable) -> void:
var x:Range = obj.get_node("value_w")
var y:Range = obj.get_node("value_h")
x.value_changed.connect(callable)
y.value_changed.connect(callable)
var dont_change_internal = false
func fuck_with_anims_tree() -> void:
var tree:Tree = anims_tree.get_node("Tree")
var add_new_name:LineEdit = anims_tree.get_node("AddNew/name")
var add_new_switch:Button = anims_tree.get_node("AddNew/switch")
var tree_root = tree.create_item()
tree.button_clicked.connect(func(item:TreeItem, column:int, id:int, _mbi):
var item_index = item.get_index()
if column == 0:
if id == 0:
spritesheet_animations.remove_at(item_index)
if selected_animation == item_index:
selected_animation = max(item_index - 1, 0)
if selected_animation > -1:
tree.set_selected(tree_root.get_child(selected_animation), 0)
set_anims_tree()
set_frames_tree()
)
tree.item_selected.connect(func():
if dont_change_internal:
dont_change_internal = false
return
var item = tree.get_selected()
selected_animation = item.get_index()
set_frames_tree()
)
add_new_switch.pressed.connect(func():
var text = add_new_name.text
if text.length() < 1:
return
for anim in spritesheet_animations:
if anim.name == text: return
var frames = []
frames.resize(spritesheet_frames)
spritesheet_animations.append({
name = text,
frames = frames
})
set_anims_tree()
add_new_name.text = ""
)
func set_anims_tree() -> void:
var tree:Tree = anims_tree.get_node("Tree")
var tree_root = tree.get_root()
for child in tree_root.get_children():
child.free()
for animation in spritesheet_animations:
var child = tree.create_item(tree_root)
child.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
child.set_editable(0, false)
child.set_text(0, animation.name)
child.add_button(0, close_icon, 0)
dont_change_internal = true
tree.set_selected(tree_root.get_child(selected_animation), 0)
func fuck_with_frames_tree() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.create_item()
tree_root.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
tree_root.set_editable(0, false)
tree_root.set_text(0, "No animation selected")
tree.button_clicked.connect(func(item:TreeItem, column:int, id:int, _mbi):
var item_index = item.get_index()
var cur_anim = spritesheet_animations[selected_animation]
if item_index >= cur_anim.frames.size(): return
if column == 1:
var frame = cur_anim.frames[item_index]
var duplicate = Input.is_action_pressed("mod_enable")
if id == 0:
if item_index + 1 >= cur_anim.frames.size(): return
var next_frame = cur_anim.frames[item_index + 1]
var placeholder
if next_frame != null and not duplicate:
placeholder = next_frame.duplicate(false)
cur_anim.frames[item_index + 1] = frame
if next_frame != null and not duplicate:
cur_anim.frames[item_index] = placeholder
if id == 1:
if item_index - 1 < 0: return
var prev_frame = cur_anim.frames[item_index - 1]
var placeholder = prev_frame.duplicate(false)
cur_anim.frames[item_index - 1] = frame
cur_anim.frames[item_index] = placeholder
set_frames_tree()
)
tree.item_edited.connect(func():
var text = tree_root.get_text(0)
if text.length() < 1:
tree_root.set_text(0, spritesheet_animations[selected_animation].name)
return
for anim in spritesheet_animations:
if anim.name == text:
tree_root.set_text(0, spritesheet_animations[selected_animation].name)
return
spritesheet_animations[selected_animation].name = text
set_anims_tree()
)
tree.item_selected.connect(func():
var item = tree.get_selected()
selected_frame = item.get_index()
set_region_view()
set_three_stooges()
)
func set_frames_tree() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.get_root()
tree_root.set_editable(0, false)
tree_root.set_text(0, "No animation selected")
for child in tree_root.get_children():
child.free()
if spritesheet_animations.size() <= selected_animation:
return
var cur_anim = spritesheet_animations[selected_animation]
tree_root.set_editable(0, true)
tree_root.set_text(0, cur_anim.name)
var frames = cur_anim.frames
for frame in spritesheet_frames:
var child = tree.create_item(tree_root)
child.set_cell_mode(0, TreeItem.CELL_MODE_STRING)
child.set_editable(0, false)
child.set_text(0, "Frame #" + str(frame + 1))
child.set_cell_mode(1, TreeItem.CELL_MODE_STRING)
child.set_editable(1, false)
child.set_text(1, "640x480")
child.set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT)
child.add_button(1, arrow_down_icon, 0)
child.add_button(1, arrow_up_icon, 1)
if frame >= frames.size() - 1:
child.set_button_disabled(1, 0, true)
if frame <= 0:
child.set_button_disabled(1, 1, true)
if frames.size() <= frame or frames[frame] == null:
child.set_text(1, "Empty")
child.set_button_disabled(1, 1, true)
child.set_button_disabled(1, 0, true)
else:
child.set_text(1, str(frames[frame].size.x) + "x" + str(frames[frame].size.y))
tree.set_selected(tree_root.get_child(selected_frame), 0)
set_region_view()
func update_current_frame_child() -> void:
var tree:Tree = frames_tree.get_node("Tree")
var tree_root = tree.get_root()
var current_frame = tree_root.get_child(selected_frame)
if spritesheet_animations.size() <= selected_animation:
return
var frames = spritesheet_animations[selected_animation].frames
var frame = selected_frame
if current_frame == null: return
if frames.size() <= frame or frames[frame] == null:
current_frame.set_text(1, "Empty")
else:
current_frame.set_text(1, str(frames[frame].size.x) + "x" + str(frames[frame].size.y))
func fuck_with_region_view() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
var character:TextureRect = frame.get_node("Character")
character.texture.atlas = preview_image
rg_oskin_prev_char.texture.atlas = preview_image
rg_oskin_next_char.texture.atlas = preview_image
func set_region_view() -> void:
var frame:ReferenceRect = region_viewport.get_node("ReferenceRect")
var character:TextureRect = frame.get_node("Character")
var character_frame:ReferenceRect = frame.get_node("ReferenceRect")
var atlas:AtlasTexture = character.texture
if spritesheet_animations.size() <= selected_animation:
rg_oskin_prev_char.position = Vector2.ZERO
rg_oskin_prev_char.texture.region = Rect2(0,0,1,1)
rg_oskin_next_char.position = Vector2.ZERO
rg_oskin_next_char.texture.region = Rect2(0,0,1,1)
character.position = Vector2.ZERO
character_frame.position = Vector2.ZERO
character_frame.size = Vector2.ZERO
atlas.region = Rect2(0,0,1,1)
return
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < selected_frame or cur_anim.frames[selected_frame] == null:
character.position = Vector2.ZERO
character_frame.position = Vector2.ZERO
character_frame.size = Vector2.ZERO
atlas.region = Rect2(0,0,1,1)
return
var cur_frame = cur_anim.frames[selected_frame]
if selected_frame - 1 < 0 or cur_anim.frames[selected_frame - 1] == null:
rg_oskin_prev_char.position = Vector2.ZERO
rg_oskin_prev_char.texture.region = Rect2(0,0,1,1)
else:
var prev_frame = cur_anim.frames[selected_frame - 1]
rg_oskin_prev_char.position = prev_frame.frame_pos
rg_oskin_prev_char.texture.region = Rect2(prev_frame.pos, prev_frame.size)
if selected_frame + 1 >= cur_anim.frames.size() or cur_anim.frames[selected_frame + 1] == null:
rg_oskin_next_char.position = Vector2.ZERO
rg_oskin_next_char.texture.region = Rect2(0,0,1,1)
else:
var next_frame = cur_anim.frames[selected_frame + 1]
rg_oskin_next_char.position = next_frame.frame_pos
rg_oskin_next_char.texture.region = Rect2(next_frame.pos, next_frame.size)
character.position = cur_frame.frame_pos
character_frame.position = cur_frame.frame_pos
character_frame.size = cur_frame.size
atlas.region = Rect2(cur_frame.pos, cur_frame.size)
frame.size = spritesheet_size
frame.position = (region_viewport.size / 2) - Vector2i(frame.size / 2)
var ts_dont_change_internal = false
func set_three_stooges() -> void:
var character:TextureRect = region_viewport.get_node("ReferenceRect/Character")
var atlas:AtlasTexture = character.texture
ts_dont_change_internal = true
set_vector(region_pos, atlas.region.position)
set_vector(region_size, atlas.region.size)
set_vector(sprite_offset, character.position)
ts_dont_change_internal = false
func get_property_on_current_frame(prop:String):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return null
var cur_frame = cur_anim.frames[selected_frame]
if cur_frame == null: return null
return cur_frame[prop]
func set_property_on_current_frame(prop:String, value:Variant):
var cur_anim = spritesheet_animations[selected_animation]
if cur_anim.frames.size() < 1: return
var cur_frame = cur_anim.frames[selected_frame]
if cur_frame == null:
cur_anim.frames[selected_frame] = {
pos = Vector2.ZERO,
size = Vector2.ONE,
frame_pos = Vector2.ZERO
}
cur_frame = cur_anim.frames[selected_frame]
cur_frame[prop] = value