diff --git a/addons/escoria-wizard/BackgroundItem.gd b/addons/escoria-wizard/BackgroundItem.gd new file mode 100644 index 00000000..7e0a853b --- /dev/null +++ b/addons/escoria-wizard/BackgroundItem.gd @@ -0,0 +1,139 @@ +tool +extends MarginContainer + +var source_image:Image +var image_stream_texture:StreamTexture +var image_has_been_loaded:bool +var image_size:Vector2 + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + background_item_reset() + + +func background_item_reset() -> void: + $Content/GridContainer/ItemName.text = "replace_me" + $Content/GridContainer/ItemGlobalID.text = "" + $Content/GridContainer/StartsInnteractiveCheckBox.pressed = true + if $Content/GridContainer/DefaultActionOption.get_item_count() > 0: + $Content/GridContainer/DefaultActionOption.clear() + for option_list in ["look", "pick up", "open", "close", "use", "push", "pull", "talk"]: + $Content/GridContainer/DefaultActionOption.add_item(option_list) + $Content/GridContainer/DefaultActionOption.selected = 0 + image_size = Vector2.ZERO + image_has_been_loaded = false + + +func background_on_ItemName_text_changed(new_text: String) -> void: + $Content/GridContainer/ItemGlobalID.text = new_text + + +func load_button_pressed() -> void: + $LoadObjectGraphic/LoadObjectFileDialog.popup() + + +func LoadObjectFileDialog_file_selected(path: String) -> void: + image_stream_texture = load(path) + + $Content/GridContainer/Preview/Preview.texture = image_stream_texture + + var preview_size = $Content/GridContainer/Preview/Preview.rect_size + + # Calculate the scale to make the preview as big as possible in the preview window depending on + # the height to width ratio of the frame + image_size = image_stream_texture.get_size() + var preview_scale = Vector2.ONE + preview_scale.x = preview_size.x / image_size.x + preview_scale.y = preview_size.y / image_size.y + + if preview_scale.y > preview_scale.x: + $Content/GridContainer/Preview/Preview.rect_scale = Vector2(preview_scale.x, preview_scale.x) + else: + $Content/GridContainer/Preview/Preview.rect_scale = Vector2(preview_scale.y, preview_scale.y) + + $Content/GridContainer/ImageSize.text = "(%s, %s)" % [image_size.x, image_size.y] + + $Content/GridContainer/ImagePath.text = path + image_has_been_loaded = true + + + +func _on_CreateButton_pressed() -> void: + var err_window = "../InformationWindows/generic_error_window" + if ! image_has_been_loaded: + get_node(err_window).dialog_text = \ + "No image has been loaded." + get_node(err_window).popup() + return + if $Content/GridContainer/ItemName.text == "replace_me": + get_node(err_window).dialog_text = \ + "Please change the object name." + get_node(err_window).popup() + return + + var item = ESCItem.new() + item.name = $Content/GridContainer/ItemName.text + item.global_id = $Content/GridContainer/ItemGlobalID.text + item.is_interactive = $Content/GridContainer/StartsInnteractiveCheckBox.pressed + item.tooltip_name = $Content/GridContainer/ItemName.text + + var selected_index = $Content/GridContainer/DefaultActionOption.selected + item.default_action = $Content/GridContainer/DefaultActionOption.get_item_text(selected_index) + + # Add sprite to the background item + var item_sprite = Sprite.new() + item_sprite.texture = $Content/GridContainer/Preview/Preview.texture + item.add_child(item_sprite) + + # Add Dialog Position to the background item + var interact_position = ESCLocation.new() + interact_position.name = "interact_position" + interact_position.position.y = image_size.y * 2 + print("A") + item.add_child(interact_position) + + # Add Collision shape to the background item + var rectangle_shape = RectangleShape2D.new() + var collision_shape = CollisionShape2D.new() + + collision_shape.shape = rectangle_shape + collision_shape.shape.extents = image_size / 2 + print("B") + item.add_child(collision_shape) + print("c") + # Make it so all the nodes can be seen in the scene tree + interact_position.set_owner(item) + print("d") + collision_shape.set_owner(item) + print("e") + + item_sprite.set_owner(item) + + print("f") + +# get_tree().edited_scene_root.add_child(item) +# item.set_owner(get_tree().edited_scene_root) + + + var current_node = EditorPlugin.new().get_editor_interface().get_selection().get_selected_nodes()[0] +# print("Cur = "+str(current_node)) +# print("Cur0 = "+str(current_node[0])) + print("g") + + current_node.add_child(item) + print("h") + +# item.set_owner(current_node) + item.set_owner(get_tree().edited_scene_root) + print("Created.") + #item.queue_free() + +#func get_edited_root() -> Node: +# var plugin := EditorPlugin.new() +# var eds:EditorInterface +# eds = plugin.get_selection() +# var selected:EditorInterface +# selected = eds.get_selected_nodes()[0] +# if selected: +# return selected.get_tree().get_edited_scene_root() +# return null diff --git a/addons/escoria-wizard/CharacterCreator.gd b/addons/escoria-wizard/CharacterCreator.gd new file mode 100644 index 00000000..9d8c1601 --- /dev/null +++ b/addons/escoria-wizard/CharacterCreator.gd @@ -0,0 +1,1615 @@ +# Outstanding proposed features +# v1.1 features +# * Have the editor kick in when an ESCPlayer is selected, i.e. "load/edit" +# * Add a settings page (if there's enough features to warrant it). This would have the path the scene gets written to, default angles for each direction so the developer can change them from the default 90s / 45s they are now, whether the ESCPlayer is click-through, errr can't think of anything else. +# * Redo the Escoria tutorial to use the plugin. + +tool +extends Control + +const METADATA_ANIM_NAME = "anim_name" +const METADATA_SPRITESHEET_SOURCE_FILE = "spritesheet_source_file" +const METADATA_SPRITESHEET_FRAMES_HORIZ = "spritesheet_frames_horiz" +const METADATA_SPRITESHEET_FRAMES_VERT = "spritesheet_frames_vert" +const METADATA_SPRITESHEET_FIRST_FRAME = "spritesheet_first_frame" +const METADATA_SPRITESHEET_LAST_FRAME = "spritesheet_last_frame" +const METADATA_SPEED = "speed" +const METADATA_IS_MIRROR = "is_mirror" + +const DIR_UP = "up" +const DIR_UP_RIGHT = "upright" +const DIR_RIGHT = "right" +const DIR_DOWN_RIGHT = "downright" +const DIR_DOWN = "down" +const DIR_DOWN_LEFT = "downleft" +const DIR_LEFT = "left" +const DIR_UP_LEFT = "upleft" + +const DIR_LIST_8 = [DIR_UP, DIR_UP_RIGHT, DIR_RIGHT, DIR_DOWN_RIGHT, DIR_DOWN, DIR_DOWN_LEFT, \ + DIR_LEFT, DIR_UP_LEFT] + +const DIR_LIST_4 = [DIR_UP, DIR_RIGHT, DIR_DOWN, DIR_LEFT] + +const TYPE_WALK = "walk" +const TYPE_TALK = "talk" +const TYPE_IDLE = "idle" + +const ANIM_IN_PROGRESS = "in_progress" + +const ANIMATION_SPEED_LABEL = "Animation speed" + +# Make the code more readable by shortening node references using constants +const NAME_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer" +const DIR_COUNT_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/HBoxContainer" +const ANIM_TYPE_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer" +const MIRROR_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer3/mirror_checkbox" +const ARROWS_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer" +const PREVIEW_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview/MarginContainer" +const PREVIEW_BGRND_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview/anim_preview_background" +const ANIM_CONTROLS_NODE = "VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer" +const STORE_ANIM_NODE = "VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim" +const SCROLL_VBOX_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/" +const SCROLL_CTRL_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control" +const NO_SPRITESHEET_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control/MarginContainer/no_spritesheet_found_sprite" +const CURRENT_SHEET_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_current/MarginContainer2/current_spritesheet_label" +const ZOOM_LABEL_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll/zoom_label" +const ZOOM_SCROLL_NODE = "VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll/MarginContainer/zoom_scrollbar" +const CHARACTER_PATH_NODE = "VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer/character_path" +const GENERIC_ERROR_NODE = "InformationWindows/generic_error_window" +const UNSTORED_CHANGE_NODE = "InformationWindows/unstored_changes_window" +const UNSTORED_ANIMTYPE_CHANGE_NODE = "InformationWindows/unstored_changes_window_anim_change" +const EXPORT_PROGRESS_NODE = "InformationWindows/export_progress" +const PROGRESS_LABEL_NODE = "InformationWindows/export_progress/progress_label" +const EXPORT_COMPLETE_NODE = "InformationWindows/export_complete" +const FILE_DIALOG_NODE = "ImageFileDialog" +const CHARACTER_FILE_NODE = "CharacterPathFileDialog" +const CONFIG_FILE = "escoria-wizard.conf" + + +# Test flag - set to true to load test data. +var test_mode: bool = false + +# The currently loaded spritesheet image +var source_image: Image + +# The current size of each animation frame (the spritesheet is broken into squares of this size. +var frame_size: Vector2 + +# The current spritesheet zoom level. +var zoom_value: float = 1 + +# The speed of the animation being previewed in frames-per-second. +var current_animation_speed: int = 5 + +# The animation direction currently being edited +var direction_selected: String + +# This is the animation direction that has been clicked on by the user. +# Once it has been confirmed that there are no unstored changes to the current animation, +# the requested direction will become the "direction_selected". +var direction_requested: String + +# The animation type currently being edited +var animation_type_selected: String + +# This is the animation ty[e that has been clicked on by the user. +# Once it has been confirmed that there are no unstored changes to the current animation, +# the requested type will become the "animation_type_selected". +var animation_type_requested: String + +# This is the array that stores the data for each animation. +var anim_metadata = [] + +# Track the page showing in the help window +var help_window_page = 1 + +# Array to track frame settings so if you do an illegal action (like changing the last sprite frame +# prior to a spritesheet being loaded) the value can be reset +var spritesheet_settings = [1, 1, 0, 0] + +# To stop errors flagging when you change to a mirrored direction +var currently_changing_direction: bool = false + +# Whether all changes are automatically 'saved' or need manual confirmation before storing +var autostore: bool = false + +# Needed due to the yield method used for export to pass back the largest sprite used +# for the character. This will determine the collision shape size. +var export_largest_sprite: Vector2 + + +func _ready() -> void: + load_settings() + character_creator_reset() + $InformationWindows/help_window.current_page = 1 + + if test_mode: + setup_test_data() + + +func character_creator_reset() -> void: + # Disconnect all the signals to stop program logic firing during setup + disconnect_selector_signals() + + get_node(NAME_NODE).get_node("node_name").text = "replace_me" + get_node(NAME_NODE).get_node("global_id").text = "" + get_node(DIR_COUNT_NODE).get_node("four_directions").pressed = true + + # For unknown reasons the above doesn't cause the trigger to fire so manual steps required + if get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed: + get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed = false + + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = true + animation_type_selected = "walk" + + # For unknown reasons the above doesn't cause the trigger to fire so manual steps required + if get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed: + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = false + + if get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed: + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = false + + get_node(NO_SPRITESHEET_NODE).visible = true + zoom_value = 1 + get_node(ZOOM_SCROLL_NODE).value = zoom_value + get_node(ZOOM_LABEL_NODE).text = "Zoom: %sx" % str(zoom_value) + get_node(ANIM_CONTROLS_NODE).get_node("original_size_label").text = "Source sprite size: (0, 0)" + get_node(ANIM_CONTROLS_NODE).get_node("frame_size_label").text = "Frame size: (0, 0)" + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").animation = ANIM_IN_PROGRESS + + preview_hide() + + get_node(STORE_ANIM_NODE).visible = false + + create_empty_animations() + + direction_selected = DIR_UP + activate_direction(direction_selected) + + reset_arrow_colours() + + # Reset GUI controls to initial values + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = spritesheet_settings[0] + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = spritesheet_settings[1] + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = spritesheet_settings[2] + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = spritesheet_settings[3] + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value = current_animation_speed + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_label").text = "%s: 5 FPS" % ANIMATION_SPEED_LABEL + get_node(CURRENT_SHEET_NODE).text="No spritesheet loaded." + # Connect all the signals now the base settings are configured to stop program logic firing during setup + reset_frame_outlines() + + # Make sure help window doesn't swallow mouse input + $InformationWindows.visible = false + autostore = $VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/HBoxContainer/AutoStoreCheckBox.pressed + connect_selector_signals() + + +func connect_selector_signals() -> void: + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").connect("value_changed", self, "controls_on_h_frames_spin_box_value_changed") + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").connect("value_changed", self, "controls_on_v_frames_spin_box_value_changed") + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").connect("value_changed", self, "controls_on_start_frame_value_changed") + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").connect("value_changed", self, "controls_on_end_frame_value_changed") + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").connect("value_changed", self, "controls_on_anim_speed_scroll_bar_value_changed") + + +func disconnect_selector_signals() -> void: + if get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").is_connected("value_changed", self, "controls_on_h_frames_spin_box_value_changed"): + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").disconnect("value_changed", self, "controls_on_h_frames_spin_box_value_changed") + + if get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").is_connected("value_changed", self, "controls_on_v_frames_spin_box_value_changed"): + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").disconnect("value_changed", self, "controls_on_v_frames_spin_box_value_changed") + + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").is_connected("value_changed", self, "controls_on_start_frame_value_changed"): + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").disconnect("value_changed", self, "controls_on_start_frame_value_changed") + + if get_node(ANIM_CONTROLS_NODE).get_node("end_frame").is_connected("value_changed", self, "controls_on_end_frame_value_changed"): + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").disconnect("value_changed", self, "controls_on_end_frame_value_changed") + + if get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").is_connected("value_changed", self, "controls_on_anim_speed_scroll_bar_value_changed"): + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").disconnect("value_changed", self, "controls_on_anim_speed_scroll_bar_value_changed") + + +func reset_frame_outlines() -> void: + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").zoom_factor = .01 + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").total_num_columns = 1 + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").total_num_rows = 1 + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").start_cell = 0 + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").end_cell = 0 + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").cell_size = Vector2(1,1) + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").update() + + +func calc_sprite_size() -> void: + var source_size = source_image.get_size() + var horiz_size = int(source_size.x / get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value) + var vert_size = int(source_size.y / get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value) + + frame_size = Vector2(horiz_size, vert_size) + + get_node(ANIM_CONTROLS_NODE).get_node("original_size_label").text = "Source sprite size: %s" % source_size + get_node(ANIM_CONTROLS_NODE).get_node("frame_size_label").text = "Frame size: %s" % frame_size + + +# Load test data - primarily for testing export, but also for testing general functionality. +# Different spritesheets, mirroring settings, frame counts, and speeds are used deliberately. +func setup_test_data() -> void: +# load_spritesheet("res://addons/escoria-wizard/graphics/mark-animtest.png") +# # Up, right, down, left, up/r, down/r, down/l, up/l +# var start_frames = [15, 10, 7, 10, 12, 14, 1, 14, 12, 3, 1, 1] +# var end_frames = [17, 14, 9, 14, 13, 18, 3, 18, 12, 3, 1, 22] +# var mirrored = [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,] +# var sourcefile = [0, 0, 0, 0, 2, 2, 1, 2, 2, 0, 0, 0] +# var fps = [3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3] +# +# for loop in range(12): # 12 for a 4 direction character, 24 for an 8 direction character +# if sourcefile[loop] == 0: +# anim_metadata[loop * 2][METADATA_SPRITESHEET_SOURCE_FILE] = "res://addons/escoria-wizard/graphics/mark-animtest.png" +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_HORIZ] = 8 +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_VERT] = 3 +# elif sourcefile[loop] == 1: +# anim_metadata[loop * 2][METADATA_SPRITESHEET_SOURCE_FILE] = "res://game/characters/mark/png/mark_talk_down.png" +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_HORIZ] = 3 +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_VERT] = 1 +# else: +# anim_metadata[loop * 2][METADATA_SPRITESHEET_SOURCE_FILE] = "res://game/characters/mark/png/markjester_talk.png" +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_HORIZ] = 21 +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FRAMES_VERT] = 1 +# +# anim_metadata[loop * 2][METADATA_SPRITESHEET_FIRST_FRAME] = start_frames[loop] +# anim_metadata[loop * 2][METADATA_SPRITESHEET_LAST_FRAME] = end_frames[loop] +# anim_metadata[loop * 2][METADATA_SPEED] = fps[loop] +# +# anim_metadata[loop * 2][METADATA_IS_MIRROR] = mirrored[loop] != 0 +# +# get_node(NO_SPRITESHEET_NODE).visible = false +# +# reset_arrow_colours() + # Up, right, down, left, up/r, down/r, down/l, up/l + var spritebase:String="addons/escoria-wizard/graphics/robot" +# load_spritesheet("" + $spritepath + "/walk_up.png") + var start_frames = [1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 5,6,4,3,1,2,4,6] + var end_frames = [16,16,16,16,16,16,16,16, 53,53,53,53,53,53,53,53, 5,6,4,3,1,2,4,6] + var mirrored = [0,0,0,0,0,0,1,1, 0,0,0,0,0,0,1,1, 0,1,1,0,0,0,0,0] + var frames_h = [16,16,16,16,16,16,16,16, 14,14,14,14,14,14,14,14, 6,6,6,6,6,6,6,6] + var frames_v = [1,1,1,1,1,1,1,1, 4,4,4,4,4,4,4,4, 1,1,1,1,1,1,1,1] + + anim_metadata[0][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_up.png" + anim_metadata[1][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_upright.png" + anim_metadata[2][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_right.png" + anim_metadata[3][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_downright.png" + anim_metadata[4][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_down.png" + anim_metadata[5][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_downleft.png" + anim_metadata[6][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_right.png" + anim_metadata[7][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/walk_upright.png" + + anim_metadata[8][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_up.png" + anim_metadata[9][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_upright.png" + anim_metadata[10][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_right.png" + anim_metadata[11][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_downright.png" + anim_metadata[12][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_down.png" + anim_metadata[13][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_downleft.png" + anim_metadata[14][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_right.png" + anim_metadata[15][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/talk_upright.png" + + anim_metadata[16][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[17][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[18][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[19][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[20][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[21][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[22][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + anim_metadata[23][METADATA_SPRITESHEET_SOURCE_FILE] = spritebase + "/idle_all.png" + + for loop in range(24): + anim_metadata[loop][METADATA_SPRITESHEET_FIRST_FRAME] = start_frames[loop] + anim_metadata[loop][METADATA_SPRITESHEET_LAST_FRAME] = end_frames[loop] + anim_metadata[loop][METADATA_SPEED] = 24 + anim_metadata[loop][METADATA_IS_MIRROR] = mirrored[loop] != 0 + anim_metadata[loop][METADATA_SPRITESHEET_FRAMES_HORIZ] = frames_h[loop] + anim_metadata[loop][METADATA_SPRITESHEET_FRAMES_VERT] = frames_v[loop] + + get_node(NO_SPRITESHEET_NODE).visible = false + get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed = true + get_node(DIR_COUNT_NODE).get_node("four_directions").pressed = false + reset_arrow_colours() + + +# Animations are stored as metadata in an array. This creates the initial empty array. +# The preview animation ("in_progress") is the only sprite animation created prior to the final export. +func create_empty_animations() -> void: + var sframes = SpriteFrames.new() + + var metadata_dict = { + METADATA_ANIM_NAME: "tbc", + METADATA_SPRITESHEET_SOURCE_FILE: "tbc", + METADATA_SPRITESHEET_FRAMES_HORIZ: -1, + METADATA_SPRITESHEET_FRAMES_VERT: -1, + METADATA_SPRITESHEET_FIRST_FRAME: 0, + METADATA_SPRITESHEET_LAST_FRAME: 0, + METADATA_SPEED: 30, + METADATA_IS_MIRROR: false + } + + var local_dict + + anim_metadata.clear() + + for typeloop in [TYPE_WALK, TYPE_TALK, TYPE_IDLE]: + for dirloop in DIR_LIST_8: + local_dict = metadata_dict.duplicate() + local_dict[METADATA_ANIM_NAME] = "%s_%s" % [typeloop, dirloop] + anim_metadata.append(local_dict) + + sframes.add_animation(ANIM_IN_PROGRESS) + + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").frames = sframes + + +# Loads a spritesheet and calculates the size of each sprite frame if loading a spritesheet +# to show a previously stored animation. +func load_spritesheet(file_to_load, read_settings_from_metadata: bool = false, metadata_frame: int = 0) -> void: + if source_image == null: + source_image = Image.new() + + var errorval = source_image.load(file_to_load) + + assert(not errorval, "Error loading file %s" % str(file_to_load)) + + var texture = ImageTexture.new() + texture.create_from_image(source_image) + texture.set_flags(2) + + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").texture = texture + + frame_size = source_image.get_size() + + if read_settings_from_metadata: + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = anim_metadata[metadata_frame][METADATA_SPRITESHEET_FRAMES_HORIZ] + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = anim_metadata[metadata_frame][METADATA_SPRITESHEET_FRAMES_VERT] + else: + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = 1 + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = 1 + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = 1 + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = 1 + + calc_sprite_size() + + get_node(CURRENT_SHEET_NODE).text = file_to_load + draw_frame_outlines() + set_zoom_scale_automatically(source_image.get_size()) + + # Make scroll bars appear if necessary + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_min_size = source_image.get_size() * zoom_value + + +# spritesheet is loaded. +func set_zoom_scale_automatically(spritesheet_size) -> void: + + var available_space = get_node(SCROLL_VBOX_NODE).get_node("spritesheet_scroll_container").rect_size + + # Calculate the scale to make the preview as big as possible in the preview window depending on + # the height to width ratio of the frame + var spritesheet_scale = Vector2.ONE + spritesheet_scale.x = available_space.x / spritesheet_size.x + spritesheet_scale.y = available_space.y / spritesheet_size.y + var blah = Vector2.ONE + blah.x = spritesheet_size.x / available_space.x + blah.y = spritesheet_size.y / available_space.y + + var newscale = 0.0 + if spritesheet_scale.y > spritesheet_scale.x: + # Round to 1 decimal place + newscale = (int(spritesheet_scale.x * 10.0)) / 10.0 + else: + # Round to 1 decimal place + newscale = (int(spritesheet_scale.y * 10.0)) / 10.0 + if newscale < 0.1: + newscale = 0.1 + if newscale > 5: + newscale = 5 + get_node(ZOOM_SCROLL_NODE).value = newscale + + +# Draws an outline on the spritesheet to show which frames are included in the current animation +func draw_frame_outlines() -> void: + check_frame_limits() + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").zoom_factor = zoom_value + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").total_num_columns = get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").total_num_rows = get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").start_cell = get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").end_cell = get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").cell_size = frame_size + get_node(SCROLL_CTRL_NODE).get_node("frame_rectangles").update() + + +# When given a frame number, this calculates the pixel coordinates that frame in the spritesheet +# based on the number of horizontal/vertical frames configured for this spritesheet +func calc_frame_coords(Frame: int) -> Vector2: + var column = (Frame - 1) % int(get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value) * frame_size.x + var row = int((Frame - 1) / get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value) * frame_size.y + return Vector2(column, row) + + +# Updates the animation metadata to store the changed / new settings for a particular animation +func store_animation(animation_to_store: String) -> void: + var texture + var rect_location + var frame_being_copied = Image.new() + var frame_counter: int = 0 + + var metadata_dict = { + METADATA_ANIM_NAME: animation_to_store, + METADATA_SPRITESHEET_SOURCE_FILE: get_node(CURRENT_SHEET_NODE).text, + METADATA_SPRITESHEET_FRAMES_HORIZ: get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value, + METADATA_SPRITESHEET_FRAMES_VERT: get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value, + METADATA_SPRITESHEET_FIRST_FRAME: get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value, + METADATA_SPRITESHEET_LAST_FRAME: get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value, + METADATA_SPEED: get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value, + METADATA_IS_MIRROR: get_node(MIRROR_NODE).pressed + } + + var metadata_array_offset: int = get_metadata_array_offset() + + anim_metadata[metadata_array_offset] = metadata_dict + + if direction_selected == DIR_UP or direction_selected == DIR_DOWN: + return + + # If this direction has already been mirrored, replicate the changes + var opp_dir = find_opposite_direction(direction_selected) + var opp_metadata_array_offset: int = get_metadata_array_offset(opp_dir) + if anim_metadata[opp_metadata_array_offset][METADATA_IS_MIRROR]: + mirror_animation(direction_selected, opp_dir) + + +# Updates the metadata to mirror animation "source" to animation "dest" +# The "source" animation is the animation that really exists as sprite frames +# in the animated sprite +func mirror_animation(source: String, dest: String) -> void: + var texture + var rect_location + var frame_being_copied = Image.new() + var frame_counter: int = 0 +# + var metadata_source_offset = get_metadata_array_offset(source) + var current_anim_type = return_current_animation_type() + var dest_anim_name = "%s_%s" % [current_anim_type, dest] + + var metadata_dict = { + METADATA_ANIM_NAME: dest_anim_name, + METADATA_SPRITESHEET_SOURCE_FILE: anim_metadata[metadata_source_offset][METADATA_SPRITESHEET_SOURCE_FILE], + METADATA_SPRITESHEET_FRAMES_HORIZ: anim_metadata[metadata_source_offset][METADATA_SPRITESHEET_FRAMES_HORIZ], + METADATA_SPRITESHEET_FRAMES_VERT: anim_metadata[metadata_source_offset][METADATA_SPRITESHEET_FRAMES_VERT], + METADATA_SPRITESHEET_FIRST_FRAME: anim_metadata[metadata_source_offset][METADATA_SPRITESHEET_FIRST_FRAME], + METADATA_SPRITESHEET_LAST_FRAME: anim_metadata[metadata_source_offset][METADATA_SPRITESHEET_LAST_FRAME], + METADATA_SPEED: anim_metadata[metadata_source_offset][METADATA_SPEED], + METADATA_IS_MIRROR: true + } + + var metadata_dest_offset = get_metadata_array_offset(dest) + anim_metadata[metadata_dest_offset] = metadata_dict + disconnect_selector_signals() + reset_arrow_colours() + connect_selector_signals() + +func unmirror_animation(anim_to_unmirror: String) -> void: + var metadata_dict = { + METADATA_ANIM_NAME: "tbc", + METADATA_SPRITESHEET_SOURCE_FILE: "tbc", + METADATA_SPRITESHEET_FRAMES_HORIZ: -1, + METADATA_SPRITESHEET_FRAMES_VERT: -1, + METADATA_SPRITESHEET_FIRST_FRAME: 0, + METADATA_SPRITESHEET_LAST_FRAME: 0, + METADATA_SPEED: 30, + METADATA_IS_MIRROR: false + } + spritesheet_settings[2] = 0 + spritesheet_settings[3] = 0 + var metadata_dest_offset = get_metadata_array_offset(anim_to_unmirror) + anim_metadata[metadata_dest_offset] = metadata_dict + reset_arrow_colours() + + +# Shows the preview animation. Required as the no_anim_found sprite doesn't always cover the +# whole preview due to UI peculiarities. +func preview_show(): + get_node(PREVIEW_NODE).get_node("no_anim_found_sprite").visible = false + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").visible = true + + +# Hides the preview animation. Required when the no_anim_found sprite doesn't cover the +# whole preview due to UI peculiarities. +func preview_hide(): + get_node(PREVIEW_NODE).get_node("no_anim_found_sprite").visible = true + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").visible = false + + +# Creates the "in_progress" animation which is shown in the UI as the animation preview based +# on the currently selected settings. +# +# A mirrored animation (frames in reverse order and sprites horizontally flipped) is generated here +# for the purpose of the preview but isn't generated in the final export as it relies on ESCPlayer's +# is_mirrored setting. +func preview_update() -> void: + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value > 0: + check_frame_limits() + + var current_anim_type = return_current_animation_type() + var anim_name = "%s_%s" % [current_anim_type, direction_selected] + var offset = get_metadata_array_offset() + var generate_mirror = get_node(MIRROR_NODE).pressed + + var texture + var rect_location + var frame_being_copied = Image.new() + var frame_counter: int = 0 + + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").frames.clear(ANIM_IN_PROGRESS) + + frame_being_copied.create(frame_size.x, frame_size.y, false, source_image.get_format()) + + for loop in range(get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value - get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value + 1): + texture = ImageTexture.new() + rect_location = calc_frame_coords(get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value + loop) + frame_being_copied.blit_rect(source_image, Rect2(rect_location, Vector2(frame_size.x, frame_size.y)), Vector2(0, 0)) + + if generate_mirror: + frame_being_copied.flip_x() + + texture.create_from_image(frame_being_copied) + # Remove the image filter to make pixel correct graphics + texture.set_flags(2) + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").frames.add_frame(ANIM_IN_PROGRESS, texture, frame_counter) + frame_counter += 1 + preview_show() + + # Calculate the scale to make the preview as big as possible in the preview window depending on + # the height to width ratio of the frame + var preview_scale = Vector2.ONE + preview_scale.x = get_node(PREVIEW_BGRND_NODE).rect_size.x / frame_size.x + preview_scale.y = get_node(PREVIEW_BGRND_NODE).rect_size.y / frame_size.y + + if preview_scale.y > preview_scale.x: + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").scale = Vector2(preview_scale.x, preview_scale.x) + else: + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").scale = Vector2(preview_scale.y, preview_scale.y) + else: + preview_hide() + + +# Ensure that the spritesheet settings are valid +func check_frame_limits(): + var max_frame = get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value * get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value + + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value > max_frame: + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = max_frame + + if get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value > max_frame: + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = max_frame + + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value > get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value: + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value + +# If any spritesheet settings have changed, display the "store animation" button to save the changes. +# If the values are manually reset after a change to the previously stored settings, the button will disappear. +func check_if_controls_have_changed(): + var metadata_array_offset: int = get_metadata_array_offset() + var metadata_entry = anim_metadata[metadata_array_offset] + + if autostore == true: + return + + # Need to check this or it registers if you load a sprite and set the number of horizontal + # or vertical frames and haven't set a start/end frame yet + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value > 0: + get_node(STORE_ANIM_NODE).visible = \ + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value != metadata_entry[METADATA_SPEED] \ + or get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value != metadata_entry[METADATA_SPRITESHEET_FIRST_FRAME] \ + or get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value != metadata_entry[METADATA_SPRITESHEET_LAST_FRAME] \ + or get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value != metadata_entry[METADATA_SPRITESHEET_FRAMES_HORIZ] \ + or get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value != metadata_entry[METADATA_SPRITESHEET_FRAMES_VERT] + + +# If the user tries to change settings before they've loaded a spritesheet, this will display +# a warning window instead of letting them change settings. +func has_spritesheet_been_loaded() -> bool: + if source_image == null: + get_node(GENERIC_ERROR_NODE).dialog_text = "Please load a spritesheet to begin." + get_node(GENERIC_ERROR_NODE).popup() + return false + return true + + +func animation_on_dir_up_pressed() -> void: + check_activate_direction(DIR_UP) + + +# Runs when the direction arrow is clicked +func animation_on_dir_right_pressed() -> void: + check_activate_direction(DIR_RIGHT) + + +# Runs when the direction arrow is clicked +func animation_on_dir_left_pressed() -> void: + check_activate_direction(DIR_LEFT) + + +# Runs when the direction arrow is clicked +func animation_on_dir_down_pressed() -> void: + check_activate_direction(DIR_DOWN) + + +# Runs when the direction arrow is clicked +func animation_on_dir_downright_pressed() -> void: + check_activate_direction(DIR_DOWN_RIGHT) + + +# Runs when the direction arrow is clicked +func animation_on_dir_downleft_pressed() -> void: + check_activate_direction(DIR_DOWN_LEFT) + + +# Runs when the direction arrow is clicked +func animation_on_dir_upright_pressed() -> void: + check_activate_direction(DIR_UP_RIGHT) + + +# Runs when the direction arrow is clicked +func animation_on_dir_upleft_pressed() -> void: + check_activate_direction(DIR_UP_LEFT) + + +# If the user tries to mirror an animation, ensure they're not trying to mirror an already +# mirrored direction, and that the direction they're trying to mirror has been created. +func animation_on_mirror_checkbox_toggled(button_pressed: bool) -> void: + if not has_spritesheet_been_loaded(): + get_node(GENERIC_ERROR_NODE).dialog_text = "No animation has been configured." + get_node(GENERIC_ERROR_NODE).popup() + get_node(MIRROR_NODE).pressed = false + return + + var opp_dir = find_opposite_direction(direction_selected) + var opp_anim_name="%s_%s" % [return_current_animation_type(), opp_dir] + var metadata_array_offset: int = get_metadata_array_offset(opp_dir) + + if button_pressed: + if anim_metadata[metadata_array_offset][METADATA_IS_MIRROR]: + get_node(GENERIC_ERROR_NODE).dialog_text = \ + "You can't mirror a direction that is already mirrored." + get_node(GENERIC_ERROR_NODE).popup() + get_node(MIRROR_NODE).set_pressed_no_signal(false) + return + + if anim_metadata[metadata_array_offset][METADATA_SPRITESHEET_FIRST_FRAME] == 0: + get_node(GENERIC_ERROR_NODE).dialog_text = \ + "You can't mirror an animation that hasn't been set up." + get_node(GENERIC_ERROR_NODE).popup() + get_node(MIRROR_NODE).set_pressed_no_signal(false) + return + + mirror_animation(opp_dir, direction_selected) + preview_update() + else: + unmirror_animation(direction_selected) + + +# When the animation speed has been changed, update the speed and label +func controls_on_anim_speed_scroll_bar_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value = current_animation_speed + return + + if anim_metadata[get_metadata_array_offset()][METADATA_IS_MIRROR] and not currently_changing_direction: + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value = current_animation_speed + get_node(GENERIC_ERROR_NODE).dialog_text = "You cannot change a mirrored animation." + get_node(GENERIC_ERROR_NODE).popup() + return + + current_animation_speed = int(value) + + check_if_controls_have_changed() + + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_label").text = "%s: %s FPS" % [ANIMATION_SPEED_LABEL, value] + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").frames.set_animation_speed(ANIM_IN_PROGRESS, value) + + preview_update() + + if autostore == true: + store_on_anim_store_button_pressed() + + +# When the first animation frame setting is changed, update the animation preview appropriately +func controls_on_start_frame_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = spritesheet_settings[2] + return + + if anim_metadata[get_metadata_array_offset()][METADATA_IS_MIRROR] and not currently_changing_direction: + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = spritesheet_settings[2] + get_node(GENERIC_ERROR_NODE).dialog_text = "You cannot change a mirrored animation." + get_node(GENERIC_ERROR_NODE).popup() + return + spritesheet_settings[2] = get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value > 0: + preview_show() + check_if_controls_have_changed() + draw_frame_outlines() + preview_update() + + if autostore == true: + store_on_anim_store_button_pressed() + + +# When the last animation frame setting is changed, update the animation preview appropriately +func controls_on_end_frame_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = spritesheet_settings[3] + return + + if anim_metadata[get_metadata_array_offset()][METADATA_IS_MIRROR] and not currently_changing_direction: + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = spritesheet_settings[3] + get_node(GENERIC_ERROR_NODE).dialog_text = "You cannot change a mirrored animation." + get_node(GENERIC_ERROR_NODE).popup() + return + + spritesheet_settings[3] = get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value + if get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value > 0: + if get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value == 0: + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = 1 + spritesheet_settings[2] = 1 + preview_show() + check_if_controls_have_changed() + + draw_frame_outlines() + preview_update() + + if autostore == true: + store_on_anim_store_button_pressed() + + +# When the number of horizontal frames in the spritesheet setting is changed, +# update the animation preview appropriately +func controls_on_h_frames_spin_box_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = spritesheet_settings[0] + return + + if anim_metadata[get_metadata_array_offset()][METADATA_IS_MIRROR] and not currently_changing_direction: + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = spritesheet_settings[0] + get_node(GENERIC_ERROR_NODE).dialog_text = "You cannot change a mirrored animation." + get_node(GENERIC_ERROR_NODE).popup() + return + + spritesheet_settings[0] = get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value + preview_show() + + check_if_controls_have_changed() + calc_sprite_size() + draw_frame_outlines() + preview_update() + + if autostore == true: + store_on_anim_store_button_pressed() + + +# When the number of vertical frames in the spritesheet setting is changed, +# update the animation preview appropriately +func controls_on_v_frames_spin_box_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = spritesheet_settings[1] + return + + if anim_metadata[get_metadata_array_offset()][METADATA_IS_MIRROR] and not currently_changing_direction: + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = spritesheet_settings[1] + get_node(GENERIC_ERROR_NODE).dialog_text = "You cannot change a mirrored animation." + get_node(GENERIC_ERROR_NODE).popup() + return + + spritesheet_settings[1] = get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value + + preview_show() + + check_if_controls_have_changed() + calc_sprite_size() + draw_frame_outlines() + preview_update() + + if autostore == true: + store_on_anim_store_button_pressed() + + +# Load a spritesheet when selected in the file browser +func controls_on_FileDialog_file_selected(path: String) -> void: + get_node(NO_SPRITESHEET_NODE).visible = false + load_spritesheet(path) + + +# Check all animations have been created when the user wants to export the ESCPlayer +func spritesheet_on_export_button_pressed() -> void: + var missing_walk_animations: int = 0 + var missing_talk_animations: int = 0 + var missing_idle_animations: int = 0 + var anim_name: String = "" + var dirnames = [] + + var scene_name = "%s/%s.scn" % [get_node(CHARACTER_PATH_NODE).text, get_node(NAME_NODE).get_node("node_name").text] + + var dest_file = File.new() + if dest_file.file_exists(scene_name): + get_node(GENERIC_ERROR_NODE).dialog_text = \ + "Scene file '%s' already exists.\nPlease change Global_ID or path,\nor delete scene before continuing.\n" \ + % scene_name + get_node(GENERIC_ERROR_NODE).popup() + return + + if get_node(DIR_COUNT_NODE).get_node("four_directions").pressed: + dirnames = DIR_LIST_4 + else: + dirnames = DIR_LIST_8 + + for dirloop in dirnames: + anim_name = "%s_%s" % [TYPE_WALK, dirloop] + + if anim_metadata[get_metadata_array_offset(dirloop, TYPE_WALK)][METADATA_SPRITESHEET_FIRST_FRAME] == 0: + missing_walk_animations += 1 + + anim_name = "%s_%s" % [TYPE_TALK, dirloop] + + if anim_metadata[get_metadata_array_offset(dirloop, TYPE_TALK)][METADATA_SPRITESHEET_FIRST_FRAME] == 0: + missing_talk_animations += 1 + + anim_name = "%s_%s" % [TYPE_IDLE, dirloop] + + if anim_metadata[get_metadata_array_offset(dirloop, TYPE_IDLE)][METADATA_SPRITESHEET_FIRST_FRAME] == 0: + missing_idle_animations += 1 + + if missing_idle_animations + missing_talk_animations + missing_walk_animations > 0: + get_node(GENERIC_ERROR_NODE).dialog_text = \ + "One or more animations are not configured.\nPlease ensure all arrows are green for\nwalk, talk, and idle animations.\n\n" + + if missing_walk_animations: + get_node(GENERIC_ERROR_NODE).dialog_text += \ + "%s walk animations not configured.\n" % missing_walk_animations + + if missing_talk_animations: + get_node(GENERIC_ERROR_NODE).dialog_text += \ + "%s talk animations not configured.\n" % missing_talk_animations + + if missing_idle_animations: + get_node(GENERIC_ERROR_NODE).dialog_text += \ + "%s idle animations not configured." % missing_idle_animations + + get_node(GENERIC_ERROR_NODE).popup() + + return + +# export_thread = Thread.new() +# export_thread.start(self, "export_player") + export_player(scene_name) + +# Update the spritesheet zoom and scrollbars +func spritesheet_on_zoom_scrollbar_value_changed(value: float) -> void: + if not has_spritesheet_been_loaded(): + return + + zoom_value = stepify(value, 0.1) + get_node(ZOOM_LABEL_NODE).text = "Zoom: %sx" % str(zoom_value) + if zoom_value > 1.0: + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_min_size = source_image.get_size() * zoom_value + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_scale = Vector2.ONE + else: + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_min_size = source_image.get_size() + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_scale.x = zoom_value + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").rect_scale.y = zoom_value + draw_frame_outlines() + + +# Show the file manager when the load spritesheet button is pressed +func spritesheet_on_load_spritesheet_button_pressed() -> void: + get_node(FILE_DIALOG_NODE).popup() + + +# Reset zoom settings when the reset button is pushed. Also called when a new +# spritesheet is loaded. +func spritesheet_on_zoom_reset_button_pressed() -> void: + if not has_spritesheet_been_loaded(): + return + + get_node(ZOOM_SCROLL_NODE).value = 1 + + get_node(SCROLL_VBOX_NODE).get_node("spritesheet_scroll_container").scroll_horizontal = 0 + get_node(SCROLL_VBOX_NODE).get_node("spritesheet_scroll_container").scroll_vertical = 0 + + +# If the node name is changed, update the global_id to match. +# NOTE : Updating the global_id doesn't update the nodename, allowing them to be different. +func nodename_on_node_name_text_changed(new_text: String) -> void: + get_node(NAME_NODE).get_node("global_id").text = new_text + + +# If 8 directions was already selected, don't let it be unselected. +# If 4 directions was selected, unselect it. +func directions_on_eight_directions_pressed() -> void: + if not get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed: + # Don't let them untick all boxes + get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed = true + + get_node(DIR_COUNT_NODE).get_node("four_directions").pressed = false + + reset_arrow_colours() + + +# If 4 directions was already selected, don't let it be unselected. +# If 8 directions was selected, unselect it. Also if the previously selected direction was +# a diagonal, reset the selection to up as the diagonal is no longer valid. +func directions_on_four_directions_pressed() -> void: + if not get_node(DIR_COUNT_NODE).get_node("four_directions").pressed: + # Don't let them untick all boxes + get_node(DIR_COUNT_NODE).get_node("four_directions").pressed = true + else: + # Current direction is diagonal + if not direction_selected in DIR_LIST_4: + direction_selected = DIR_UP + activate_direction(DIR_UP) + + get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed = false + reset_arrow_colours() + + +# Returns the currently selected animation type +func return_current_animation_type() -> String: + var animation_type: String = "" + + if get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed: + animation_type = TYPE_WALK + elif get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed: + animation_type = TYPE_TALK + elif get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed: + animation_type = TYPE_IDLE + + assert(not animation_type.empty(), "No animation type selected.") + + return animation_type + + +# Runs whenever a direction arrow is clicked. If the store button is visible (i.e. the settings +# for the sprite frames have changed since they were last stored) the selected direction isn't +# changed and a confirmation window is shown instead. +func check_activate_direction(direction) -> void: + direction_requested = direction + + if get_node(STORE_ANIM_NODE).visible: + get_node(ARROWS_NODE).get_node("Container_%s" % direction).get_node("set_dir_%s" % direction).pressed = false + get_node(ARROWS_NODE).get_node("Container_%s" % direction).get_node("unset_dir_%s" % direction).pressed = false + $InformationWindows/unstored_changes_window.popup() + else: + activate_direction(direction) + + +# Change the selected direction. This clears the selected direction arrow and mirror settings. +# If the selected direction has an animation, it will be displayed, if not, the "no animation" +# graphic will be displayed in the preview window. +# Spritesheet control values are set based on the direction chosen (if it had a previous animation) +# If it used a different spritesheet, that will be loaded. +func activate_direction(direction) -> void: + var anim_type = return_current_animation_type() + var arrows = get_tree().get_nodes_in_group("direction_buttons") + var anim_name = "%s_%s" % [anim_type, direction] + + currently_changing_direction = true + direction_selected = direction + + for arrow in arrows: + arrow.pressed = false + + if direction == DIR_UP or direction == DIR_DOWN: + get_node(MIRROR_NODE).visible = false + else: + get_node(MIRROR_NODE).visible = true + + get_node(MIRROR_NODE).set_pressed_no_signal(false) + + # If no animation has been created yet for this direction + if anim_metadata[get_metadata_array_offset()][METADATA_SPRITESHEET_FIRST_FRAME] == 0: + get_node(ARROWS_NODE).get_node("Container_%s" % direction).get_node("unset_dir_%s" % direction).pressed = true + spritesheet_settings[2] = 0 + spritesheet_settings[3] = 0 + + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = 0 + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = 0 + preview_hide() + else: + get_node(ARROWS_NODE).get_node("Container_%s" % direction).get_node("set_dir_%s" % direction).pressed = true + + var metadata = anim_metadata[get_metadata_array_offset()] + + assert(metadata[METADATA_ANIM_NAME] == anim_name, \ + "Anim %s expected in metadata array. Found %s" % [anim_name, metadata[METADATA_ANIM_NAME]]) + + if metadata[METADATA_SPRITESHEET_SOURCE_FILE] != get_node(CURRENT_SHEET_NODE).text: + load_spritesheet(metadata[METADATA_SPRITESHEET_SOURCE_FILE]) + + # Disconnect the signals so if we're changing to a mirrored direction it doesn't complain + # when all the settings update +# disconnect_selector_signals() + get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value = metadata[METADATA_SPRITESHEET_FRAMES_HORIZ] + get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value = metadata[METADATA_SPRITESHEET_FRAMES_VERT] + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = metadata[METADATA_SPRITESHEET_FIRST_FRAME] + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = metadata[METADATA_SPRITESHEET_LAST_FRAME] + get_node(ANIM_CONTROLS_NODE).get_node("anim_speed_scroll_bar").value = metadata[METADATA_SPEED] + get_node(MIRROR_NODE).set_pressed_no_signal(metadata[METADATA_IS_MIRROR]) +# connect_selector_signals() + preview_update() + + # Restart animation otherwise it will first complete all the frames before changing to the new animation + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").playing = false + get_node(PREVIEW_NODE).get_node("anim_preview_sprite").playing = true + currently_changing_direction = false + +# Store the metadata for the animation changes for the current direction +func store_on_anim_store_button_pressed() -> void: + get_node(STORE_ANIM_NODE).visible = false + + var anim_type = return_current_animation_type() + store_animation("%s_%s" % [anim_type, direction_selected]) + + reset_arrow_colours() + + +# Based on the type of animation and direction, find its array position in the metadata array. +func get_metadata_array_offset(dir_to_retrieve = "default", anim_type = "default") -> int: + var offset: int = 0 + + if anim_type == "default": + anim_type = return_current_animation_type() + + if anim_type == TYPE_TALK: + offset = 8 + elif anim_type == TYPE_IDLE: + offset = 16 + + if dir_to_retrieve == "default": + dir_to_retrieve = direction_selected + + var dir_offset: int = DIR_LIST_8.find(dir_to_retrieve) + + assert(dir_offset > -1, "Could not find direction in list. This should never happen.") + + return offset + dir_offset + + +# Using both set and unset buttons (instead of changing the texture to a different colour) as +# updating the direction arrow sprite was causing issues due to Godot storing the +# sprite by reference rather than by value. It was easier to duplicate the sprites/buttons. +func reset_arrow_colours() -> void: + var current_animation_type = return_current_animation_type() + var current_animation_name + + for dir in DIR_LIST_8: + current_animation_name = "%s_%s" % [current_animation_type, dir] + + if anim_metadata[get_metadata_array_offset(dir)][METADATA_SPRITESHEET_FIRST_FRAME] > 0: + get_node(ARROWS_NODE).get_node("Container_%s" % dir).get_node("set_dir_%s" % dir).visible = true + get_node(ARROWS_NODE).get_node("Container_%s" % dir).get_node("unset_dir_%s" % dir).visible = false + else: + get_node(ARROWS_NODE).get_node("Container_%s" % dir).get_node("set_dir_%s" % dir).visible = false + get_node(ARROWS_NODE).get_node("Container_%s" % dir).get_node("unset_dir_%s" % dir).visible = true + + if get_node(DIR_COUNT_NODE).get_node("four_directions").pressed: + var arrows = get_tree().get_nodes_in_group("8_direction_buttons") + + for arrow in arrows: + arrow.visible = false + + # Current direction is diagonal + if not direction_selected in DIR_LIST_4: + direction_selected = DIR_UP + activate_direction(DIR_UP) + + # This works when you change between animation types + # eg. walk and talk - to ensure that the arrow will get changed back from selected with stored + # animation to selected with unstored animation if needs be. It also resets the preview. + activate_direction(direction_selected) + + +# If the user tries to change direction without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to save the changes, then will update +# the interface to select the new direction. +func unstored_warning_on_commit_button_pressed() -> void: + get_node(UNSTORED_CHANGE_NODE).visible = false + get_node(STORE_ANIM_NODE).visible = false + + var anim_type = return_current_animation_type() + store_animation("%s_%s" % [anim_type, direction_selected]) + + reset_arrow_colours() + + activate_direction(direction_requested) + + +# If the user tries to change direction without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to lose the changes, then will update +# the interface to select the new direction. +func unstored_warning_on_lose_button_pressed() -> void: + get_node(UNSTORED_CHANGE_NODE).visible = false + get_node(STORE_ANIM_NODE).visible = false + + activate_direction(direction_requested) + + +# If the user tries to change direction without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to cancel the request to change direction +# and let the user continue to edit the current animation. +func unstored_warning_on_cancel_button_pressed() -> void: + get_node(UNSTORED_CHANGE_NODE).visible = false + + +# Returns the opposite direction for mirroring animations +func find_opposite_direction(direction:String) -> String: + var opposite_dir: String = "" + + match direction: + DIR_UP_RIGHT: + opposite_dir = DIR_UP_LEFT + DIR_RIGHT: + opposite_dir = DIR_LEFT + DIR_DOWN_RIGHT: + opposite_dir = DIR_DOWN_LEFT + DIR_DOWN_LEFT: + opposite_dir = DIR_DOWN_RIGHT + DIR_LEFT: + opposite_dir = DIR_RIGHT + DIR_UP_LEFT: + opposite_dir = DIR_UP_RIGHT + + assert(not opposite_dir.empty(), "This should never happen : direction = %s" % direction) + return opposite_dir + + +# Creates an ESCPlayer node based on the settings configured in the wizard. +# It will save it as a scene (named based on the name provided in the GUI text box) +# and open it in the Godot editor - which is why this utility has to run as a plugin. +# This will also create an ESCDialogue position, and a collision box. The collision box will +# be sized based on the widest and tallest frames encountered during export (note that the +# widest/tallest frame settings do not necessarily come from the same animation frame but are +# from all the animation frames. +func export_player(scene_name) -> void: + var num_directions + var start_angle_array + var angle_size + var dirnames + + var plugin_reference = get_node("..").plugin_reference + + disconnect_selector_signals() + get_node(EXPORT_PROGRESS_NODE).popup() + get_node(EXPORT_PROGRESS_NODE).get_node("progress_bar").value = 0 + get_node(EXPORT_PROGRESS_NODE).get_node("progress_bar").visible = true + get_node(EXPORT_PROGRESS_NODE).get_node("progress_label").visible = true + + if get_node(DIR_COUNT_NODE).get_node("eight_directions").pressed: + num_directions = 8 + else: + num_directions = 4 + + var new_character = ESCPlayer.new() + new_character.name = get_node(NAME_NODE).get_node("node_name").text + + if get_node(NAME_NODE).get_node("global_id").text == null: + new_character.global_id = new_character.name + + new_character.global_id = get_node(NAME_NODE).get_node("global_id").text + + var animations_resource = ESCAnimationResource.new() + + # This is necessary to avoid a Godot bug when appending to one array + # appends to all arrays in the same class (possibly for resources only). + animations_resource.dir_angles = [] + animations_resource.directions = [] + animations_resource.idles = [] + animations_resource.speaks = [] + + if get_node(DIR_COUNT_NODE).get_node("four_directions").pressed: + num_directions = 4 + start_angle_array = [315, 45, 135, 225] + angle_size = 90 + dirnames = DIR_LIST_4 + else: + num_directions = 8 + start_angle_array = [338, 22, 69, 114, 159, 204, 249, 294] + angle_size = 45 + dirnames = DIR_LIST_8 + + for loop in range(num_directions): + # Need to create new objects here each time in order to avoid having multiple references + # to the same objects. + var dir_angle = ESCDirectionAngle.new() + var anim_details: ESCAnimationName + + dir_angle.angle_start = start_angle_array[loop] + dir_angle.angle_size = angle_size + animations_resource.dir_angles.append(dir_angle) + + anim_details = _create_esc_animation(TYPE_WALK, dirnames[loop]) + animations_resource.directions.append(anim_details) + + anim_details = _create_esc_animation(TYPE_TALK, dirnames[loop]) + animations_resource.speaks.append(anim_details) + + anim_details = _create_esc_animation(TYPE_IDLE, dirnames[loop]) + animations_resource.idles.append(anim_details) + +# var largest_sprite = export_generate_animations(new_character, num_directions) + export_largest_sprite = Vector2.ONE + # Need to yield on the child function so this function doesn't continue + # when the child yields + var export_state = export_generate_animations(new_character, num_directions) + if export_state is GDScriptFunctionState: + export_state = yield(export_state, "completed") + # Add Collision shape to the ESCPlayer + var rectangle_shape = RectangleShape2D.new() + var collision_shape = CollisionShape2D.new() + progress_bar_update("Creating collision shape") + yield(get_tree(), "idle_frame") + + collision_shape.shape = rectangle_shape + collision_shape.shape.extents = export_largest_sprite / 2 + collision_shape.position.y = -(export_largest_sprite.y / 2) + + new_character.add_child(collision_shape) + progress_bar_update("Setting up dialog position") + yield(get_tree(), "idle_frame") + + # Add Dialog Position to the ESCPlayer + var dialog_position = ESCLocation.new() + dialog_position.name = "dialog_position" + dialog_position.position.y = -(export_largest_sprite.y * 1.2) + new_character.add_child(dialog_position) + + progress_bar_update("Configuring animations") + yield(get_tree(), "idle_frame") + # Make it so all the nodes can be seen in the scene tree + new_character.animations = animations_resource + progress_bar_update("Adding child to scene tree") + yield(get_tree(), "idle_frame") + get_tree().edited_scene_root.add_child(new_character) + new_character.set_owner(get_tree().edited_scene_root) + + # Making the owner "new_character" rather than "get_tree().edited_scene_root" means that + # when saving as a packed scene, the child nodes get saved under the parent (as the parent + # must own the child nodes). If the owner is not the scene root though, the nodes will NOT + # show up in the scene tree. + collision_shape.set_owner(new_character) + dialog_position.set_owner(new_character) + + # Export scene + var packed_scene = PackedScene.new() + + progress_bar_update("Packing scene - this might take up to 30 seconds") + yield(get_tree(), "idle_frame") + packed_scene.pack(get_tree().edited_scene_root.get_node(new_character.name)) + + progress_bar_update("Resource saving - this might take up to 30 seconds") + yield(get_tree(), "idle_frame") + # Flag suggestions from https://godotengine.org/qa/50437/how-to-turn-a-node-into-a-packedscene-via-gdscript + ResourceSaver.save(scene_name, packed_scene, ResourceSaver.FLAG_CHANGE_PATH|ResourceSaver.FLAG_REPLACE_SUBRESOURCE_PATHS|ResourceSaver.FLAG_COMPRESS) + + progress_bar_update("Releasing resources - this might take up to 30 seconds") + yield(get_tree(), "idle_frame") + new_character.queue_free() + + get_tree().edited_scene_root.get_node(new_character.name).queue_free() + plugin_reference.open_scene(scene_name) + plugin_reference.make_visible(false) + get_node(EXPORT_PROGRESS_NODE).hide() + get_node(EXPORT_COMPLETE_NODE).popup() + + connect_selector_signals() + + +# Updates the text in the export window so the user knows what's happening +func progress_bar_update(message, bar_increase_amount = 1) -> void: + get_node(PROGRESS_LABEL_NODE).text = message + get_node(EXPORT_PROGRESS_NODE).get_node("progress_bar").value += bar_increase_amount + + +# When exporting the ESCPlayer, this function loads the relevant spritesheets based on the +# animation metadata, and copies the frames to the relevant animations within the animatedsprite +# attached to the ESCPlayer. +#func export_generate_animations(character_node, num_directions) -> Vector2: +func export_generate_animations(character_node, num_directions) -> void: + # This variable is used instead of running this function in a thread as I hit this issue + # when I tried to thread this - https://github.com/godotengine/godot/issues/38058 + var display_refresh_timer:int = OS.get_ticks_msec() + var direction_names + var loaded_spritesheet: String + var largest_frame_dimensions: Vector2 = Vector2.ZERO + var sprite_frames = SpriteFrames.new() + + if num_directions == 4: + direction_names = DIR_LIST_4 + else: + direction_names = DIR_LIST_8 + + for animtype in [TYPE_WALK, TYPE_TALK, TYPE_IDLE]: + for anim_dir in direction_names: + # Using this in place of threads due to the above mentioned issue so that the + # UI continues to update while the export is running + var current_ticks = OS.get_ticks_msec() + if current_ticks - display_refresh_timer > 30: + yield(get_tree(), "idle_frame") + + display_refresh_timer = current_ticks + + if num_directions == 4: + progress_bar_update("Processing "+str(animtype)+" "+str(anim_dir),2) + else: + progress_bar_update("Processing "+str(animtype)+" "+str(anim_dir),1) + + var anim_name = "%s_%s" % [animtype, anim_dir] + var metadata = anim_metadata[get_metadata_array_offset(anim_dir, animtype)] + + if metadata[METADATA_IS_MIRROR]: + continue + + var texture + var rect_location + var frame_being_copied = Image.new() + var frame_counter: int = 0 + sprite_frames.add_animation(anim_name) + + if metadata[METADATA_SPRITESHEET_SOURCE_FILE] != loaded_spritesheet: + load_spritesheet(metadata[METADATA_SPRITESHEET_SOURCE_FILE], true, get_metadata_array_offset(anim_dir, animtype)) + + loaded_spritesheet = metadata[METADATA_SPRITESHEET_SOURCE_FILE] + calc_sprite_size() + if (frame_size.x / 2) > largest_frame_dimensions.x: + largest_frame_dimensions.x = frame_size.x + + if (frame_size.y / 2) > largest_frame_dimensions.y: + largest_frame_dimensions.y = frame_size.y + frame_being_copied.create(frame_size.x, frame_size.y, false, source_image.get_format()) + +# str(metadata[METADATA_SPRITESHEET_LAST_FRAME])) + for loop in range(metadata[METADATA_SPRITESHEET_LAST_FRAME] - metadata[METADATA_SPRITESHEET_FIRST_FRAME] + 1): + texture = ImageTexture.new() + rect_location = calc_frame_coords(metadata[METADATA_SPRITESHEET_FIRST_FRAME] + loop) + frame_being_copied.blit_rect(source_image, Rect2(rect_location, Vector2(frame_size.x, frame_size.y)), Vector2(0, 0)) + texture.create_from_image(frame_being_copied) + + # Remove "filter" flag so it's pixel perfect + texture.set_flags(2) + sprite_frames.add_frame (anim_name, texture, frame_counter ) + sprite_frames.set_animation_speed(anim_name, metadata[METADATA_SPEED]) + frame_counter += 1 + sprite_frames.remove_animation("default") + + var animated_sprite = AnimatedSprite.new() + + progress_bar_update("Adding sprite frames to node") + animated_sprite.frames = sprite_frames + animated_sprite.animation = "%s_%s" % [TYPE_IDLE, DIR_DOWN] + animated_sprite.position.y = -(largest_frame_dimensions.y / 2) # Place feet at (0,0) + character_node.add_child(animated_sprite) + # Making the owner "character_node" rather than "get_tree().edited_scene_root" means that + # when saving as a packed scene, the child nodes get saved under the parent (as the parent + # must own the child nodes). If the owner is not the scene root though, the nodes will NOT + # show up in the scene tree. + animated_sprite.set_owner(character_node) + #return largest_frame_dimensions + export_largest_sprite = largest_frame_dimensions + + +# Open the help window +func spritesheet_on_help_button_pressed() -> void: + $InformationWindows/help_window.popup() + $InformationWindows/help_window.show_page() + + +func spritesheet_on_reset_button_pressed() -> void: + $InformationWindows/ConfirmationDialog.dialog_text = "WARNING!\n\n" + \ + "If you continue you will lose the current character." + $InformationWindows/ConfirmationDialog.popup() + + +func spritesheet_on_reset_confirmed() -> void: + spritesheet_settings = [1, 1, 0, 0] + source_image = null + get_node(SCROLL_CTRL_NODE).get_node("spritesheet_sprite").texture = null + create_empty_animations() + character_creator_reset() + + +func spritesheet_on_MainMenuConfirmation_confirmed() -> void: + get_node("../Menu").visible = true + get_node(".").visible = false + + +func spritesheet_on_main_menu_button_up() -> void: + $InformationWindows/MainMenuConfirmation.popup() + + +func load_settings() -> void: + var file_path = "res://" + var file = File.new() + if file.file_exists(CONFIG_FILE): + file.open(CONFIG_FILE, File.READ) + file_path = file.get_pascal_string() + file.close() + get_node(CHARACTER_PATH_NODE).text = file_path + + +# Creates and returns an ESCAnimationName for use by ESCAnimationResource +# +# #### Parameters +# +# - type: One of TYPE_WALK, TYPE_TALK, TYPE_IDLE (these are consts defined at the top of this script) +# - dir_name: One of DIR_LIST_8's or DIR_LIST_4's entries (these are consts defined at the top of this script) +# +# *Returns* a valid ESCAnimationName object. +func _create_esc_animation(type: String, dir_name: String) -> ESCAnimationName: + var anim_details = ESCAnimationName.new() + + anim_details.animation = "%s_%s" % [type, dir_name] + + if anim_metadata[get_metadata_array_offset(dir_name, type)][METADATA_IS_MIRROR]: + anim_details.mirrored = true + anim_details.animation = "%s_%s" % [type, find_opposite_direction(dir_name)] + else: + anim_details.mirrored = false + return anim_details + + +func _on_character_path_change_button_pressed() -> void: + get_node(CHARACTER_FILE_NODE).popup_centered() + + +func _on_CharacterPathFileDialog_dir_selected(dir: String) -> void: + get_node(CHARACTER_PATH_NODE).text = dir + var file = File.new() + file.open(CONFIG_FILE, File.WRITE) + file.store_pascal_string(dir) + file.close() + + +# Mouse clicks inside the spritesheet +func _on_control_gui_input(event: InputEvent) -> void: + var ClickedTile:Vector2 + if event.is_pressed(): + var NumHorizFrames = get_node(ANIM_CONTROLS_NODE).get_node("h_frames_spin_box").value + var NumVertFrames = get_node(ANIM_CONTROLS_NODE).get_node("v_frames_spin_box").value + + ClickedTile.x = int(event.position.x / (frame_size.x * zoom_value)) + if ClickedTile.x >= NumHorizFrames: + return + ClickedTile.y = int(event.position.y / (frame_size.y * zoom_value)) + if ClickedTile.y >= NumVertFrames: + return + + var AbsoluteFrame = ((ClickedTile.y * NumHorizFrames) + ClickedTile.x) + 1 + + if event.button_index == BUTTON_LEFT: + get_node(ANIM_CONTROLS_NODE).get_node("start_frame").value = AbsoluteFrame + if event.button_index == BUTTON_RIGHT: + get_node(ANIM_CONTROLS_NODE).get_node("end_frame").value = AbsoluteFrame + + +# If the user tries to change animation type without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to save the changes, then will update +# the interface to select the new direction. +func unstored_animchange_warning_on_commit_button_pressed() -> void: + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).visible = false + get_node(STORE_ANIM_NODE).visible = false + var anim_type = return_current_animation_type() + store_animation("%s_%s" % [anim_type, direction_selected]) + change_animation_type(animation_type_requested) + reset_arrow_colours() + +# If the user tries to change animation type without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to lose the changes, then will update +# the interface to select the new direction. +func unstored_animchange_warning_on_lose_button_pressed() -> void: + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).visible = false + get_node(STORE_ANIM_NODE).visible = false + change_animation_type(animation_type_requested) + reset_arrow_colours() + + +# If the user tries to change animation type without commiting first, a window will appear to +# confirm what they want to do. +# The button associated with this function chooses to cancel the request to change direction +# and let the user continue to edit the current animation. +func unstored_animchange_warning_on_cancel_button_pressed() -> void: + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).visible = false + + +func change_animation_type(anim_type) -> void: + if anim_type == "walk": + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = true + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = false + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = false + animation_type_selected = "walk" + elif anim_type == "talk": + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = true + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = false + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = false + animation_type_selected = "talk" + else: # idle + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = true + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = false + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = false + animation_type_selected = "idle" + reset_arrow_colours() + + +# If the walk button is selected, unselect the other buttons. +# If this option was already the selected option, reselect it rather than letting the +# user disable it (which would mean that none of walk/talk/idle were selected. +func animation_on_walk_checkbox_pressed() -> void: + # Don't let the checkbox be unselected if it's currently selected + if animation_type_selected == "walk": + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = true + return + if get_node(STORE_ANIM_NODE).visible: + # Reset the buttons back to how they were + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = false + if animation_type_selected == "talk": + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = true + if animation_type_selected == "idle": + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = true + animation_type_requested="walk" + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).popup() + else: + change_animation_type("walk") + + +# If the talk button is selected, unselect the other buttons. +# If this option was already the selected option, reselect it rather than letting the +# user disable it (which would mean that none of walk/talk/idle were selected. +func animation_on_talk_checkbox_pressed() -> void: + # Don't let the checkbox be unselected if it's currently selected + if animation_type_selected == "talk": + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = true + return + if get_node(STORE_ANIM_NODE).visible: + # Reset the buttons back to how they were + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = false + if animation_type_selected == "idle": + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = true + if animation_type_selected == "walk": + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = true + animation_type_requested="talk" + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).popup() + else: + change_animation_type("talk") + + +# If the idle button is selected, unselect the other buttons. +# If this option was already the selected option, reselect it rather than letting the +# user disable it (which would mean that none of walk/talk/idle were selected. +func animation_on_idle_checkbox_pressed() -> void: + # Don't let the checkbox be unselected if it's currently selected + if animation_type_selected == "idle": + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = true + return + if get_node(STORE_ANIM_NODE).visible: + # Reset the buttons back to how they were + get_node(ANIM_TYPE_NODE).get_node("idle_checkbox").pressed = false + if animation_type_selected == "talk": + get_node(ANIM_TYPE_NODE).get_node("talk_checkbox").pressed = true + if animation_type_selected == "walk": + get_node(ANIM_TYPE_NODE).get_node("walk_checkbox").pressed = true + animation_type_requested="idle" + get_node(UNSTORED_ANIMTYPE_CHANGE_NODE).popup() + else: + change_animation_type("idle") + + +func _on_AutoStoreCheckBox_toggled(button_pressed: bool) -> void: + autostore = button_pressed diff --git a/addons/escoria-wizard/CharacterCreator.tscn b/addons/escoria-wizard/CharacterCreator.tscn new file mode 100644 index 00000000..c77b5bc4 --- /dev/null +++ b/addons/escoria-wizard/CharacterCreator.tscn @@ -0,0 +1,1448 @@ +[gd_scene load_steps=40 format=2] + +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_down.png" type="Texture" id=1] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_r.png" type="Texture" id=2] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_right.png" type="Texture" id=3] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_right.png" type="Texture" id=4] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_down.png" type="Texture" id=5] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_ul.png" type="Texture" id=6] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_dl.png" type="Texture" id=7] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_d.png" type="Texture" id=8] +[ext_resource path="res://addons/escoria-wizard/graphics/no_animation.png" type="Texture" id=9] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_downleft.png" type="Texture" id=10] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_downleft.png" type="Texture" id=11] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_left.png" type="Texture" id=12] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_l.png" type="Texture" id=13] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_ur.png" type="Texture" id=14] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_ul.png" type="Texture" id=15] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_upright.png" type="Texture" id=16] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_ur.png" type="Texture" id=17] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_u.png" type="Texture" id=18] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_r.png" type="Texture" id=19] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_u.png" type="Texture" id=20] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_l.png" type="Texture" id=21] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_dr.png" type="Texture" id=22] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_up.png" type="Texture" id=23] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_upright.png" type="Texture" id=24] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_downright.png" type="Texture" id=25] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_left.png" type="Texture" id=26] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_upleft.png" type="Texture" id=27] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreenarrow_up.png" type="Texture" id=28] +[ext_resource path="res://addons/escoria-wizard/graphics/no_spritesheet.png" type="Texture" id=29] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_upleft.png" type="Texture" id=30] +[ext_resource path="res://addons/escoria-wizard/graphics/greenarrow_downright.png" type="Texture" id=31] +[ext_resource path="res://addons/escoria-wizard/graphics/icon.png" type="Texture" id=32] +[ext_resource path="res://addons/escoria-wizard/graphics/greyarrow_d.png" type="Texture" id=33] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_dr.png" type="Texture" id=34] +[ext_resource path="res://addons/escoria-wizard/graphics/darkgreyarrow_dl.png" type="Texture" id=35] +[ext_resource path="res://addons/escoria-wizard/draw_frame_rects.gd" type="Script" id=36] +[ext_resource path="res://addons/escoria-wizard/CharacterCreator.gd" type="Script" id=37] +[ext_resource path="res://addons/escoria-wizard/help_window.tscn" type="PackedScene" id=38] + +[sub_resource type="SpriteFrames" id=1] +animations = [ { +"frames": [ ], +"loop": true, +"name": "default", +"speed": 5.0 +}, { +"frames": [ ], +"loop": true, +"name": "in_progress", +"speed": 5.0 +} ] + +[node name="CharacterCreator" type="MarginContainer"] +margin_right = 1290.0 +margin_bottom = 900.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_constants/margin_right = 50 +custom_constants/margin_top = 50 +custom_constants/margin_left = 50 +custom_constants/margin_bottom = 50 +script = ExtResource( 37 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 50.0 +margin_top = 50.0 +margin_right = 1240.0 +margin_bottom = 850.0 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"] +margin_right = 1190.0 +margin_bottom = 14.0 + +[node name="node_name_colorrect2" type="ColorRect" parent="VBoxContainer/MarginContainer"] +margin_right = 1190.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 400, 0 ) +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/MarginContainer"] +margin_right = 1190.0 +margin_bottom = 14.0 + +[node name="Label" type="Label" parent="VBoxContainer/MarginContainer/CenterContainer"] +margin_left = 527.0 +margin_right = 663.0 +margin_bottom = 14.0 +custom_colors/font_color = Color( 0.921569, 1, 0, 1 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 1 ) +text = "Character Creator" +uppercase = true + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +margin_top = 18.0 +margin_right = 1190.0 +margin_bottom = 800.0 +rect_min_size = Vector2( 1190, 550 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_constants/separation = 20 + +[node name="configuration" type="MarginContainer" parent="VBoxContainer/HBoxContainer"] +margin_right = 400.0 +margin_bottom = 782.0 +rect_min_size = Vector2( 400, 550 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="node_name_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration"] +margin_right = 400.0 +margin_bottom = 782.0 +rect_min_size = Vector2( 400, 0 ) +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration"] +margin_right = 400.0 +margin_bottom = 782.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="node_name" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer"] +margin_right = 400.0 +margin_bottom = 130.0 +rect_min_size = Vector2( 400, 130 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name"] +margin_right = 400.0 +margin_bottom = 24.0 + +[node name="name_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +size_flags_vertical = 3 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 395.0 +margin_bottom = 19.0 +size_flags_vertical = 6 +text = "Node Details" + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name"] +margin_top = 28.0 +margin_right = 400.0 +margin_bottom = 108.0 +custom_constants/margin_left = 5 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2"] +margin_left = 5.0 +margin_right = 400.0 +margin_bottom = 80.0 +columns = 3 + +[node name="node_name_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_top = 5.0 +margin_right = 91.0 +margin_bottom = 19.0 +text = "Name:" + +[node name="node_name" type="LineEdit" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 95.0 +margin_right = 295.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 200, 0 ) +hint_tooltip = "The will be the name of the node in your scene tree." +text = "replace_me" +caret_blink = true +caret_blink_speed = 0.5 + +[node name="Spacer" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 299.0 +margin_right = 357.0 +margin_bottom = 24.0 + +[node name="global_id_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_top = 33.0 +margin_right = 91.0 +margin_bottom = 47.0 +text = "Global ID:" + +[node name="global_id" type="LineEdit" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 95.0 +margin_top = 28.0 +margin_right = 295.0 +margin_bottom = 52.0 +rect_min_size = Vector2( 200, 0 ) +hint_tooltip = "The global id for the character to be used in ESC scripts." +caret_blink = true +caret_blink_speed = 0.5 + +[node name="Spacer2" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 299.0 +margin_top = 28.0 +margin_right = 357.0 +margin_bottom = 52.0 + +[node name="character_path_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_top = 61.0 +margin_right = 91.0 +margin_bottom = 75.0 +text = "Save to folder:" + +[node name="character_path" type="LineEdit" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 95.0 +margin_top = 56.0 +margin_right = 295.0 +margin_bottom = 80.0 +rect_min_size = Vector2( 200, 0 ) +hint_tooltip = "The global id for the character to be used in ESC scripts." +text = "res://game/characters" +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="character_path_change_button" type="Button" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer"] +margin_left = 299.0 +margin_top = 56.0 +margin_right = 357.0 +margin_bottom = 80.0 +text = "Change" + +[node name="directions" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer"] +margin_top = 134.0 +margin_right = 400.0 +margin_bottom = 186.0 +rect_min_size = Vector2( 400, 50 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions"] +margin_right = 400.0 +margin_bottom = 24.0 + +[node name="directions_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="direction_number_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 395.0 +margin_bottom = 19.0 +text = "Number of Directions" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions"] +margin_top = 28.0 +margin_right = 400.0 +margin_bottom = 52.0 +custom_constants/separation = 50 +alignment = 1 + +[node name="four_directions" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/HBoxContainer"] +margin_left = 139.0 +margin_right = 175.0 +margin_bottom = 24.0 +hint_tooltip = "Create 4 directions of animation" +pressed = true +text = "4" + +[node name="eight_directions" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/HBoxContainer"] +margin_left = 225.0 +margin_right = 261.0 +margin_bottom = 24.0 +hint_tooltip = "Create 8 directions of animation" +text = "8" + +[node name="animation" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer"] +margin_top = 190.0 +margin_right = 400.0 +margin_bottom = 628.0 +rect_min_size = Vector2( 400, 200 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_right = 400.0 +margin_bottom = 24.0 + +[node name="animation_type_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="animation_type_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 395.0 +margin_bottom = 19.0 +text = "Animation" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_top = 28.0 +margin_right = 400.0 +margin_bottom = 52.0 +custom_constants/separation = 20 +alignment = 1 + +[node name="walk_checkbox" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer"] +margin_left = 100.0 +margin_right = 156.0 +margin_bottom = 24.0 +hint_tooltip = "Configure walk animations" +pressed = true +text = "walk" + +[node name="talk_checkbox" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer"] +margin_left = 176.0 +margin_right = 227.0 +margin_bottom = 24.0 +hint_tooltip = "Configure talk animations" +text = "talk" + +[node name="idle_checkbox" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer"] +margin_left = 247.0 +margin_right = 299.0 +margin_bottom = 24.0 +hint_tooltip = "Configure idle animations" +text = "idle" + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_top = 56.0 +margin_right = 400.0 +margin_bottom = 106.0 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/MarginContainer2"] +margin_right = 400.0 +margin_bottom = 50.0 +rect_min_size = Vector2( 0, 50 ) + +[node name="HBoxContainer2" type="GridContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_top = 110.0 +margin_right = 400.0 +margin_bottom = 328.0 +columns = 5 + +[node name="Control" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_right = 50.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="HBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 54.0 +margin_right = 164.0 +margin_bottom = 200.0 + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer"] +margin_right = 110.0 +margin_bottom = 92.0 +custom_constants/margin_left = 5 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2"] +margin_left = 5.0 +margin_right = 110.0 +margin_bottom = 92.0 +columns = 3 + +[node name="Container_upleft" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_right = 28.0 +margin_bottom = 28.0 + +[node name="set_dir_upleft" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upleft" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up left animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 27 ) +texture_pressed = ExtResource( 30 ) +texture_hover = ExtResource( 30 ) + +[node name="unset_dir_upleft" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upleft" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up left animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 15 ) +texture_pressed = ExtResource( 6 ) +texture_hover = ExtResource( 6 ) + +[node name="Container_up" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 32.0 +margin_right = 60.0 +margin_bottom = 28.0 + +[node name="set_dir_up" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_up" groups=["direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 28 ) +texture_pressed = ExtResource( 23 ) +texture_hover = ExtResource( 23 ) + +[node name="unset_dir_up" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_up" groups=["direction_buttons"]] +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up animation (unconfigured)" +toggle_mode = true +pressed = true +texture_normal = ExtResource( 20 ) +texture_pressed = ExtResource( 18 ) +texture_hover = ExtResource( 18 ) + +[node name="Container_upright" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 64.0 +margin_right = 92.0 +margin_bottom = 28.0 + +[node name="unset_dir_upright" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upright" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up right animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 14 ) +texture_pressed = ExtResource( 17 ) +texture_hover = ExtResource( 17 ) + +[node name="set_dir_upright" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upright" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Up right animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 16 ) +texture_pressed = ExtResource( 24 ) +texture_hover = ExtResource( 24 ) + +[node name="Container_left" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_top = 32.0 +margin_right = 28.0 +margin_bottom = 60.0 + +[node name="set_dir_left" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_left" groups=["direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Left animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 12 ) +texture_pressed = ExtResource( 26 ) +texture_hover = ExtResource( 26 ) + +[node name="unset_dir_left" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_left" groups=["direction_buttons"]] +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Left animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 21 ) +texture_pressed = ExtResource( 13 ) +texture_hover = ExtResource( 13 ) + +[node name="Container_centre" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 32.0 +margin_top = 32.0 +margin_right = 60.0 +margin_bottom = 60.0 + +[node name="Container_right" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 64.0 +margin_top = 32.0 +margin_right = 92.0 +margin_bottom = 60.0 + +[node name="set_dir_right" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_right" groups=["direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Right animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 3 ) +texture_pressed = ExtResource( 4 ) +texture_hover = ExtResource( 4 ) + +[node name="unset_dir_right" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_right" groups=["direction_buttons"]] +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Right animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 19 ) +texture_pressed = ExtResource( 2 ) +texture_hover = ExtResource( 2 ) + +[node name="Container_downleft" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_top = 64.0 +margin_right = 28.0 +margin_bottom = 92.0 + +[node name="unset_dir_downleft" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downleft" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down left animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 35 ) +texture_pressed = ExtResource( 7 ) +texture_hover = ExtResource( 7 ) + +[node name="set_dir_downleft" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downleft" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down left animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 11 ) +texture_pressed = ExtResource( 10 ) +texture_hover = ExtResource( 10 ) + +[node name="Container_down" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 32.0 +margin_top = 64.0 +margin_right = 60.0 +margin_bottom = 92.0 + +[node name="set_dir_down" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_down" groups=["direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 1 ) +texture_pressed = ExtResource( 5 ) +texture_hover = ExtResource( 5 ) + +[node name="unset_dir_down" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_down" groups=["direction_buttons"]] +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 8 ) +texture_pressed = ExtResource( 33 ) +texture_hover = ExtResource( 33 ) + +[node name="Container_downright" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer"] +margin_left = 64.0 +margin_top = 64.0 +margin_right = 92.0 +margin_bottom = 92.0 + +[node name="set_dir_downright" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downright" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down right animation (configured)" +toggle_mode = true +texture_normal = ExtResource( 25 ) +texture_pressed = ExtResource( 31 ) +texture_hover = ExtResource( 31 ) + +[node name="unset_dir_downright" type="TextureButton" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downright" groups=["8_direction_buttons", "direction_buttons"]] +visible = false +margin_right = 28.0 +margin_bottom = 28.0 +hint_tooltip = "Down right animation (unconfigured)" +toggle_mode = true +texture_normal = ExtResource( 34 ) +texture_pressed = ExtResource( 22 ) +texture_hover = ExtResource( 22 ) + +[node name="MarginContainer3" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer"] +margin_top = 96.0 +margin_right = 110.0 +margin_bottom = 161.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_constants/margin_left = 15 + +[node name="mirror_checkbox" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer3"] +visible = false +margin_left = 15.0 +margin_right = 110.0 +margin_bottom = 65.0 +hint_tooltip = "Mirror opposite direction's animation" +text = "Mirror" + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer"] +margin_top = 165.0 +margin_right = 110.0 +margin_bottom = 200.0 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer"] +margin_right = 110.0 +margin_bottom = 35.0 +rect_min_size = Vector2( 0, 35 ) + +[node name="Control2" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 168.0 +margin_right = 218.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="preview" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 222.0 +margin_right = 342.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 100, 200 ) + +[node name="anim_preview_background" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview"] +margin_right = 120.0 +margin_bottom = 200.0 +hint_tooltip = "Animation preview based on current animation settings" +color = Color( 0.215686, 0.207843, 0.207843, 1 ) + +[node name="MarginContainer" type="CenterContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview"] +margin_right = 120.0 +margin_bottom = 200.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="anim_preview_sprite" type="AnimatedSprite" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview/MarginContainer"] +visible = false +scale = Vector2( 0.05, 0.05 ) +frames = SubResource( 1 ) +animation = "in_progress" +playing = true +centered = false + +[node name="no_anim_found_sprite" type="TextureRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/preview/MarginContainer"] +margin_left = 10.0 +margin_right = 110.0 +margin_bottom = 200.0 +texture = ExtResource( 9 ) + +[node name="Control3" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 346.0 +margin_right = 396.0 +margin_bottom = 200.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="Control4" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_top = 204.0 +margin_right = 50.0 +margin_bottom = 218.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="current_direction_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 54.0 +margin_top = 204.0 +margin_right = 164.0 +margin_bottom = 218.0 +text = "Current Direction" + +[node name="Control5" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 168.0 +margin_top = 204.0 +margin_right = 218.0 +margin_bottom = 218.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="anim_preview_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 222.0 +margin_top = 204.0 +margin_right = 342.0 +margin_bottom = 218.0 +text = "Animation Preview" + +[node name="Control6" type="Control" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2"] +margin_left = 346.0 +margin_top = 204.0 +margin_right = 396.0 +margin_bottom = 218.0 +rect_min_size = Vector2( 50, 0 ) + +[node name="MarginContainer3" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_top = 332.0 +margin_right = 400.0 +margin_bottom = 382.0 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/MarginContainer3"] +margin_right = 400.0 +margin_bottom = 50.0 +rect_min_size = Vector2( 0, 50 ) + +[node name="autosave" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation"] +margin_top = 386.0 +margin_right = 400.0 +margin_bottom = 438.0 +rect_min_size = Vector2( 400, 50 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave"] +margin_right = 400.0 +margin_bottom = 24.0 + +[node name="autosave_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="Autosave_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 395.0 +margin_bottom = 19.0 +text = "Autosave changes" + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/MarginContainer"] +margin_right = 400.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="Autosave_label" type="Label" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/MarginContainer/MarginContainer2"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 395.0 +margin_bottom = 19.0 +text = "Autosave changes" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave"] +margin_top = 28.0 +margin_right = 400.0 +margin_bottom = 52.0 +custom_constants/separation = 50 +alignment = 1 + +[node name="AutoStoreCheckBox" type="CheckBox" parent="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/HBoxContainer"] +margin_left = 60.0 +margin_right = 339.0 +margin_bottom = 24.0 +hint_tooltip = "All changes in this tool are automatically saved for a quicker workflow." +text = "Auto-store all changes to this character" + +[node name="spritesheet" type="MarginContainer" parent="VBoxContainer/HBoxContainer"] +margin_left = 420.0 +margin_right = 870.0 +margin_bottom = 782.0 +rect_min_size = Vector2( 440, 550 ) +mouse_filter = 1 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="spritesheet_background" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet"] +margin_right = 450.0 +margin_bottom = 782.0 +mouse_filter = 1 +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet"] +margin_right = 450.0 +margin_bottom = 782.0 +rect_min_size = Vector2( 450, 550 ) +mouse_filter = 1 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 445.0 +margin_bottom = 777.0 + +[node name="spritesheet_scroll_container" type="ScrollContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer"] +margin_right = 440.0 +margin_bottom = 714.0 +hint_tooltip = "Loaded spritesheet" +mouse_filter = 1 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="control" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container"] +margin_right = 440.0 +margin_bottom = 714.0 +rect_min_size = Vector2( 192, 210 ) +mouse_filter = 1 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="spritesheet_area" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control"] +margin_right = 440.0 +margin_bottom = 714.0 +mouse_filter = 1 +color = Color( 0.203922, 0.184314, 0.184314, 1 ) + +[node name="spritesheet_sprite" type="TextureRect" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control"] +margin_right = 240.0 +margin_bottom = 25.0 +rect_min_size = Vector2( 240, 25 ) +size_flags_horizontal = 0 +size_flags_vertical = 0 +expand = true + +[node name="frame_rectangles" type="Control" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control"] +margin_right = 440.0 +margin_bottom = 714.0 +mouse_filter = 1 +script = ExtResource( 36 ) +total_num_rows = 1 +total_num_columns = 1 +cell_size = Vector2( 1, 1 ) +zoom_factor = 0.01 + +[node name="MarginContainer" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control"] +margin_right = 440.0 +margin_bottom = 714.0 +mouse_filter = 1 + +[node name="no_spritesheet_found_sprite" type="TextureRect" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control/MarginContainer"] +margin_left = 20.0 +margin_top = 157.0 +margin_right = 420.0 +margin_bottom = 557.0 +texture = ExtResource( 29 ) + +[node name="zoom_scroll" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer"] +margin_top = 718.0 +margin_right = 440.0 +margin_bottom = 738.0 +rect_min_size = Vector2( 440, 0 ) + +[node name="zoom_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll"] +margin_top = 3.0 +margin_right = 80.0 +margin_bottom = 17.0 +rect_min_size = Vector2( 80, 0 ) +text = "Zoom: 1x" + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll"] +margin_left = 84.0 +margin_right = 388.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="zoom_scrollbar" type="HScrollBar" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll/MarginContainer"] +margin_right = 304.0 +margin_bottom = 20.0 +hint_tooltip = "Current spritesheet zoom level" +size_flags_horizontal = 3 +size_flags_vertical = 3 +min_value = 0.1 +max_value = 5.0 +value = 1.0 + +[node name="zoom_reset_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll"] +margin_left = 392.0 +margin_right = 440.0 +margin_bottom = 20.0 +hint_tooltip = "Reset spritesheet zoom" +text = "Reset" + +[node name="zoom_current" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer"] +margin_top = 742.0 +margin_right = 440.0 +margin_bottom = 772.0 +rect_min_size = Vector2( 440, 30 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_current"] +margin_right = 128.0 +margin_bottom = 30.0 + +[node name="current_spritesheet" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_current/MarginContainer"] +margin_top = 8.0 +margin_right = 128.0 +margin_bottom = 22.0 +text = "Current spritesheet:" + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_current"] +margin_left = 132.0 +margin_right = 440.0 +margin_bottom = 30.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="current_spritesheet_label" type="TextEdit" parent="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_current/MarginContainer2"] +margin_right = 308.0 +margin_bottom = 30.0 +size_flags_horizontal = 3 +text = "No spritesheet loaded." +readonly = true + +[node name="spritesheet_controls" type="MarginContainer" parent="VBoxContainer/HBoxContainer"] +margin_left = 890.0 +margin_right = 1190.0 +margin_bottom = 782.0 +rect_min_size = Vector2( 300, 450 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="background_colorrect" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet_controls"] +margin_right = 300.0 +margin_bottom = 782.0 +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls"] +margin_right = 300.0 +margin_bottom = 782.0 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_right = 300.0 +margin_bottom = 30.0 +custom_constants/margin_bottom = 6 + +[node name="name_colorrect3" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer"] +margin_right = 300.0 +margin_bottom = 24.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer"] +margin_right = 300.0 +margin_bottom = 24.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 295.0 +margin_bottom = 19.0 +text = "Spritesheet Details" + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 34.0 +margin_right = 300.0 +margin_bottom = 54.0 + +[node name="load_spritesheet_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/CenterContainer"] +margin_left = 90.0 +margin_right = 209.0 +margin_bottom = 20.0 +hint_tooltip = "Load a new spritesheet to create animations" +text = "Load spritesheet" + +[node name="spritesheet_details_container" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 58.0 +margin_right = 300.0 +margin_bottom = 256.0 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container"] +margin_left = 20.0 +margin_right = 280.0 +margin_bottom = 198.0 +rect_min_size = Vector2( 260, 0 ) +custom_constants/vseparation = 10 +custom_constants/hseparation = 8 +columns = 2 + +[node name="h_frames_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 5.0 +margin_right = 154.0 +margin_bottom = 19.0 +text = "Horizontal frames:" +align = 2 + +[node name="h_frames_spin_box" type="SpinBox" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_right = 236.0 +margin_bottom = 24.0 +hint_tooltip = "Divide spritesheet into this many horizontal frames" +min_value = 1.0 +value = 1.0 +exp_edit = true +rounded = true + +[node name="v_frames_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 39.0 +margin_right = 154.0 +margin_bottom = 53.0 +text = "Vertical frames:" +align = 2 + +[node name="v_frames_spin_box" type="SpinBox" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 34.0 +margin_right = 236.0 +margin_bottom = 58.0 +hint_tooltip = "Divide spritesheet into this many vertical frames" +min_value = 1.0 +value = 1.0 +rounded = true + +[node name="start_frame_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 73.0 +margin_right = 154.0 +margin_bottom = 87.0 +text = "Start frame:" +align = 2 + +[node name="start_frame" type="SpinBox" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 68.0 +margin_right = 236.0 +margin_bottom = 92.0 +hint_tooltip = "Start frame to use for this animation" +max_value = 1000.0 +rounded = true + +[node name="end_frame_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 107.0 +margin_right = 154.0 +margin_bottom = 121.0 +text = "End frame:" +align = 2 + +[node name="end_frame" type="SpinBox" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 102.0 +margin_right = 236.0 +margin_bottom = 126.0 +hint_tooltip = "End frame to use for this animation" +max_value = 1000.0 +rounded = true + +[node name="anim_speed_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 136.0 +margin_right = 154.0 +margin_bottom = 150.0 +text = "Animation speed: 5 FPS" +align = 2 + +[node name="anim_speed_scroll_bar" type="HScrollBar" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 136.0 +margin_right = 236.0 +margin_bottom = 148.0 +hint_tooltip = "Speed of the current animation" +min_value = 1.0 +max_value = 60.0 +step = 1.0 +value = 5.0 +rounded = true + +[node name="original_size_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 160.0 +margin_right = 154.0 +margin_bottom = 174.0 +text = "Source sprite size: (0, 0)" +align = 2 + +[node name="empty_node2" type="Control" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 160.0 +margin_right = 236.0 +margin_bottom = 174.0 + +[node name="frame_size_label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_top = 184.0 +margin_right = 154.0 +margin_bottom = 198.0 +text = "Frame size: (0, 0)" +align = 2 + +[node name="empty_node3" type="Control" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer"] +margin_left = 162.0 +margin_top = 184.0 +margin_right = 236.0 +margin_bottom = 198.0 + +[node name="empty_node" type="Control" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 260.0 +margin_right = 300.0 +margin_bottom = 310.0 +rect_min_size = Vector2( 0, 50 ) + +[node name="store_anim" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +visible = false +margin_top = 314.0 +margin_right = 300.0 +margin_bottom = 414.0 +rect_min_size = Vector2( 300, 100 ) +custom_constants/separation = 10 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim"] +margin_right = 300.0 +margin_bottom = 36.0 + +[node name="name_colorrect2" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim/MarginContainer"] +margin_right = 300.0 +margin_bottom = 36.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim/MarginContainer"] +margin_right = 300.0 +margin_bottom = 36.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim/MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 295.0 +margin_bottom = 36.0 +size_flags_vertical = 6 +text = "Store Animation +" +valign = 1 + +[node name="CenterContainer2" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim"] +margin_top = 46.0 +margin_right = 300.0 +margin_bottom = 66.0 + +[node name="anim_store_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim/CenterContainer2"] +margin_left = 92.0 +margin_right = 207.0 +margin_bottom = 20.0 +text = "Store Animation" + +[node name="MarginContainer2" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 314.0 +margin_right = 300.0 +margin_bottom = 379.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer2"] +margin_left = 17.0 +margin_right = 283.0 +margin_bottom = 65.0 + +[node name="export_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer2/VBoxContainer"] +margin_right = 266.0 +margin_bottom = 61.0 +hint_tooltip = "Export all animations to a Godot scene" +custom_colors/font_color = Color( 0, 1, 0.0392157, 1 ) +text = "Export Character to Godot Scene" +icon = ExtResource( 32 ) + +[node name="name_colorrect4" type="ColorRect" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer2/VBoxContainer"] +margin_top = 65.0 +margin_right = 266.0 +margin_bottom = 65.0 +color = Color( 0.215686, 0.478431, 0.235294, 1 ) + +[node name="empty_node2" type="Control" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 383.0 +margin_right = 300.0 +margin_bottom = 663.0 +rect_min_size = Vector2( 0, 280 ) + +[node name="MarginContainer3" type="CenterContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer"] +margin_top = 667.0 +margin_right = 300.0 +margin_bottom = 687.0 + +[node name="HBoxContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3"] +margin_left = 48.0 +margin_right = 251.0 +margin_bottom = 20.0 +custom_constants/hseparation = 15 +columns = 3 + +[node name="help_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer"] +margin_right = 42.0 +margin_bottom = 20.0 +hint_tooltip = "Export all animations to a Godot scene" +text = "Help" + +[node name="reset_button" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer"] +margin_left = 57.0 +margin_right = 105.0 +margin_bottom = 20.0 +text = "Reset" + +[node name="main_menu" type="Button" parent="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer"] +margin_left = 120.0 +margin_right = 203.0 +margin_bottom = 20.0 +text = "Main Menu" + +[node name="ImageFileDialog" type="FileDialog" parent="."] +margin_left = 50.0 +margin_top = 50.0 +margin_right = 1240.0 +margin_bottom = 850.0 +popup_exclusive = true +window_title = "Open a File" +mode = 0 +access = 2 +filters = PoolStringArray( "*.png, *.jpg, *.jpeg ; Supported Images" ) + +[node name="CharacterPathFileDialog" type="FileDialog" parent="."] +margin_left = 50.0 +margin_top = 50.0 +margin_right = 1240.0 +margin_bottom = 850.0 +window_title = "Open a Directory" +mode = 2 + +[node name="InformationWindows" type="Control" parent="."] +visible = false +margin_left = 50.0 +margin_top = 50.0 +margin_right = 1240.0 +margin_bottom = 850.0 + +[node name="unstored_changes_window" type="WindowDialog" parent="InformationWindows"] +margin_left = 295.0 +margin_top = 154.0 +margin_right = 985.0 +margin_bottom = 454.0 +popup_exclusive = true +window_title = "WARNING : Unstored changes" + +[node name="Label" type="Label" parent="InformationWindows/unstored_changes_window"] +margin_left = 86.0 +margin_top = 57.0 +margin_right = 605.0 +margin_bottom = 156.0 +text = "WARNING : You have made changes to this animation which haven't been stored. + +You can +* Commit the changes, and then change to the selected direction. +* Lose the changes, and then change to the selected direction. +* Cancel the request to change directions and keep editing this direction." + +[node name="commit_button" type="Button" parent="InformationWindows/unstored_changes_window"] +margin_left = 45.0 +margin_top = 250.0 +margin_right = 215.0 +margin_bottom = 270.0 +text = "Commit changes" + +[node name="lose_button" type="Button" parent="InformationWindows/unstored_changes_window"] +margin_left = 260.0 +margin_top = 250.0 +margin_right = 430.0 +margin_bottom = 270.0 +text = "Lose changes" + +[node name="cancel_button" type="Button" parent="InformationWindows/unstored_changes_window"] +margin_left = 475.0 +margin_top = 250.0 +margin_right = 645.0 +margin_bottom = 270.0 +text = "Cancel and keep editing" + +[node name="unstored_changes_window_anim_change" type="WindowDialog" parent="InformationWindows"] +margin_left = 295.0 +margin_top = 154.0 +margin_right = 985.0 +margin_bottom = 454.0 +popup_exclusive = true +window_title = "WARNING : Unstored changes" + +[node name="Label" type="Label" parent="InformationWindows/unstored_changes_window_anim_change"] +margin_left = 86.0 +margin_top = 57.0 +margin_right = 605.0 +margin_bottom = 156.0 +text = "WARNING : You have made changes to this animation which haven't been stored. + +You can +* Commit the changes, and then change to the selected direction. +* Lose the changes, and then change to the selected direction. +* Cancel the request to change directions and keep editing this direction." + +[node name="commit_button" type="Button" parent="InformationWindows/unstored_changes_window_anim_change"] +margin_left = 45.0 +margin_top = 250.0 +margin_right = 215.0 +margin_bottom = 270.0 +text = "Commit changes" + +[node name="lose_button" type="Button" parent="InformationWindows/unstored_changes_window_anim_change"] +margin_left = 260.0 +margin_top = 250.0 +margin_right = 430.0 +margin_bottom = 270.0 +text = "Lose changes" + +[node name="cancel_button" type="Button" parent="InformationWindows/unstored_changes_window_anim_change"] +margin_left = 475.0 +margin_top = 250.0 +margin_right = 645.0 +margin_bottom = 270.0 +text = "Cancel and keep editing" + +[node name="generic_error_window" type="AcceptDialog" parent="InformationWindows"] +margin_left = 343.0 +margin_top = 242.0 +margin_right = 943.0 +margin_bottom = 402.0 +input_pass_on_modal_close_click = false +popup_exclusive = true +dialog_text = "Please load a spritesheet to begin." + +[node name="export_progress" type="WindowDialog" parent="InformationWindows"] +visible = true +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -151.0 +margin_top = -87.0 +margin_right = 249.0 +margin_bottom = 113.0 +size_flags_horizontal = 3 +popup_exclusive = true +window_title = "Export Status" + +[node name="progress_label" type="Label" parent="InformationWindows/export_progress"] +anchor_left = 0.5 +anchor_right = 0.5 +margin_left = -200.0 +margin_top = 30.0 +margin_right = 200.0 +margin_bottom = 78.0 +size_flags_horizontal = 3 +size_flags_vertical = 5 +text = "Exporting animations to ESCPlayer node." +align = 1 + +[node name="progress_bar" type="ProgressBar" parent="InformationWindows/export_progress"] +margin_left = 50.0 +margin_top = 100.0 +margin_right = 350.0 +margin_bottom = 130.0 +max_value = 31.0 +rounded = true + +[node name="export_complete" type="AcceptDialog" parent="InformationWindows"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -208.0 +margin_top = -132.0 +margin_right = 309.0 +margin_bottom = 147.0 +window_title = "Export complete" +dialog_text = "The new ESCPlayer node has now been exported. +For your convenience, it has been automatically opened in the Godot editor. + +Some actions you may now want to perform: + +* A dialog position node has been created. This is where text will appear when +the player talks. You will want to move this either above the character's head +or below their feet. + +* The CollisionShape child node defines the bounds of the character. You may +want to resize or change the shape assigned to this node. + +* You may want to shift this node to a different directory in your codebase +(e.g. into a \"characters\" folder) to group it with other game characters." + +[node name="help_window" parent="InformationWindows" instance=ExtResource( 38 )] + +[node name="ConfirmationDialog" type="ConfirmationDialog" parent="InformationWindows"] +margin_left = 479.0 +margin_top = 312.0 +margin_right = 817.0 +margin_bottom = 404.0 +popup_exclusive = true +dialog_text = "WARNING! + +If you continue you will lose the current character." + +[node name="MainMenuConfirmation" type="ConfirmationDialog" parent="InformationWindows"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -122.5 +margin_top = -46.0 +margin_right = 122.5 +margin_bottom = 46.0 +dialog_text = "If you return to the main menu +you will lose your current character. +" + +[connection signal="text_changed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer/node_name" to="." method="nodename_on_node_name_text_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/node_name/MarginContainer2/GridContainer/character_path_change_button" to="." method="_on_character_path_change_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/HBoxContainer/four_directions" to="." method="directions_on_four_directions_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/directions/HBoxContainer/eight_directions" to="." method="directions_on_eight_directions_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer/walk_checkbox" to="." method="animation_on_walk_checkbox_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer/talk_checkbox" to="." method="animation_on_talk_checkbox_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer/idle_checkbox" to="." method="animation_on_idle_checkbox_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upleft/set_dir_upleft" to="." method="animation_on_dir_upleft_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upleft/unset_dir_upleft" to="." method="animation_on_dir_upleft_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_up/set_dir_up" to="." method="animation_on_dir_up_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_up/unset_dir_up" to="." method="animation_on_dir_up_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upright/unset_dir_upright" to="." method="animation_on_dir_upright_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_upright/set_dir_upright" to="." method="animation_on_dir_upright_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_left/set_dir_left" to="." method="animation_on_dir_left_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_left/unset_dir_left" to="." method="animation_on_dir_left_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_right/set_dir_right" to="." method="animation_on_dir_right_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_right/unset_dir_right" to="." method="animation_on_dir_right_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downleft/unset_dir_downleft" to="." method="animation_on_dir_downleft_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downleft/set_dir_downleft" to="." method="animation_on_dir_downleft_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_down/set_dir_down" to="." method="animation_on_dir_down_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_down/unset_dir_down" to="." method="animation_on_dir_down_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downright/set_dir_downright" to="." method="animation_on_dir_downright_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer2/GridContainer/Container_downright/unset_dir_downright" to="." method="animation_on_dir_downright_pressed"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/HBoxContainer2/HBoxContainer/MarginContainer3/mirror_checkbox" to="." method="animation_on_mirror_checkbox_toggled"] +[connection signal="toggled" from="VBoxContainer/HBoxContainer/configuration/VBoxContainer/animation/autosave/HBoxContainer/AutoStoreCheckBox" to="." method="_on_AutoStoreCheckBox_toggled"] +[connection signal="gui_input" from="VBoxContainer/HBoxContainer/spritesheet" to="." method="_on_spritesheet_gui_input"] +[connection signal="gui_input" from="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/spritesheet_scroll_container/control" to="." method="_on_control_gui_input"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll/MarginContainer/zoom_scrollbar" to="." method="spritesheet_on_zoom_scrollbar_value_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet/MarginContainer/VBoxContainer/zoom_scroll/zoom_reset_button" to="." method="spritesheet_on_zoom_reset_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/CenterContainer/load_spritesheet_button" to="." method="spritesheet_on_load_spritesheet_button_pressed"] +[connection signal="changed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/spritesheet_details_container/GridContainer/anim_speed_scroll_bar" to="." method="controls_on_anim_speed_scroll_bar_value_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/store_anim/CenterContainer2/anim_store_button" to="." method="store_on_anim_store_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer2/VBoxContainer/export_button" to="." method="spritesheet_on_export_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer/help_button" to="." method="spritesheet_on_help_button_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer/reset_button" to="." method="spritesheet_on_reset_button_pressed"] +[connection signal="button_up" from="VBoxContainer/HBoxContainer/spritesheet_controls/VBoxContainer/MarginContainer3/HBoxContainer/main_menu" to="." method="spritesheet_on_main_menu_button_up"] +[connection signal="file_selected" from="ImageFileDialog" to="." method="controls_on_FileDialog_file_selected"] +[connection signal="dir_selected" from="CharacterPathFileDialog" to="." method="_on_CharacterPathFileDialog_dir_selected"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window/commit_button" to="." method="unstored_warning_on_commit_button_pressed"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window/lose_button" to="." method="unstored_warning_on_lose_button_pressed"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window/cancel_button" to="." method="unstored_warning_on_cancel_button_pressed"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window_anim_change/commit_button" to="." method="unstored_animchange_warning_on_commit_button_pressed"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window_anim_change/lose_button" to="." method="unstored_animchange_warning_on_lose_button_pressed"] +[connection signal="pressed" from="InformationWindows/unstored_changes_window_anim_change/cancel_button" to="." method="unstored_animchange_warning_on_cancel_button_pressed"] +[connection signal="confirmed" from="InformationWindows/ConfirmationDialog" to="." method="spritesheet_on_reset_confirmed"] +[connection signal="confirmed" from="InformationWindows/MainMenuConfirmation" to="." method="spritesheet_on_MainMenuConfirmation_confirmed"] diff --git a/addons/escoria-wizard/ItemCreator.tscn b/addons/escoria-wizard/ItemCreator.tscn new file mode 100644 index 00000000..7c497cd6 --- /dev/null +++ b/addons/escoria-wizard/ItemCreator.tscn @@ -0,0 +1,436 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/escoria-wizard/item_creator.gd" type="Script" id=1] +[ext_resource path="res://addons/escoria-wizard/graphics/inventory_preview.png" type="Texture" id=2] +[ext_resource path="res://addons/escoria-wizard/graphics/object_preview.png" type="Texture" id=3] + +[node name="ItemCreator" type="MarginContainer"] +margin_left = 395.0 +margin_top = 50.0 +margin_right = 895.0 +margin_bottom = 850.0 +rect_min_size = Vector2( 500, 500 ) +mouse_filter = 1 +size_flags_horizontal = 4 +size_flags_vertical = 4 +script = ExtResource( 1 ) + +[node name="window_background_colour" type="ColorRect" parent="."] +margin_right = 500.0 +margin_bottom = 800.0 +rect_min_size = Vector2( 500, 800 ) +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_right = 500.0 +margin_bottom = 800.0 + +[node name="Control" type="Control" parent="VBoxContainer"] +margin_right = 500.0 +margin_bottom = 60.0 +rect_min_size = Vector2( 0, 60 ) + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/Control"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -183.5 +margin_top = -20.0 +margin_right = 183.5 +margin_bottom = 20.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/Control/CenterContainer"] +margin_left = 3.0 +margin_top = 8.0 +margin_right = 364.0 +margin_bottom = 32.0 + +[node name="BackgroundObjectCheckBox" type="CheckBox" parent="VBoxContainer/Control/CenterContainer/HBoxContainer"] +margin_right = 190.0 +margin_bottom = 24.0 +pressed = true +text = "Create background object" + +[node name="InventoryItemCheckBox" type="CheckBox" parent="VBoxContainer/Control/CenterContainer/HBoxContainer"] +margin_left = 194.0 +margin_right = 361.0 +margin_bottom = 24.0 +text = "Create inventory item" + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +margin_top = 64.0 +margin_right = 500.0 +margin_bottom = 68.0 + +[node name="HelperHeading" type="MarginContainer" parent="VBoxContainer"] +margin_top = 72.0 +margin_right = 500.0 +margin_bottom = 112.0 +rect_min_size = Vector2( 0, 40 ) + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/HelperHeading"] +margin_right = 500.0 +margin_bottom = 40.0 + +[node name="ObjectHeading" type="Label" parent="VBoxContainer/HelperHeading/CenterContainer"] +margin_left = 196.0 +margin_top = 13.0 +margin_right = 303.0 +margin_bottom = 27.0 +custom_colors/font_color = Color( 0.592157, 0.87451, 0.533333, 1 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 1 ) +text = "Object Creator" +uppercase = true + +[node name="InventoryHeading" type="Label" parent="VBoxContainer/HelperHeading/CenterContainer"] +visible = false +margin_left = 165.0 +margin_top = 13.0 +margin_right = 335.0 +margin_bottom = 27.0 +custom_colors/font_color = Color( 0.592157, 0.87451, 0.533333, 1 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 1 ) +text = "Inventory Item Creator" +uppercase = true + +[node name="Description" type="MarginContainer" parent="VBoxContainer"] +margin_top = 116.0 +margin_right = 500.0 +margin_bottom = 232.0 + +[node name="ObjectDescription" type="Label" parent="VBoxContainer/Description"] +margin_right = 500.0 +margin_bottom = 116.0 +text = "The object creator is used to create background objects +that the player can interact with, but that will not become +part of their inventory. + +NOTE: The node will be created as a child of whichever node +is currently selected in the scene tree. +" +align = 1 + +[node name="InventoryDescription" type="Label" parent="VBoxContainer/Description"] +visible = false +margin_right = 500.0 +margin_bottom = 116.0 +text = "The inventory item creator is used to create objects +that the player can pick up to add +to their inventory. + +NOTE: The node will be created in the inventory folder shown +below. You can change this in Godot's settings under: +\"Escoria/UI/Items autoregister path\"" +align = 1 + +[node name="Content" type="MarginContainer" parent="VBoxContainer"] +margin_top = 236.0 +margin_right = 500.0 +margin_bottom = 736.0 +rect_min_size = Vector2( 0, 500 ) +mouse_filter = 1 +custom_constants/margin_right = 20 +custom_constants/margin_top = 0 +custom_constants/margin_left = 20 + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/Content"] +margin_left = 20.0 +margin_right = 480.0 +margin_bottom = 500.0 +rect_min_size = Vector2( 460, 500 ) +columns = 3 + +[node name="ItemNameLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 5.0 +margin_right = 110.0 +margin_bottom = 19.0 +text = "Item name:" + +[node name="ItemName" type="LineEdit" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_right = 354.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 200, 0 ) +text = "replace_me" + +[node name="BlankItem" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_right = 460.0 +margin_bottom = 24.0 + +[node name="ItemGlobalIDLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 33.0 +margin_right = 110.0 +margin_bottom = 47.0 +text = "Global ID:" + +[node name="ItemGlobalID" type="LineEdit" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 28.0 +margin_right = 354.0 +margin_bottom = 52.0 + +[node name="BlankItem2" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 28.0 +margin_right = 460.0 +margin_bottom = 52.0 + +[node name="StartsInteractiveLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 61.0 +margin_right = 110.0 +margin_bottom = 75.0 +rect_min_size = Vector2( 110, 0 ) +text = "Is 'Interactive':" + +[node name="StartsInteractiveCheckBox" type="CheckBox" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 56.0 +margin_right = 354.0 +margin_bottom = 80.0 +hint_tooltip = "When the room first loads, can the player interact with this?" +pressed = true + +[node name="BlankItem3" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 56.0 +margin_right = 460.0 +margin_bottom = 80.0 + +[node name="DefaultActionLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 84.0 +margin_right = 110.0 +margin_bottom = 115.0 +text = "Default action: +" +valign = 1 + +[node name="DefaultActionOption" type="OptionButton" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 84.0 +margin_right = 354.0 +margin_bottom = 115.0 +rect_min_size = Vector2( 200, 31 ) +text = "look" +items = [ "look", null, false, 0, null, "pick up", null, false, 1, null, "open", null, false, 2, null, "close", null, false, 3, null, "use", null, false, 4, null, "push", null, false, 5, null, "pull", null, false, 6, null, "talk", null, false, 7, null ] +selected = 0 + +[node name="BlankItem4" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 84.0 +margin_right = 460.0 +margin_bottom = 115.0 + +[node name="ImagePathLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 124.0 +margin_right = 110.0 +margin_bottom = 138.0 +text = "Item graphic:" + +[node name="ImagePath" type="LineEdit" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 119.0 +margin_right = 354.0 +margin_bottom = 143.0 +editable = false + +[node name="ChangeImageButton" type="Button" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 119.0 +margin_right = 460.0 +margin_bottom = 143.0 +text = "Change Image" + +[node name="PreviewLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 260.0 +margin_right = 110.0 +margin_bottom = 274.0 +text = "Preview:" + +[node name="Preview" type="ColorRect" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 147.0 +margin_right = 354.0 +margin_bottom = 387.0 +rect_min_size = Vector2( 240, 240 ) +color = Color( 0.121569, 0.196078, 0.0823529, 1 ) + +[node name="BackgroundColour" type="ColorRect" parent="VBoxContainer/Content/GridContainer/Preview"] +margin_left = 4.0 +margin_top = 4.0 +margin_right = 236.0 +margin_bottom = 236.0 +rect_min_size = Vector2( 232, 232 ) +color = Color( 0.254902, 0.231373, 0.231373, 1 ) + +[node name="InventoryPreview" type="TextureRect" parent="VBoxContainer/Content/GridContainer/Preview"] +visible = false +margin_left = 4.0 +margin_top = 4.0 +margin_right = 236.0 +margin_bottom = 236.0 +texture = ExtResource( 2 ) + +[node name="ObjectPreview" type="TextureRect" parent="VBoxContainer/Content/GridContainer/Preview"] +margin_left = 4.0 +margin_top = 4.0 +margin_right = 236.0 +margin_bottom = 236.0 +texture = ExtResource( 3 ) + +[node name="Preview" type="TextureRect" parent="VBoxContainer/Content/GridContainer/Preview"] +margin_left = 4.0 +margin_top = 4.0 +margin_right = 236.0 +margin_bottom = 236.0 +rect_min_size = Vector2( 232, 232 ) + +[node name="BlankItem5" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 147.0 +margin_right = 460.0 +margin_bottom = 387.0 + +[node name="ImageSizeLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_top = 391.0 +margin_right = 110.0 +margin_bottom = 405.0 +text = "Image size:" + +[node name="ImageSize" type="Label" parent="VBoxContainer/Content/GridContainer"] +margin_left = 114.0 +margin_top = 391.0 +margin_right = 354.0 +margin_bottom = 405.0 +text = "(0, 0)" + +[node name="BlankItem6" type="Control" parent="VBoxContainer/Content/GridContainer"] +margin_left = 358.0 +margin_top = 391.0 +margin_right = 460.0 +margin_bottom = 405.0 + +[node name="InventoryPathLabel" type="Label" parent="VBoxContainer/Content/GridContainer"] +visible = false +margin_top = 409.0 +margin_right = 110.0 +margin_bottom = 423.0 +text = "Inventory path:" + +[node name="InventoryPath" type="Label" parent="VBoxContainer/Content/GridContainer"] +visible = false +margin_left = 114.0 +margin_top = 409.0 +margin_right = 354.0 +margin_bottom = 423.0 +text = "res://" + +[node name="BlankItem7" type="Control" parent="VBoxContainer/Content/GridContainer"] +visible = false +margin_left = 114.0 +margin_top = 409.0 +margin_right = 354.0 +margin_bottom = 423.0 + +[node name="Buttons" type="MarginContainer" parent="VBoxContainer"] +margin_top = 740.0 +margin_right = 500.0 +margin_bottom = 770.0 +mouse_filter = 2 +custom_constants/margin_bottom = 10 + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/Buttons"] +margin_right = 500.0 +margin_bottom = 20.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/Buttons/CenterContainer"] +margin_left = 98.0 +margin_right = 402.0 +margin_bottom = 20.0 + +[node name="CreateButton" type="Button" parent="VBoxContainer/Buttons/CenterContainer/HBoxContainer"] +margin_right = 100.0 +margin_bottom = 20.0 +text = "Create Object" + +[node name="Spacer" type="Control" parent="VBoxContainer/Buttons/CenterContainer/HBoxContainer"] +margin_left = 104.0 +margin_right = 124.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 20, 0 ) + +[node name="ClearButton" type="Button" parent="VBoxContainer/Buttons/CenterContainer/HBoxContainer"] +margin_left = 128.0 +margin_right = 193.0 +margin_bottom = 20.0 +text = "Clear All" + +[node name="Spacer2" type="Control" parent="VBoxContainer/Buttons/CenterContainer/HBoxContainer"] +margin_left = 197.0 +margin_right = 217.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 20, 0 ) + +[node name="ExitButton" type="Button" parent="VBoxContainer/Buttons/CenterContainer/HBoxContainer"] +margin_left = 221.0 +margin_right = 304.0 +margin_bottom = 20.0 +text = "Main Menu" + +[node name="LoadObjectGraphic" type="CenterContainer" parent="."] +visible = false +margin_right = 500.0 +margin_bottom = 800.0 +mouse_filter = 2 + +[node name="LoadObjectFileDialog" type="FileDialog" parent="LoadObjectGraphic"] +margin_left = -150.0 +margin_top = 100.0 +margin_right = 650.0 +margin_bottom = 700.0 +rect_min_size = Vector2( 800, 600 ) +popup_exclusive = true +window_title = "Open a File" +mode = 0 +filters = PoolStringArray( "*.png", "*.bmp", "*.jpg", "*.jpeg", "*.webp", "*.tga" ) + +[node name="Windows" type="CenterContainer" parent="."] +visible = false +margin_right = 500.0 +margin_bottom = 800.0 + +[node name="ConfirmationDialog" type="ConfirmationDialog" parent="Windows"] +margin_left = 90.0 +margin_top = 354.0 +margin_right = 409.0 +margin_bottom = 446.0 +dialog_text = "WARNING! + +If you continue you will lose the current object." + +[node name="ErrorDialog" type="AcceptDialog" parent="Windows"] +margin_left = 208.0 +margin_top = 371.0 +margin_right = 291.0 +margin_bottom = 429.0 + +[node name="CreateCompleteDialog" type="AcceptDialog" parent="Windows"] +margin_left = 208.0 +margin_top = 371.0 +margin_right = 291.0 +margin_bottom = 429.0 + +[connection signal="toggled" from="VBoxContainer/Control/CenterContainer/HBoxContainer/BackgroundObjectCheckBox" to="." method="_on_BackgroundObjectCheckBox_toggled"] +[connection signal="toggled" from="VBoxContainer/Control/CenterContainer/HBoxContainer/InventoryItemCheckBox" to="." method="_on_InventoryItemCheckBox_toggled"] +[connection signal="text_changed" from="VBoxContainer/Content/GridContainer/ItemName" to="." method="background_on_ItemName_text_changed"] +[connection signal="text_changed" from="VBoxContainer/Content/GridContainer/ItemGlobalID" to="." method="_on_ItemGlobalID_text_changed"] +[connection signal="pressed" from="VBoxContainer/Content/GridContainer/StartsInteractiveCheckBox" to="." method="_on_StartsInteractiveCheckBox_pressed"] +[connection signal="item_selected" from="VBoxContainer/Content/GridContainer/DefaultActionOption" to="." method="_on_DefaultActionOption_item_selected"] +[connection signal="pressed" from="VBoxContainer/Content/GridContainer/ChangeImageButton" to="." method="load_button_pressed"] +[connection signal="pressed" from="VBoxContainer/Buttons/CenterContainer/HBoxContainer/CreateButton" to="." method="_on_CreateButton_pressed"] +[connection signal="pressed" from="VBoxContainer/Buttons/CenterContainer/HBoxContainer/ClearButton" to="." method="Item_on_ClearButton_pressed"] +[connection signal="pressed" from="VBoxContainer/Buttons/CenterContainer/HBoxContainer/ExitButton" to="." method="Item_on_ExitButton_pressed"] +[connection signal="file_selected" from="LoadObjectGraphic/LoadObjectFileDialog" to="." method="LoadObjectFileDialog_file_selected"] +[connection signal="confirmed" from="Windows/ConfirmationDialog" to="." method="_on_ObjectConfirmationDialog_confirmed"] +[connection signal="confirmed" from="Windows/CreateCompleteDialog" to="." method="_on_CreateCompleteDialog_confirmed"] diff --git a/addons/escoria-wizard/RoomCreator.gd b/addons/escoria-wizard/RoomCreator.gd new file mode 100644 index 00000000..66b52b58 --- /dev/null +++ b/addons/escoria-wizard/RoomCreator.gd @@ -0,0 +1,323 @@ +tool +extends Control + +const ROOM_NAME = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/RoomName" +const GLOBAL_ID = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/GlobalID" +const PLAYER_SCENE = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/PlayerScene" +const SELECT_PLAYER_SCENE = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectPlayerScene" +const SELECT_PLAYER_SCENE_SPACER = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectPlayerSceneSpacer" +const USE_EMPTY_PLAYER_BUTTON = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyPlayerButton" +const ESC_SCRIPT = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/ESCScript" +const USE_EMPTY_ROOM_SCRIPT = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyRoomScript" +const USE_EMPTY_ROOM_SPACER = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyRoomSpacer" +const BACKGROUND_IMAGE = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/BackgroundImage" +const USE_EMPTY_BACKGROUND = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyBackground" +const SELECT_BACKGROUND = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectBackground" +const SELECT_BACKGROUNDSPACER = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectBackgroundSpacer" +const ROOM_FOLDER_PATH = "MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/RoomFolder" +const ROOM_BACKGROUND = "MarginContainer/MarginContainer/VBoxContainer/PreviewSection/CenterContainer/RoomBackground" +const BACKGROUND_PREVIEW = "MarginContainer/MarginContainer/VBoxContainer/PreviewSection/BackgroundPreview" + +const SCRIPT_BLANK_TEXT = "Room will not have a script configured." +const SCRIPT_SELECT_TEXT = "Please select script." +const PLAYER_BLANK_TEXT = "Scene will be left blank." +const PLAYER_SELECT_TEXT = "Please select scene." +const BACKGROUND_BLANK_TEXT = "Image will be left blank." +const BACKGROUND_SELECT_TEXT = "Please select image." + + +var settings_modified: bool + + +func _ready() -> void: + room_creator_reset() + $"InformationWindows/PlayerSceneFileDialog".get_cancel().connect("pressed", self, "PlayerSceneCancelled") + $"InformationWindows/BackgroundImageFileDialog".get_cancel().connect("pressed", self, "BackgroundFileCancelled") + + +func PlayerSceneCancelled() -> void: + if get_node(PLAYER_SCENE).text == PLAYER_SELECT_TEXT: + get_node(USE_EMPTY_PLAYER_BUTTON).pressed = true + + +func BackgroundFileCancelled() -> void: + if get_node(BACKGROUND_IMAGE).text == BACKGROUND_SELECT_TEXT: + get_node(USE_EMPTY_BACKGROUND).pressed = true + + +func room_creator_reset() -> void: + get_node(ROOM_NAME).text = "" + get_node(GLOBAL_ID).text = "" + get_node(PLAYER_SCENE).text = PLAYER_BLANK_TEXT + get_node(SELECT_PLAYER_SCENE).visible = false + get_node(SELECT_PLAYER_SCENE_SPACER).visible = true + get_node(USE_EMPTY_PLAYER_BUTTON).pressed = true + get_node(ESC_SCRIPT).editable = false + get_node(ESC_SCRIPT).text = SCRIPT_BLANK_TEXT + get_node(USE_EMPTY_ROOM_SCRIPT).pressed = true + get_node(BACKGROUND_IMAGE).text = BACKGROUND_BLANK_TEXT + get_node(USE_EMPTY_ROOM_SPACER).visible = true + get_node(USE_EMPTY_BACKGROUND).pressed = true + get_node(SELECT_BACKGROUND).visible = false + get_node(SELECT_BACKGROUNDSPACER).visible = true + get_node(BACKGROUND_PREVIEW).visible = true + get_node(ROOM_BACKGROUND).visible = true + get_node(BACKGROUND_PREVIEW).texture = null + get_node(ROOM_FOLDER_PATH).text = ProjectSettings.get_setting("escoria/debug/room_selector_room_dir") + $InformationWindows/RoomFolderDialog.current_dir = ProjectSettings.get_setting("escoria/debug/room_selector_room_dir") + settings_modified = false + + +func _on_RoomName_text_changed(new_text: String) -> void: + get_node(GLOBAL_ID).text = new_text + settings_modified = true + + +func _on_GlobalID_text_changed(new_text: String) -> void: + settings_modified = true + + +func _on_UseEmptyPlayerButton_toggled(button_pressed: bool) -> void: + if button_pressed == true: + get_node(SELECT_PLAYER_SCENE).visible = false + get_node(SELECT_PLAYER_SCENE_SPACER).visible = true + get_node(PLAYER_SCENE).text = PLAYER_BLANK_TEXT + else: + get_node(SELECT_PLAYER_SCENE).visible = true + get_node(SELECT_PLAYER_SCENE_SPACER).visible = false + get_node(PLAYER_SCENE).text = PLAYER_SELECT_TEXT + $"InformationWindows/PlayerSceneFileDialog".popup_centered() + + +func _on_SelectPlayerScene_pressed() -> void: + $"InformationWindows/PlayerSceneFileDialog".visible = true + $"InformationWindows/PlayerSceneFileDialog".invalidate() + + +func _on_PlayerSceneFileDialog_file_selected(path: String) -> void: + settings_modified = true + get_node(PLAYER_SCENE).text = path + + +func _on_UseEmptyRoomScript_toggled(button_pressed: bool) -> void: + if button_pressed == true: + get_node(ESC_SCRIPT).editable = false + get_node(ESC_SCRIPT).text = SCRIPT_BLANK_TEXT + else: + get_node(ESC_SCRIPT).editable = true + get_node(ESC_SCRIPT).text = "%s.esc" % get_node(GLOBAL_ID).text + + +func _on_SelectRoomScript_pressed() -> void: + $"InformationWindows/ESCScriptFileDialog".visible = true + $"InformationWindows/ESCScriptFileDialog".invalidate() + + +func _on_ESCScriptFileDialog_file_selected(path: String) -> void: + settings_modified = true + get_node(ESC_SCRIPT).text = path + + +func _on_UseEmptyBackground_toggled(button_pressed: bool) -> void: + if button_pressed == true: + get_node(SELECT_BACKGROUND).visible = false + get_node(SELECT_BACKGROUNDSPACER).visible = true + get_node(BACKGROUND_IMAGE).text = BACKGROUND_BLANK_TEXT + get_node(BACKGROUND_PREVIEW).texture = null + get_node(ROOM_BACKGROUND).visible = true + else: + get_node(SELECT_BACKGROUND).visible = true + get_node(SELECT_BACKGROUNDSPACER).visible = false + get_node(BACKGROUND_IMAGE).text = BACKGROUND_SELECT_TEXT + + var viewport_centre: Vector2 = get_viewport_rect().size / 2 + var dialog_start: Vector2 = $"InformationWindows/BackgroundImageFileDialog".rect_size / 2 + var dialog_pos: Vector2 = viewport_centre - dialog_start + $"InformationWindows/BackgroundImageFileDialog".rect_position = dialog_pos + + $"InformationWindows/BackgroundImageFileDialog".popup_centered() + + +func _on_SelectBackground_pressed() -> void: + var viewport_centre: Vector2 = get_viewport_rect().size / 2 + var dialog_start: Vector2 = $"InformationWindows/BackgroundImageFileDialog".rect_size / 2 + var dialog_pos: Vector2 = viewport_centre - dialog_start + $"InformationWindows/BackgroundImageFileDialog".rect_position = dialog_pos + + $"InformationWindows/BackgroundImageFileDialog".visible = true + $"InformationWindows/BackgroundImageFileDialog".invalidate() + + +func _on_BackgroundImageFileDialog_file_selected(path: String) -> void: + settings_modified = true + + get_node(BACKGROUND_IMAGE).text = path + + var image_stream_texture:StreamTexture + + image_stream_texture = load(path) + + var preview_size = get_node(ROOM_BACKGROUND).rect_size + + get_node(BACKGROUND_PREVIEW).texture = image_stream_texture + get_node(ROOM_BACKGROUND).visible = false + set_preview_scale() + + +func set_preview_scale() -> void: + var preview_scale = Vector2.ONE + # Calculate the scale to make the preview as big as possible in the preview window depending on + # the height to width ratio of the frame + var preview_size = get_node(ROOM_BACKGROUND).get_size() +# get_node(BACKGROUND_PREVIEW).rect_scale = Vector2.ONE + var image_size = get_node(BACKGROUND_PREVIEW).texture.get_size() + + preview_scale.x = preview_size.x / image_size.x + preview_scale.y = preview_size.y / image_size.y + +# print("scale = "+str(preview_scale)+", preview size = "+str(preview_size)+", image_size = "+str(image_size)) + if preview_scale.y > preview_scale.x: + get_node(BACKGROUND_PREVIEW).rect_scale = Vector2(preview_scale.x, preview_scale.x) + else: + # Image width will hit the preview boundary before the height will + get_node(BACKGROUND_PREVIEW).rect_scale = Vector2(preview_scale.y, preview_scale.y) + + +func _on_ClearButton_pressed() -> void: + if settings_modified: + $InformationWindows/ClearConfirmationDialog.popup_centered() + + +func _on_MainMenuButton_pressed() -> void: + if settings_modified: + $InformationWindows/MainMenuConfirmationDialog.popup_centered() + else: + get_node("../Menu").visible = true + get_node("../RoomCreator").visible = false + + +func _on_ClearConfirmationDialog_confirmed() -> void: + room_creator_reset() + + +func _on_MainMenuConfirmationDialog_confirmed() -> void: + get_node("../Menu").visible = true + get_node("../RoomCreator").visible = false + + +func _on_ChangeRoomFolderButton_pressed() -> void: + $"InformationWindows/RoomFolderDialog".popup_centered() + + +func _on_RoomFolderDialog_dir_selected(dir: String) -> void: + ProjectSettings.set_setting("escoria/debug/room_selector_room_dir", dir) + get_node(ROOM_FOLDER_PATH).text = dir + + +func _on_CreateButton_pressed() -> void: + var RoomName = get_node(ROOM_NAME).text + + if RoomName.length() < 1: + $"InformationWindows/GenericErrorDialog".dialog_text = "Error!\n\nRoom name must be specified." + $"InformationWindows/GenericErrorDialog".popup_centered() + return + + var ScriptName = get_node(ESC_SCRIPT).text + + if get_node(USE_EMPTY_ROOM_SCRIPT).pressed == false: + if ScriptName.length() < 5 or ! ScriptName.substr(ScriptName.length() - 4) == ".esc": + $"InformationWindows/GenericErrorDialog".dialog_text = "Error!\n\n" \ + + "Room ESC script must be a filename ending in '.esc'" + $"InformationWindows/GenericErrorDialog".popup_centered() + return + + if "/" in get_node(ESC_SCRIPT).text: + $"InformationWindows/GenericErrorDialog".dialog_text = "Error!\n\n" \ + + "Please remove any '/' characters from the name of the Room ESC script." + $"InformationWindows/GenericErrorDialog".popup_centered() + return + + var BaseDir = ProjectSettings.get_setting("escoria/debug/room_selector_room_dir") + var ImageSize = Vector2(1,1) + var NewRoom = ESCRoom.new() + + NewRoom.name = RoomName + NewRoom.global_id = get_node(GLOBAL_ID).text + + if ! get_node(ESC_SCRIPT).text == SCRIPT_SELECT_TEXT and ! get_node(ESC_SCRIPT).text == SCRIPT_BLANK_TEXT: + NewRoom.esc_script = "%s/%s/scripts/%s" % [BaseDir, RoomName, get_node(ESC_SCRIPT).text] + + if ! get_node(PLAYER_SCENE).text == PLAYER_SELECT_TEXT and ! get_node(PLAYER_SCENE).text == PLAYER_BLANK_TEXT: + var player_scene = load(get_node(PLAYER_SCENE).text) + NewRoom.player_scene = player_scene + + var Background = ESCBackground.new() + Background.name = "Background" + + var BackgroundSize = Vector2.ONE + + if ! get_node(BACKGROUND_IMAGE).text == BACKGROUND_SELECT_TEXT and ! get_node(BACKGROUND_IMAGE).text == BACKGROUND_BLANK_TEXT: + Background.texture = get_node(BACKGROUND_PREVIEW).texture + BackgroundSize = Background.texture.get_size() + else: + # Set TextureRect to have the same size as the Viewport so that the room + # works even if no texture is set in the TextureRect + BackgroundSize = Vector2(ProjectSettings.get_setting("display/window/size/width"), \ + ProjectSettings.get_setting("display/window/size/height")) + Background.rect_size = BackgroundSize + + NewRoom.add_child(Background) + + var NewTerrain = ESCTerrain.new() + NewTerrain.name = "WalkableArea" + var NewNavigationPolygonInstance = NavigationPolygonInstance.new() + + var NewNavigationPolygon = NavigationPolygon.new() + NewNavigationPolygonInstance.navpoly = NewNavigationPolygon + + NewRoom.add_child(NewTerrain) + + NewTerrain.add_child(NewNavigationPolygonInstance) + + var Objects = Node2D.new() + Objects.name = "RoomObjects" + NewRoom.add_child(Objects) + + var StartPos = ESCLocation.new() + StartPos.name = "StartPos" + StartPos.is_start_location = true + StartPos.global_id = "%s_start_pos" % RoomName + StartPos.position = Vector2(int(BackgroundSize.x / 2), int(BackgroundSize.y / 2)) + NewRoom.add_child(StartPos) + + get_tree().edited_scene_root.add_child(NewRoom) + NewRoom.set_owner(get_tree().edited_scene_root) + NewNavigationPolygonInstance.set_owner(NewRoom) + NewTerrain.set_owner(NewRoom) + Background.set_owner(NewRoom) + Objects.set_owner(NewRoom) + StartPos.set_owner(NewRoom) + + var dir = Directory.new() + dir.make_dir_recursive("%s/%s/scripts" % [BaseDir, RoomName]) + dir.make_dir_recursive("%s/%s/objects" % [BaseDir, RoomName]) + dir.copy("res://addons/escoria-wizard/room_script_template.esc", "%s/%s/scripts/%s" % \ + [BaseDir, RoomName, get_node(ESC_SCRIPT).text]) + + # Export scene + var packed_scene = PackedScene.new() + packed_scene.pack(get_tree().edited_scene_root.get_node(NewRoom.name)) + + # Flag suggestions from https://godotengine.org/qa/50437/how-to-turn-a-node-into-a-packedscene-via-gdscript + ResourceSaver.save("%s/%s/%s.tscn" % [BaseDir, RoomName, RoomName], \ + packed_scene, ResourceSaver.FLAG_CHANGE_PATH|ResourceSaver.FLAG_REPLACE_SUBRESOURCE_PATHS) + + NewRoom.queue_free() + get_tree().edited_scene_root.get_node(NewRoom.name).queue_free() + # Scan the filesystem so that the new folders show up in the file browser. + # Without this you might not see the objects/scripts folders in the filetree. + var ep = EditorPlugin.new() + ep.get_editor_interface().get_resource_filesystem().scan() + ep.free() + + $InformationWindows/CreateCompleteDialog.popup_centered() diff --git a/addons/escoria-wizard/RoomCreator.tscn b/addons/escoria-wizard/RoomCreator.tscn new file mode 100644 index 00000000..48433a06 --- /dev/null +++ b/addons/escoria-wizard/RoomCreator.tscn @@ -0,0 +1,431 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://addons/escoria-wizard/RoomCreator.gd" type="Script" id=1] +[ext_resource path="res://addons/escoria-wizard/graphics/background_preview.png" type="Texture" id=2] + +[node name="CenterContainer" type="CenterContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_clip_content = true +script = ExtResource( 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="."] +margin_left = 135.0 +margin_top = 73.0 +margin_right = 1145.0 +margin_bottom = 827.0 + +[node name="ColorRect" type="ColorRect" parent="MarginContainer"] +margin_right = 1010.0 +margin_bottom = 754.0 +color = Color( 0.235294, 0.341176, 0.290196, 1 ) + +[node name="MarginContainer" type="MarginContainer" parent="MarginContainer"] +margin_right = 1010.0 +margin_bottom = 754.0 +custom_constants/margin_right = 5 +custom_constants/margin_top = 5 +custom_constants/margin_left = 5 +custom_constants/margin_bottom = 5 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/MarginContainer"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 1005.0 +margin_bottom = 749.0 + +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/MarginContainer/VBoxContainer"] +margin_right = 1000.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 0, 40 ) + +[node name="Label" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/CenterContainer"] +margin_left = 448.0 +margin_top = 13.0 +margin_right = 552.0 +margin_bottom = 27.0 +custom_colors/font_color = Color( 0.921569, 1, 0, 1 ) +custom_colors/font_color_shadow = Color( 0, 0, 0, 1 ) +text = "Room Creator" +uppercase = true + +[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/MarginContainer/VBoxContainer"] +margin_top = 44.0 +margin_right = 1000.0 +margin_bottom = 256.0 +rect_min_size = Vector2( 460, 200 ) + +[node name="GridContainer" type="GridContainer" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer"] +margin_right = 1000.0 +margin_bottom = 212.0 +rect_min_size = Vector2( 300, 200 ) +custom_constants/hseparation = 10 +columns = 4 + +[node name="RoomNameLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 5.0 +margin_right = 127.0 +margin_bottom = 19.0 +text = "Room name:" + +[node name="RoomName" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_right = 537.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 400, 0 ) +caret_blink = true +caret_blink_speed = 0.5 + +[node name="Spacer3" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_right = 782.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="Spacer6" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_right = 992.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 200, 0 ) + +[node name="GlobalIDLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 33.0 +margin_right = 127.0 +margin_bottom = 47.0 +text = "Global ID:" + +[node name="GlobalID" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_top = 28.0 +margin_right = 537.0 +margin_bottom = 52.0 +caret_blink = true +caret_blink_speed = 0.5 + +[node name="Spacer4" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_top = 28.0 +margin_right = 782.0 +margin_bottom = 52.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="Spacer7" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_top = 28.0 +margin_right = 992.0 +margin_bottom = 52.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="PlayerSceneLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 69.0 +margin_right = 127.0 +margin_bottom = 83.0 +text = "Player scene:" + +[node name="PlayerScene" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_top = 56.0 +margin_right = 537.0 +margin_bottom = 96.0 +text = "Scene will be left blank." +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="UseEmptyPlayerButton" type="CheckButton" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_top = 56.0 +margin_right = 782.0 +margin_bottom = 96.0 +pressed = true +text = "Use empty player scene" + +[node name="SelectPlayerScene" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +visible = false +margin_left = 578.0 +margin_top = 56.0 +margin_right = 808.0 +margin_bottom = 96.0 +text = "Select Player Scene" + +[node name="SelectPlayerSceneSpacer" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_top = 56.0 +margin_right = 992.0 +margin_bottom = 96.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="ESCScriptLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 113.0 +margin_right = 127.0 +margin_bottom = 127.0 +text = "Room ESC script:" + +[node name="ESCScript" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_top = 100.0 +margin_right = 537.0 +margin_bottom = 140.0 +hint_tooltip = "In the room's scripts folder +an empty file will be created +with this name." +text = "Room will not have a script configured." +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="UseEmptyRoomScript" type="CheckButton" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_top = 100.0 +margin_right = 782.0 +margin_bottom = 140.0 +pressed = true +text = "No script" + +[node name="UseEmptyRoomSpacer" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_top = 100.0 +margin_right = 992.0 +margin_bottom = 140.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="BackgroundImageLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 157.0 +margin_right = 127.0 +margin_bottom = 171.0 +text = "Background image:" + +[node name="BackgroundImage" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_top = 144.0 +margin_right = 537.0 +margin_bottom = 184.0 +text = "Image will be left blank." +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="UseEmptyBackground" type="CheckButton" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_top = 144.0 +margin_right = 782.0 +margin_bottom = 184.0 +pressed = true +text = "Use empty background" + +[node name="SelectBackground" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +visible = false +margin_left = 564.0 +margin_top = 144.0 +margin_right = 693.0 +margin_bottom = 184.0 +text = "Select Background" + +[node name="SelectBackgroundSpacer" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_top = 144.0 +margin_right = 992.0 +margin_bottom = 184.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="RoomFolderLabel" type="Label" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_top = 193.0 +margin_right = 127.0 +margin_bottom = 207.0 +text = "Room folder parent:" + +[node name="RoomFolder" type="LineEdit" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 137.0 +margin_top = 188.0 +margin_right = 537.0 +margin_bottom = 212.0 +hint_tooltip = "A folder () for your room will be created inside this parent folder." +text = "res://game/rooms" +editable = false +caret_blink = true +caret_blink_speed = 0.5 + +[node name="ChangeRoomFolderButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 547.0 +margin_top = 188.0 +margin_right = 782.0 +margin_bottom = 212.0 +text = "Change Room Folder" + +[node name="Spacer8" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer"] +margin_left = 792.0 +margin_top = 188.0 +margin_right = 992.0 +margin_bottom = 212.0 +rect_min_size = Vector2( 40, 0 ) + +[node name="PreviewSection" type="Control" parent="MarginContainer/MarginContainer/VBoxContainer"] +margin_top = 260.0 +margin_right = 1000.0 +margin_bottom = 660.0 +rect_min_size = Vector2( 1000, 400 ) + +[node name="PreviewFrame" type="ColorRect" parent="MarginContainer/MarginContainer/VBoxContainer/PreviewSection"] +margin_right = 1000.0 +margin_bottom = 400.0 +rect_min_size = Vector2( 1000, 400 ) +color = Color( 0, 0, 0, 1 ) + +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/MarginContainer/VBoxContainer/PreviewSection"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 995.0 +margin_bottom = 395.0 + +[node name="RoomBackground" type="TextureRect" parent="MarginContainer/MarginContainer/VBoxContainer/PreviewSection/CenterContainer"] +margin_right = 990.0 +margin_bottom = 390.0 +rect_min_size = Vector2( 990, 390 ) +texture = ExtResource( 2 ) + +[node name="BackgroundPreview" type="TextureRect" parent="MarginContainer/MarginContainer/VBoxContainer/PreviewSection"] +margin_left = 5.0 +margin_top = 5.0 +margin_right = 5.0 +margin_bottom = 5.0 + +[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/MarginContainer/VBoxContainer"] +margin_top = 664.0 +margin_right = 1000.0 +margin_bottom = 744.0 +rect_min_size = Vector2( 0, 80 ) + +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2"] +margin_right = 1000.0 +margin_bottom = 80.0 +rect_min_size = Vector2( 800, 80 ) + +[node name="GridContainer" type="GridContainer" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer"] +margin_left = 349.0 +margin_top = 20.0 +margin_right = 650.0 +margin_bottom = 60.0 +rect_min_size = Vector2( 300, 40 ) +custom_constants/hseparation = 40 +columns = 3 + +[node name="CreateButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer"] +margin_right = 94.0 +margin_bottom = 20.0 +text = "Create Room" + +[node name="ClearButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer"] +margin_left = 134.0 +margin_right = 178.0 +margin_bottom = 20.0 +text = "Clear" + +[node name="MainMenuButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer"] +margin_left = 218.0 +margin_right = 301.0 +margin_bottom = 20.0 +text = "Main Menu" + +[node name="InformationWindows" type="Control" parent="."] +margin_left = 640.0 +margin_top = 450.0 +margin_right = 640.0 +margin_bottom = 450.0 + +[node name="PlayerSceneFileDialog" type="FileDialog" parent="InformationWindows"] +margin_left = 1400.0 +margin_top = 1400.0 +margin_right = 2000.0 +margin_bottom = 2000.0 +rect_min_size = Vector2( 600, 600 ) +popup_exclusive = true +window_title = "Open a File" +mode = 0 +filters = PoolStringArray( "*.tscn, *.scn ; Scene Files" ) +__meta__ = { +"_editor_description_": "" +} + +[node name="ESCScriptFileDialog" type="FileDialog" parent="InformationWindows"] +margin_left = 172.0 +margin_top = -206.0 +margin_right = 772.0 +margin_bottom = 394.0 +rect_min_size = Vector2( 600, 600 ) +popup_exclusive = true +window_title = "Open a File" +mode = 0 +filters = PoolStringArray( "*.esc; Escoria script files" ) +__meta__ = { +"_editor_description_": "" +} + +[node name="BackgroundImageFileDialog" type="FileDialog" parent="InformationWindows"] +margin_left = 1400.0 +margin_top = 1400.0 +margin_right = 2000.0 +margin_bottom = 2000.0 +rect_min_size = Vector2( 600, 600 ) +popup_exclusive = true +window_title = "Open a File" +mode = 0 +filters = PoolStringArray( "*.png, *.jpg, *.jpeg ; Supported Images" ) + +[node name="ClearConfirmationDialog" type="ConfirmationDialog" parent="InformationWindows"] +margin_right = 353.0 +margin_bottom = 92.0 +popup_exclusive = true +dialog_text = "WARNING! + +If you continue you will lose the current room setup." + +[node name="MainMenuConfirmationDialog" type="ConfirmationDialog" parent="InformationWindows"] +margin_right = 353.0 +margin_bottom = 92.0 +popup_exclusive = true +dialog_text = "WARNING! + +If you continue you will lose the current room setup." + +[node name="GenericErrorDialog" type="AcceptDialog" parent="InformationWindows"] +margin_right = 83.0 +margin_bottom = 58.0 +popup_exclusive = true +dialog_text = "ERROR! + +Please supply a name for the room." + +[node name="CreateCompleteDialog" type="AcceptDialog" parent="InformationWindows"] +margin_right = 83.0 +margin_bottom = 58.0 +popup_exclusive = true +window_title = "Export Complete" +dialog_text = "The room has been created." + +[node name="RoomFolderDialog" type="FileDialog" parent="InformationWindows"] +margin_left = -279.0 +margin_top = -343.0 +margin_right = 321.0 +margin_bottom = 257.0 +rect_min_size = Vector2( 600, 600 ) +popup_exclusive = true +window_title = "Open a Directory" +mode = 2 + +[connection signal="text_changed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/RoomName" to="." method="_on_RoomName_text_changed"] +[connection signal="text_changed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/GlobalID" to="." method="_on_GlobalID_text_changed"] +[connection signal="toggled" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyPlayerButton" to="." method="_on_UseEmptyPlayerButton_toggled"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectPlayerScene" to="." method="_on_SelectPlayerScene_pressed"] +[connection signal="toggled" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyRoomScript" to="." method="_on_UseEmptyRoomScript_toggled"] +[connection signal="toggled" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/UseEmptyBackground" to="." method="_on_UseEmptyBackground_toggled"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/SelectBackground" to="." method="_on_SelectBackground_pressed"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer/GridContainer/ChangeRoomFolderButton" to="." method="_on_ChangeRoomFolderButton_pressed"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer/CreateButton" to="." method="_on_CreateButton_pressed"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer/ClearButton" to="." method="_on_ClearButton_pressed"] +[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/MarginContainer2/CenterContainer/GridContainer/MainMenuButton" to="." method="_on_MainMenuButton_pressed"] +[connection signal="file_selected" from="InformationWindows/PlayerSceneFileDialog" to="." method="_on_PlayerSceneFileDialog_file_selected"] +[connection signal="file_selected" from="InformationWindows/ESCScriptFileDialog" to="." method="_on_ESCScriptFileDialog_file_selected"] +[connection signal="file_selected" from="InformationWindows/BackgroundImageFileDialog" to="." method="_on_BackgroundImageFileDialog_file_selected"] +[connection signal="confirmed" from="InformationWindows/ClearConfirmationDialog" to="." method="_on_ClearConfirmationDialog_confirmed"] +[connection signal="confirmed" from="InformationWindows/MainMenuConfirmationDialog" to="." method="_on_MainMenuConfirmationDialog_confirmed"] +[connection signal="dir_selected" from="InformationWindows/RoomFolderDialog" to="." method="_on_RoomFolderDialog_dir_selected"] diff --git a/addons/escoria-wizard/background.pdn b/addons/escoria-wizard/background.pdn new file mode 100644 index 00000000..9362b68d Binary files /dev/null and b/addons/escoria-wizard/background.pdn differ diff --git a/addons/escoria-wizard/draw_frame_rects.gd b/addons/escoria-wizard/draw_frame_rects.gd new file mode 100644 index 00000000..c1a6e7eb --- /dev/null +++ b/addons/escoria-wizard/draw_frame_rects.gd @@ -0,0 +1,44 @@ +tool +extends Control + +const grid_colour = Color.brown +const highlight_colour = Color.gold #fuchsia + +# Number of rows to break the spritesheet into +export var total_num_rows:int +# Number of columns to break the spritesheet into +export var total_num_columns:int +# First animation cell. Boxes will be drawn around every cell from the start_cell to end_cell. +export var start_cell:int +# Last animation cell. Boxes will be drawn around every cell from the start_cell to end_cell. +export var end_cell:int +# The size of each animation cell in pixels. +export var cell_size:Vector2 +# Zoom factor +export var zoom_factor:float + +# This function will calculate where on the spritesheet the start and end frames for an animation +# are, and draw boxes around all used frames. The visual indicator makes frame selection easier. +func _draw() -> void: + if start_cell > 0: + # Draw grid for all frames in the spritesheet + for yloop in range(total_num_rows): + for xloop in range(total_num_columns): + var corner1 = Vector2(xloop * cell_size.x, yloop * cell_size.y) + var corner2 = Vector2(corner1.x + cell_size.x, corner1.y + cell_size.y) + draw_line(Vector2(corner1.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner1.y * zoom_factor), grid_colour, 2.0, false) + draw_line(Vector2(corner1.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner1.x * zoom_factor, corner2.y * zoom_factor), grid_colour, 2.0, false) + draw_line(Vector2(corner1.x * zoom_factor, corner2.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner2.y * zoom_factor), grid_colour, 2.0, false) + draw_line(Vector2(corner2.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner2.y * zoom_factor), grid_colour, 2.0, false) + + # Highlight selected frames in the spritesheet + for loop in range(end_cell - start_cell + 1): + var current_cell = start_cell + loop + var frame_row = (current_cell - 1) / total_num_columns + var frame_column = (current_cell - 1) % total_num_columns + var corner1 = Vector2(frame_column * cell_size.x, frame_row * cell_size.y) + var corner2 = Vector2(corner1.x + cell_size.x, corner1.y + cell_size.y) + draw_line(Vector2(corner1.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner1.y * zoom_factor), highlight_colour, 2.0, false) + draw_line(Vector2(corner1.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner1.x * zoom_factor, corner2.y * zoom_factor), highlight_colour, false) + draw_line(Vector2(corner1.x * zoom_factor, corner2.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner2.y * zoom_factor), highlight_colour, 2.0, false) + draw_line(Vector2(corner2.x * zoom_factor, corner1.y * zoom_factor), Vector2(corner2.x * zoom_factor, corner2.y * zoom_factor), highlight_colour, 2.0, false) diff --git a/addons/escoria-wizard/escoria_wizard.gd b/addons/escoria-wizard/escoria_wizard.gd new file mode 100644 index 00000000..bb4b26b3 --- /dev/null +++ b/addons/escoria-wizard/escoria_wizard.gd @@ -0,0 +1,45 @@ +tool +extends Control + + +const GENERIC_ERROR_NODE = "Menu/InformationWindows/generic_error_window" + + +# This variable is set by plugin.gd and used to allow the plugin to interact with the Godot +# editor (open the ESCPlayer scene in the editor once it's created) +var plugin_reference + + +func _ready() -> void: + for section_loop in ["RoomCreator", "CharacterCreator", "ItemCreator"]: + get_node(section_loop).visible = false + + $Menu.visible = true + + +func NewGame_pressed() -> void: + pass # Replace with function body. + + +func NewRoom_pressed() -> void: + $Menu.visible = false + $RoomCreator.visible = true + $RoomCreator.room_creator_reset() + + +func CharacterCreator_pressed() -> void: + $Menu.visible = false + $CharacterCreator.visible = true + + if plugin_reference == null: + get_node(GENERIC_ERROR_NODE).dialog_text = "Warning!\n\nExporting your character will fail when\n" + get_node(GENERIC_ERROR_NODE).dialog_text += "running the character creator directly rather than\n" + get_node(GENERIC_ERROR_NODE).dialog_text += "as a plugin.\n\nPlease open this as a plugin." + get_node(GENERIC_ERROR_NODE).popup() + + +func InventoryItem_pressed() -> void: + $Menu.visible = false + $ItemCreator.visible = true + $ItemCreator.inventory_mode = false + $ItemCreator.item_creator_reset() diff --git a/addons/escoria-wizard/escoria_wizard.tscn b/addons/escoria-wizard/escoria_wizard.tscn new file mode 100644 index 00000000..8cca161c --- /dev/null +++ b/addons/escoria-wizard/escoria_wizard.tscn @@ -0,0 +1,101 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://addons/escoria-wizard/graphics/background.png" type="Texture" id=1] +[ext_resource path="res://addons/escoria-wizard/CharacterCreator.tscn" type="PackedScene" id=2] +[ext_resource path="res://addons/escoria-wizard/ItemCreator.tscn" type="PackedScene" id=3] +[ext_resource path="res://addons/escoria-wizard/RoomCreator.tscn" type="PackedScene" id=4] +[ext_resource path="res://addons/escoria-wizard/escoria_wizard.gd" type="Script" id=38] +[ext_resource path="res://addons/escoria-wizard/graphics/character.png" type="Texture" id=40] +[ext_resource path="res://addons/escoria-wizard/graphics/room.png" type="Texture" id=42] +[ext_resource path="res://addons/escoria-wizard/graphics/inventory.png" type="Texture" id=44] + +[node name="root" type="MarginContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = 10.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource( 38 ) + +[node name="background" type="TextureRect" parent="."] +margin_right = 1290.0 +margin_bottom = 900.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +texture = ExtResource( 1 ) +expand = true +stretch_mode = 2 + +[node name="Menu" type="MarginContainer" parent="."] +margin_right = 1290.0 +margin_bottom = 900.0 + +[node name="CenterContainer" type="CenterContainer" parent="Menu"] +margin_right = 1290.0 +margin_bottom = 900.0 + +[node name="GridContainer" type="GridContainer" parent="Menu/CenterContainer"] +margin_left = 549.0 +margin_top = 325.0 +margin_right = 740.0 +margin_bottom = 575.0 +custom_constants/vseparation = 20 + +[node name="NewRoom" type="Button" parent="Menu/CenterContainer/GridContainer"] +margin_right = 191.0 +margin_bottom = 70.0 +text = "Room Creator" +icon = ExtResource( 42 ) + +[node name="CharacterCreator" type="Button" parent="Menu/CenterContainer/GridContainer"] +margin_top = 90.0 +margin_right = 191.0 +margin_bottom = 160.0 +custom_constants/hseparation = 5 +text = "Character Creator" +icon = ExtResource( 40 ) + +[node name="InventoryItem" type="Button" parent="Menu/CenterContainer/GridContainer"] +margin_top = 180.0 +margin_right = 191.0 +margin_bottom = 250.0 +custom_constants/hseparation = 5 +text = "Item Creator" +icon = ExtResource( 44 ) + +[node name="InformationWindows" type="Control" parent="Menu"] +visible = false +margin_right = 1290.0 +margin_bottom = 900.0 + +[node name="generic_error_window" type="AcceptDialog" parent="Menu/InformationWindows"] +margin_left = 519.0 +margin_top = 234.0 +margin_right = 846.0 +margin_bottom = 394.0 +input_pass_on_modal_close_click = false +popup_exclusive = true +dialog_text = "Warning! + +Exporting your character will fail when +running the character creator directly rather than +as a plugin. + +Please open this as a plugin." + +[node name="RoomCreator" parent="." instance=ExtResource( 4 )] +visible = false +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 1290.0 +margin_bottom = 900.0 + +[node name="CharacterCreator" parent="." instance=ExtResource( 2 )] +visible = false + +[node name="ItemCreator" parent="." instance=ExtResource( 3 )] +visible = false + +[connection signal="pressed" from="Menu/CenterContainer/GridContainer/NewRoom" to="." method="NewRoom_pressed"] +[connection signal="pressed" from="Menu/CenterContainer/GridContainer/CharacterCreator" to="." method="CharacterCreator_pressed"] +[connection signal="pressed" from="Menu/CenterContainer/GridContainer/InventoryItem" to="." method="InventoryItem_pressed"] diff --git a/addons/escoria-wizard/graphics/background.png b/addons/escoria-wizard/graphics/background.png new file mode 100644 index 00000000..94f6f929 Binary files /dev/null and b/addons/escoria-wizard/graphics/background.png differ diff --git a/addons/escoria-wizard/graphics/background_preview.png b/addons/escoria-wizard/graphics/background_preview.png new file mode 100644 index 00000000..8ba42429 Binary files /dev/null and b/addons/escoria-wizard/graphics/background_preview.png differ diff --git a/addons/escoria-wizard/graphics/character.png b/addons/escoria-wizard/graphics/character.png new file mode 100644 index 00000000..11b09717 Binary files /dev/null and b/addons/escoria-wizard/graphics/character.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_down.png b/addons/escoria-wizard/graphics/darkgreenarrow_down.png new file mode 100644 index 00000000..7c107403 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_down.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_downleft.png b/addons/escoria-wizard/graphics/darkgreenarrow_downleft.png new file mode 100644 index 00000000..df369b68 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_downleft.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_downright.png b/addons/escoria-wizard/graphics/darkgreenarrow_downright.png new file mode 100644 index 00000000..bf24e3d9 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_downright.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_left.png b/addons/escoria-wizard/graphics/darkgreenarrow_left.png new file mode 100644 index 00000000..8ab0141b Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_left.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_right.png b/addons/escoria-wizard/graphics/darkgreenarrow_right.png new file mode 100644 index 00000000..7716a287 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_right.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_up.png b/addons/escoria-wizard/graphics/darkgreenarrow_up.png new file mode 100644 index 00000000..c4637e81 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_up.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_upleft.png b/addons/escoria-wizard/graphics/darkgreenarrow_upleft.png new file mode 100644 index 00000000..072f8ee4 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_upleft.png differ diff --git a/addons/escoria-wizard/graphics/darkgreenarrow_upright.png b/addons/escoria-wizard/graphics/darkgreenarrow_upright.png new file mode 100644 index 00000000..f36a441f Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreenarrow_upright.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_d.png b/addons/escoria-wizard/graphics/darkgreyarrow_d.png new file mode 100644 index 00000000..756fb2d0 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_d.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_dl.png b/addons/escoria-wizard/graphics/darkgreyarrow_dl.png new file mode 100644 index 00000000..66bfea0e Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_dl.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_dr.png b/addons/escoria-wizard/graphics/darkgreyarrow_dr.png new file mode 100644 index 00000000..d8174c49 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_dr.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_l.png b/addons/escoria-wizard/graphics/darkgreyarrow_l.png new file mode 100644 index 00000000..42e28e54 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_l.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_r.png b/addons/escoria-wizard/graphics/darkgreyarrow_r.png new file mode 100644 index 00000000..9ef00364 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_r.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_u.png b/addons/escoria-wizard/graphics/darkgreyarrow_u.png new file mode 100644 index 00000000..e0e85fc8 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_u.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_ul.png b/addons/escoria-wizard/graphics/darkgreyarrow_ul.png new file mode 100644 index 00000000..1331b463 Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_ul.png differ diff --git a/addons/escoria-wizard/graphics/darkgreyarrow_ur.png b/addons/escoria-wizard/graphics/darkgreyarrow_ur.png new file mode 100644 index 00000000..0b0ef7af Binary files /dev/null and b/addons/escoria-wizard/graphics/darkgreyarrow_ur.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_down.png b/addons/escoria-wizard/graphics/greenarrow_down.png new file mode 100644 index 00000000..5610a96b Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_down.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_downleft.png b/addons/escoria-wizard/graphics/greenarrow_downleft.png new file mode 100644 index 00000000..248f29fe Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_downleft.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_downright.png b/addons/escoria-wizard/graphics/greenarrow_downright.png new file mode 100644 index 00000000..a84d0b6b Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_downright.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_left.png b/addons/escoria-wizard/graphics/greenarrow_left.png new file mode 100644 index 00000000..dfba2e9b Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_left.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_right.png b/addons/escoria-wizard/graphics/greenarrow_right.png new file mode 100644 index 00000000..80827ac1 Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_right.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_up.png b/addons/escoria-wizard/graphics/greenarrow_up.png new file mode 100644 index 00000000..6d94311d Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_up.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_upleft.png b/addons/escoria-wizard/graphics/greenarrow_upleft.png new file mode 100644 index 00000000..81e505fc Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_upleft.png differ diff --git a/addons/escoria-wizard/graphics/greenarrow_upright.png b/addons/escoria-wizard/graphics/greenarrow_upright.png new file mode 100644 index 00000000..d65c24b0 Binary files /dev/null and b/addons/escoria-wizard/graphics/greenarrow_upright.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_d.png b/addons/escoria-wizard/graphics/greyarrow_d.png new file mode 100644 index 00000000..08d46e9d Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_d.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_dl.png b/addons/escoria-wizard/graphics/greyarrow_dl.png new file mode 100644 index 00000000..7653aef4 Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_dl.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_dr.png b/addons/escoria-wizard/graphics/greyarrow_dr.png new file mode 100644 index 00000000..0eebaa88 Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_dr.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_l.png b/addons/escoria-wizard/graphics/greyarrow_l.png new file mode 100644 index 00000000..bdb58ad7 Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_l.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_r.png b/addons/escoria-wizard/graphics/greyarrow_r.png new file mode 100644 index 00000000..1e9895d1 Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_r.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_u.png b/addons/escoria-wizard/graphics/greyarrow_u.png new file mode 100644 index 00000000..06d3194f Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_u.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_ul.png b/addons/escoria-wizard/graphics/greyarrow_ul.png new file mode 100644 index 00000000..f839c4b4 Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_ul.png differ diff --git a/addons/escoria-wizard/graphics/greyarrow_ur.png b/addons/escoria-wizard/graphics/greyarrow_ur.png new file mode 100644 index 00000000..884afafc Binary files /dev/null and b/addons/escoria-wizard/graphics/greyarrow_ur.png differ diff --git a/addons/escoria-wizard/graphics/help/help_background.png b/addons/escoria-wizard/graphics/help/help_background.png new file mode 100644 index 00000000..b7cf95d9 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/help_background.png differ diff --git a/addons/escoria-wizard/graphics/help/left1.png b/addons/escoria-wizard/graphics/help/left1.png new file mode 100644 index 00000000..6b6ffb6e Binary files /dev/null and b/addons/escoria-wizard/graphics/help/left1.png differ diff --git a/addons/escoria-wizard/graphics/help/left2.png b/addons/escoria-wizard/graphics/help/left2.png new file mode 100644 index 00000000..46173cb9 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/left2.png differ diff --git a/addons/escoria-wizard/graphics/help/left3.png b/addons/escoria-wizard/graphics/help/left3.png new file mode 100644 index 00000000..7d37685b Binary files /dev/null and b/addons/escoria-wizard/graphics/help/left3.png differ diff --git a/addons/escoria-wizard/graphics/help/left4.png b/addons/escoria-wizard/graphics/help/left4.png new file mode 100644 index 00000000..f4e8aa84 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/left4.png differ diff --git a/addons/escoria-wizard/graphics/help/left5.png b/addons/escoria-wizard/graphics/help/left5.png new file mode 100644 index 00000000..bd5b50a6 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/left5.png differ diff --git a/addons/escoria-wizard/graphics/help/leftall.png b/addons/escoria-wizard/graphics/help/leftall.png new file mode 100644 index 00000000..d8f2c7ed Binary files /dev/null and b/addons/escoria-wizard/graphics/help/leftall.png differ diff --git a/addons/escoria-wizard/graphics/help/middle1.png b/addons/escoria-wizard/graphics/help/middle1.png new file mode 100644 index 00000000..c83e0beb Binary files /dev/null and b/addons/escoria-wizard/graphics/help/middle1.png differ diff --git a/addons/escoria-wizard/graphics/help/middle2.png b/addons/escoria-wizard/graphics/help/middle2.png new file mode 100644 index 00000000..8f5ceb5b Binary files /dev/null and b/addons/escoria-wizard/graphics/help/middle2.png differ diff --git a/addons/escoria-wizard/graphics/help/middle3.png b/addons/escoria-wizard/graphics/help/middle3.png new file mode 100644 index 00000000..59208271 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/middle3.png differ diff --git a/addons/escoria-wizard/graphics/help/middleall.png b/addons/escoria-wizard/graphics/help/middleall.png new file mode 100644 index 00000000..fd516b63 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/middleall.png differ diff --git a/addons/escoria-wizard/graphics/help/right1.png b/addons/escoria-wizard/graphics/help/right1.png new file mode 100644 index 00000000..06252661 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/right1.png differ diff --git a/addons/escoria-wizard/graphics/help/right2.png b/addons/escoria-wizard/graphics/help/right2.png new file mode 100644 index 00000000..a4f37775 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/right2.png differ diff --git a/addons/escoria-wizard/graphics/help/right3.png b/addons/escoria-wizard/graphics/help/right3.png new file mode 100644 index 00000000..65b769bb Binary files /dev/null and b/addons/escoria-wizard/graphics/help/right3.png differ diff --git a/addons/escoria-wizard/graphics/help/right4.png b/addons/escoria-wizard/graphics/help/right4.png new file mode 100644 index 00000000..fffc948f Binary files /dev/null and b/addons/escoria-wizard/graphics/help/right4.png differ diff --git a/addons/escoria-wizard/graphics/help/right5.png b/addons/escoria-wizard/graphics/help/right5.png new file mode 100644 index 00000000..0888c9dd Binary files /dev/null and b/addons/escoria-wizard/graphics/help/right5.png differ diff --git a/addons/escoria-wizard/graphics/help/rightall.png b/addons/escoria-wizard/graphics/help/rightall.png new file mode 100644 index 00000000..0873e138 Binary files /dev/null and b/addons/escoria-wizard/graphics/help/rightall.png differ diff --git a/addons/escoria-wizard/graphics/icon.png b/addons/escoria-wizard/graphics/icon.png new file mode 100644 index 00000000..712b0060 Binary files /dev/null and b/addons/escoria-wizard/graphics/icon.png differ diff --git a/addons/escoria-wizard/graphics/icon16x16.png b/addons/escoria-wizard/graphics/icon16x16.png new file mode 100644 index 00000000..8c4191b1 Binary files /dev/null and b/addons/escoria-wizard/graphics/icon16x16.png differ diff --git a/addons/escoria-wizard/graphics/inventory.png b/addons/escoria-wizard/graphics/inventory.png new file mode 100644 index 00000000..52a6475c Binary files /dev/null and b/addons/escoria-wizard/graphics/inventory.png differ diff --git a/addons/escoria-wizard/graphics/inventory_preview.png b/addons/escoria-wizard/graphics/inventory_preview.png new file mode 100644 index 00000000..b22db898 Binary files /dev/null and b/addons/escoria-wizard/graphics/inventory_preview.png differ diff --git a/addons/escoria-wizard/graphics/mark-animtest.png b/addons/escoria-wizard/graphics/mark-animtest.png new file mode 100644 index 00000000..1f64e034 Binary files /dev/null and b/addons/escoria-wizard/graphics/mark-animtest.png differ diff --git a/addons/escoria-wizard/graphics/no_animation.png b/addons/escoria-wizard/graphics/no_animation.png new file mode 100644 index 00000000..5408dca9 Binary files /dev/null and b/addons/escoria-wizard/graphics/no_animation.png differ diff --git a/addons/escoria-wizard/graphics/no_spritesheet.png b/addons/escoria-wizard/graphics/no_spritesheet.png new file mode 100644 index 00000000..4fe2c70f Binary files /dev/null and b/addons/escoria-wizard/graphics/no_spritesheet.png differ diff --git a/addons/escoria-wizard/graphics/object_preview.png b/addons/escoria-wizard/graphics/object_preview.png new file mode 100644 index 00000000..14c1e3b2 Binary files /dev/null and b/addons/escoria-wizard/graphics/object_preview.png differ diff --git a/addons/escoria-wizard/graphics/robot/idle_all.png b/addons/escoria-wizard/graphics/robot/idle_all.png new file mode 100644 index 00000000..da6757a4 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/idle_all.png differ diff --git a/addons/escoria-wizard/graphics/robot/open_all.png b/addons/escoria-wizard/graphics/robot/open_all.png new file mode 100644 index 00000000..21750b46 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/open_all.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_down.png b/addons/escoria-wizard/graphics/robot/talk_down.png new file mode 100644 index 00000000..132570fa Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_down.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_downleft.png b/addons/escoria-wizard/graphics/robot/talk_downleft.png new file mode 100644 index 00000000..fb4c9714 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_downleft.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_downright.png b/addons/escoria-wizard/graphics/robot/talk_downright.png new file mode 100644 index 00000000..d09a52da Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_downright.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_right.png b/addons/escoria-wizard/graphics/robot/talk_right.png new file mode 100644 index 00000000..e5fa6a21 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_right.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_up.png b/addons/escoria-wizard/graphics/robot/talk_up.png new file mode 100644 index 00000000..7d77d81c Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_up.png differ diff --git a/addons/escoria-wizard/graphics/robot/talk_upright.png b/addons/escoria-wizard/graphics/robot/talk_upright.png new file mode 100644 index 00000000..5a3fd6ae Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/talk_upright.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_down.png b/addons/escoria-wizard/graphics/robot/walk_down.png new file mode 100644 index 00000000..432cf82a Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_down.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_downleft.png b/addons/escoria-wizard/graphics/robot/walk_downleft.png new file mode 100644 index 00000000..464a4469 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_downleft.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_downright.png b/addons/escoria-wizard/graphics/robot/walk_downright.png new file mode 100644 index 00000000..7eeea0f8 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_downright.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_right.png b/addons/escoria-wizard/graphics/robot/walk_right.png new file mode 100644 index 00000000..91c08ddf Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_right.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_up.png b/addons/escoria-wizard/graphics/robot/walk_up.png new file mode 100644 index 00000000..65dfcc06 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_up.png differ diff --git a/addons/escoria-wizard/graphics/robot/walk_upright.png b/addons/escoria-wizard/graphics/robot/walk_upright.png new file mode 100644 index 00000000..2a619381 Binary files /dev/null and b/addons/escoria-wizard/graphics/robot/walk_upright.png differ diff --git a/addons/escoria-wizard/graphics/room.png b/addons/escoria-wizard/graphics/room.png new file mode 100644 index 00000000..42746fae Binary files /dev/null and b/addons/escoria-wizard/graphics/room.png differ diff --git a/addons/escoria-wizard/graphics/roomitem.png b/addons/escoria-wizard/graphics/roomitem.png new file mode 100644 index 00000000..7770f7c3 Binary files /dev/null and b/addons/escoria-wizard/graphics/roomitem.png differ diff --git a/addons/escoria-wizard/graphics/wand.png b/addons/escoria-wizard/graphics/wand.png new file mode 100644 index 00000000..d692dc4e Binary files /dev/null and b/addons/escoria-wizard/graphics/wand.png differ diff --git a/addons/escoria-wizard/help_window.gd b/addons/escoria-wizard/help_window.gd new file mode 100644 index 00000000..8a5e3455 --- /dev/null +++ b/addons/escoria-wizard/help_window.gd @@ -0,0 +1,56 @@ +tool +extends WindowDialog + + +# Declare member variables here. Examples: +# var a: int = 2 +# var b: String = "text" + +const LAST_PAGE = 15 + +export var current_page = 1 + + +func help_on_prev_button_pressed() -> void: + current_page -= 1 + if current_page < 1: + current_page = 1 + show_page() + + +func help_on_next_button_pressed() -> void: + current_page += 1 + if current_page > LAST_PAGE: + current_page = LAST_PAGE + show_page() + + +func show_page() -> void: + for loop in get_tree().get_nodes_in_group("masks"): + loop.visible = false + for loop in get_tree().get_nodes_in_group("pagetext"): + loop.visible = false + + $masks/leftall.visible = true + $masks/middleall.visible = true + $masks/rightall.visible = true + + get_node("masks").get_node("page%s" % current_page).visible = true + get_node("text").get_node("page%s" % current_page).visible = true + + match current_page: + 2: $masks/leftall.visible = false + 3: $masks/rightall.visible = false + 4: $masks/leftall.visible = false + 5: $masks/leftall.visible = false + 6: $masks/leftall.visible = false + 7: $masks/leftall.visible = false + 8: $masks/middleall.visible = false + 9: $masks/middleall.visible = false + 10: $masks/middleall.visible = false + 11: $masks/rightall.visible = false + 12: $masks/rightall.visible = false + 13: $masks/rightall.visible = false + 14: $masks/rightall.visible = false + + diff --git a/addons/escoria-wizard/help_window.tscn b/addons/escoria-wizard/help_window.tscn new file mode 100644 index 00000000..cb0709c1 --- /dev/null +++ b/addons/escoria-wizard/help_window.tscn @@ -0,0 +1,533 @@ +[gd_scene load_steps=19 format=2] + +[ext_resource path="res://addons/escoria-wizard/graphics/help/left3.png" type="Texture" id=1] +[ext_resource path="res://addons/escoria-wizard/graphics/help/left4.png" type="Texture" id=2] +[ext_resource path="res://addons/escoria-wizard/graphics/help/left5.png" type="Texture" id=3] +[ext_resource path="res://addons/escoria-wizard/graphics/help/middle3.png" type="Texture" id=4] +[ext_resource path="res://addons/escoria-wizard/graphics/help/right4.png" type="Texture" id=5] +[ext_resource path="res://addons/escoria-wizard/graphics/help/middleall.png" type="Texture" id=6] +[ext_resource path="res://addons/escoria-wizard/graphics/help/middle2.png" type="Texture" id=7] +[ext_resource path="res://addons/escoria-wizard/graphics/help/left2.png" type="Texture" id=8] +[ext_resource path="res://addons/escoria-wizard/graphics/help/rightall.png" type="Texture" id=9] +[ext_resource path="res://addons/escoria-wizard/graphics/help/right5.png" type="Texture" id=10] +[ext_resource path="res://addons/escoria-wizard/graphics/help/right2.png" type="Texture" id=11] +[ext_resource path="res://addons/escoria-wizard/graphics/help/right3.png" type="Texture" id=12] +[ext_resource path="res://addons/escoria-wizard/graphics/help/leftall.png" type="Texture" id=13] +[ext_resource path="res://addons/escoria-wizard/graphics/help/help_background.png" type="Texture" id=14] +[ext_resource path="res://addons/escoria-wizard/graphics/help/left1.png" type="Texture" id=15] +[ext_resource path="res://addons/escoria-wizard/graphics/help/middle1.png" type="Texture" id=16] +[ext_resource path="res://addons/escoria-wizard/graphics/help/right1.png" type="Texture" id=17] +[ext_resource path="res://addons/escoria-wizard/help_window.gd" type="Script" id=18] + +[node name="help_window" type="WindowDialog"] +margin_left = 100.0 +margin_top = 100.0 +margin_right = 1012.0 +margin_bottom = 742.0 +popup_exclusive = true +script = ExtResource( 18 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 4.0 +margin_top = 4.0 +margin_right = 908.0 +margin_bottom = 638.0 + +[node name="Background" type="TextureRect" parent="VBoxContainer"] +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 14 ) + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer"] +margin_top = 614.0 +margin_right = 904.0 +margin_bottom = 634.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CenterContainer"] +margin_left = 322.0 +margin_right = 581.0 +margin_bottom = 20.0 + +[node name="prev_button" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"] +margin_right = 118.0 +margin_bottom = 20.0 +text = "<- Previous Page" + +[node name="Control" type="Control" parent="VBoxContainer/CenterContainer/HBoxContainer"] +margin_left = 122.0 +margin_right = 162.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 40, 20 ) + +[node name="next_button" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"] +margin_left = 166.0 +margin_right = 259.0 +margin_bottom = 20.0 +text = "Next Page ->" + +[node name="masks" type="Control" parent="."] +margin_right = 40.0 +margin_bottom = 40.0 + +[node name="leftall" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 13 ) + +[node name="middleall" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 324.0 +margin_top = 8.0 +margin_right = 663.0 +margin_bottom = 610.0 +texture = ExtResource( 6 ) + +[node name="rightall" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 9 ) + +[node name="page1" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 4.0 +margin_top = 4.0 +margin_right = 305.0 +margin_bottom = 606.0 + +[node name="page2" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 15 ) + +[node name="page3" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 17 ) + +[node name="page4" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 8 ) + +[node name="page5" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 1 ) + +[node name="page6" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 2 ) + +[node name="page7" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 309.0 +margin_bottom = 610.0 +texture = ExtResource( 3 ) + +[node name="page8" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 324.0 +margin_top = 8.0 +margin_right = 663.0 +margin_bottom = 610.0 +texture = ExtResource( 16 ) + +[node name="page9" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 324.0 +margin_top = 8.0 +margin_right = 663.0 +margin_bottom = 610.0 +texture = ExtResource( 7 ) + +[node name="page10" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 324.0 +margin_top = 8.0 +margin_right = 663.0 +margin_bottom = 610.0 +texture = ExtResource( 4 ) + +[node name="page11" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 11 ) + +[node name="page12" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 12 ) + +[node name="page13" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 5 ) + +[node name="page14" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.882353 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 904.0 +margin_bottom = 610.0 +texture = ExtResource( 10 ) + +[node name="page15" type="TextureRect" parent="masks" groups=["masks"]] +visible = false +modulate = Color( 1, 1, 1, 0.784314 ) +margin_left = 678.0 +margin_top = 8.0 +margin_right = 979.0 +margin_bottom = 610.0 + +[node name="text" type="Control" parent="."] +margin_right = 40.0 +margin_bottom = 40.0 + +[node name="page1" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 229.0 +margin_top = 137.0 +margin_right = 699.0 +margin_bottom = 440.0 +text = "Escoria Player Creator + +Game characters in Escoria are Godot scenes with an ESCPlayer node. +The ESCPlayer requires configuration to define things like how many +directions the character has animations defined for, and which +movement direction in the game world corresponds to each animation. + +While Escoria can create characters that can move in as many +directions as you like, most games will feature characters that can +move in either 4 or 8 directions. For each direction, walk, talk and idle +animations are required. This tool simplifies the process for configuring +all these settings. + +These help pages will guide you through the process, but essentially you +give your character a name, choose 4 or 8 directions, then choose frames +from sprite sheets for walk, talk and idle animations in each direction. + +Click the \"Next Page\" button below to progress to the next help page." + +[node name="page2" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 301.0 +margin_top = 6.0 +margin_right = 657.0 +margin_bottom = 156.0 +text = "Use the name field to supply a name for your character. +Any changes to the name will be reflected to the +global_id field. The global_id is used to identify the +character in scripts. + +Note that you can change the global_id to be different +from the name if you choose. It's generally easiest +to keep them the same but there's no requirement to. +" + +[node name="page3" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 299.0 +margin_top = 10.0 +margin_right = 654.0 +margin_bottom = 194.0 +text = "Use the \"Load Spritesheet\" button to load a spritesheet +graphic. The spritesheet is an image that contains one +or more sprite frames that will be used for the walk, +talk and/or idle animation frames for the character. + +The character creator remembers which spritesheet is +used for each type and direction of animation, so you +can use one spritesheet for all the animations, one +spritesheet per animation, or any combination +inbetween. +" + +[node name="page4" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 298.0 +margin_top = 59.0 +margin_right = 591.0 +margin_bottom = 124.0 +text = "Use these buttons to indicate whether your +character will have animations facing in either +4 or 8 directions. This can be changed at any +time while creating the character." + +[node name="page5" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 303.0 +margin_top = 105.0 +margin_right = 596.0 +margin_bottom = 170.0 +text = "You will use these buttons to choose whether +you are currently creating walk, talk, or idle +animations." + +[node name="page6" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 133.0 +margin_top = 126.0 +margin_right = 523.0 +margin_bottom = 378.0 +text = "Click the arrow matching the direction you wish to create +an animation for. For example, if you select walk from the +options above, and the right arrow, you'll be creating the +animation for the character walking right. + +Once you store (save) the animation, the arrow will change +to a green colour to show you the animation has been +configured. It can still be edited once it has been stored. + +When you select an direction that isn't up or down, the +mirror button will appear. If you click this button, the +animation will be created automatically as a mirror of the +opposite side's animation. e.g. If you create the right side +animation, you can click the left arrow then the mirror +button to quickly create the left hand animation." + +[node name="page7" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 63.0 +margin_top = 369.0 +margin_right = 334.0 +margin_bottom = 417.0 +text = "When you select the animation frames to +define a particular animation, a preview +of the animation will be shown in this box." + +[node name="page8" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 37.0 +margin_top = 21.0 +margin_right = 308.0 +margin_bottom = 103.0 +text = "This is the currently loaded spritesheet. +As you select particular frames to be +part of the current animation, a box will +be drawn around them to help you see +what is included in the animation." + +[node name="page9" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 339.0 +margin_top = 422.0 +margin_right = 610.0 +margin_bottom = 538.0 +text = "Use this slider to reset the zoom level +on the spritesheet. The zoom is only +used in this tool and will not affect the +zoom level of your character in game. + +Use the reset button to reset the zoom +level." + +[node name="page10" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 354.0 +margin_top = 511.0 +margin_right = 594.0 +margin_bottom = 559.0 +text = "This information window tells you the +filename of the currently loaded +spritesheet." + +[node name="page11" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 297.0 +margin_top = 28.0 +margin_right = 622.0 +margin_bottom = 229.0 +text = "Once you've loaded your spritesheet you need to +tell the character creator how to divide it into +individual frames with the horizontal/vertical +frames selectors. + +The start/end frame selectors tell the tool which +frames to use from the spritesheet to create the +animation. + +The speed slider defines the speed of this +animation in frames per second. Each animation +can have a different speed value if desired." + +[node name="page12" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 374.0 +margin_top = 124.0 +margin_right = 651.0 +margin_bottom = 189.0 +text = "These lines are informational. They tell you +how big the current spritesheet is, and how +big each animation frame is based on the +frame settings above." + +[node name="page13" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 374.0 +margin_top = 171.0 +margin_right = 648.0 +margin_bottom = 321.0 +text = "When you change the settings for the +current animation, the \"store animation\" +button will appear. This saves the current +settings to the selected animation. + +If the settings are changed back to how +they were, the store button will +disappear to tell you that there is currently +no change to save." + +[node name="page14" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 332.0 +margin_top = 228.0 +margin_right = 660.0 +margin_bottom = 429.0 +text = "Click this button to export the completed character +out to a Godot scene for use by Escoria. +Note that a walk, talk and idle animation for each of +the specified (4 or 8) directions must have been +set up before you can export the character. + +If any animations haven't been configured, it will +tell you that animations are missing. + +Direction arrows that haven't turned green are a +visual indicator of the directions still requiring +animations." + +[node name="page15" type="Label" parent="text" groups=["pagetext"]] +visible = false +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = 273.0 +margin_top = 143.0 +margin_right = 663.0 +margin_bottom = 412.0 +text = "Once you have exported your character they will be a saved +ESCPlayer scene in your filesystem. The scene will be named +based on the name you gave your character in the Name +field. + +If this is a user-controllable character, this character can now +be included in your game by : + +* Creating a Godot scene for your room +* Creating an ESCRoom node +* Selecting the created ESCPlayer scene as the Player Scene + property in that node. + +If they are an NPC, add the scene to your scene tree, and +program them in your ESC scripts using the global_id you +have configured." + +[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/prev_button" to="." method="help_on_prev_button_pressed"] +[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/next_button" to="." method="help_on_next_button_pressed"] diff --git a/addons/escoria-wizard/item_creator.gd b/addons/escoria-wizard/item_creator.gd new file mode 100644 index 00000000..ef08e484 --- /dev/null +++ b/addons/escoria-wizard/item_creator.gd @@ -0,0 +1,283 @@ +tool +extends MarginContainer + + +const ITEM_NAME_NODE = "VBoxContainer/Content/GridContainer/ItemName" +const GLOBAL_ID_NODE = "VBoxContainer/Content/GridContainer/ItemGlobalID" +const INTERACTIVE_NODE = "VBoxContainer/Content/GridContainer/StartsInteractiveCheckBox" +const ACTION_NODE = "VBoxContainer/Content/GridContainer/DefaultActionOption" +const PREVIEW_NODE = "VBoxContainer/Content/GridContainer/Preview/Preview" +const IMAGE_SIZE_NODE = "VBoxContainer/Content/GridContainer/ImageSize" +const IMAGE_PATH_NODE = "VBoxContainer/Content/GridContainer/ImagePath" +const LOAD_NODE = "LoadObjectGraphic/LoadObjectFileDialog" +const CONFIRM_NODE = "Windows/ConfirmationDialog" +const OBJECT_HEADING_NODE = "VBoxContainer/HelperHeading/CenterContainer/ObjectHeading" +const OBJECT_DESC_NODE = "VBoxContainer/Description/ObjectDescription" +const INVENTORY_HEADING_NODE = "VBoxContainer/HelperHeading/CenterContainer/InventoryHeading" +const INVENTORY_DESC_NODE = "VBoxContainer/Description/InventoryDescription" +const INVENTORY_PATH_NODE = "VBoxContainer/Content/GridContainer/InventoryPath" +const INVENTORY_PATH_LABEL_NODE = "VBoxContainer/Content/GridContainer/InventoryPathLabel" +const INVENTORY_PATH_SPACER_NODE = "VBoxContainer/Content/GridContainer/BlankItem7" +const CREATE_BUTTON_NODE = "VBoxContainer/Buttons/CenterContainer/HBoxContainer/CreateButton" +const ERROR_WINDOW_NODE = "Windows/ErrorDialog" +const INVENTORY_PREV_NODE = "VBoxContainer/Content/GridContainer/Preview/InventoryPreview" +const OBJECT_PREV_NODE = "VBoxContainer/Content/GridContainer/Preview/ObjectPreview" + + +var source_image:Image +var image_stream_texture:StreamTexture +var image_has_been_loaded:bool +var image_size:Vector2 +var main_menu_requested:bool +var inventory_mode:bool +var settings_modified:bool + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + inventory_mode = false + item_creator_reset() + + +func item_creator_reset() -> void: + get_node(ITEM_NAME_NODE).text = "replace_me" + get_node(GLOBAL_ID_NODE).text = "" + get_node(IMAGE_PATH_NODE).text = "" + get_node(INTERACTIVE_NODE).pressed = true + + if get_node(ACTION_NODE).get_item_count() > 0: + get_node(ACTION_NODE).clear() + + for option_list in ["look", "pick up", "open", "close", "use", "push", "pull", "talk"]: + get_node(ACTION_NODE).add_item(option_list) + + get_node(ACTION_NODE).selected = 0 + image_size = Vector2.ZERO + image_has_been_loaded = false + main_menu_requested = false + settings_modified = false + get_node(PREVIEW_NODE).texture = null + + if inventory_mode: + get_node(INVENTORY_PATH_NODE).text = ProjectSettings.get_setting("escoria/ui/inventory_items_path") + get_node(CREATE_BUTTON_NODE).text = "Create Inventory" + get_node(INVENTORY_PREV_NODE).visible = true + get_node(OBJECT_PREV_NODE).visible = false + + for loop in [INVENTORY_PATH_NODE, INVENTORY_PATH_LABEL_NODE, INVENTORY_PATH_SPACER_NODE]: + get_node(loop).visible = true + else: + get_node(CREATE_BUTTON_NODE).text = "Create Object" + get_node(INVENTORY_PREV_NODE).visible = false + get_node(OBJECT_PREV_NODE).visible = true + for loop in [INVENTORY_PATH_NODE, INVENTORY_PATH_LABEL_NODE, INVENTORY_PATH_SPACER_NODE]: + get_node(loop).visible = false + + for loop in [OBJECT_HEADING_NODE, OBJECT_DESC_NODE]: + get_node(loop).visible = not inventory_mode + + for loop in [INVENTORY_HEADING_NODE, INVENTORY_DESC_NODE, INVENTORY_PATH_NODE]: + get_node(loop).visible = inventory_mode + + +func resize_image() -> void: + var preview_size = get_node(PREVIEW_NODE).rect_size + + # Calculate the scale to make the preview as big as possible in the preview window depending on + # the height to width ratio of the frame + image_size = image_stream_texture.get_size() + var preview_scale = Vector2.ONE + preview_scale.x = preview_size.x / image_size.x + preview_scale.y = preview_size.y / image_size.y + + if preview_scale.y > preview_scale.x: + get_node(PREVIEW_NODE).rect_scale = Vector2(preview_scale.x, preview_scale.x) + else: + get_node(PREVIEW_NODE).rect_scale = Vector2(preview_scale.y, preview_scale.y) + + +func background_on_ItemName_text_changed(new_text: String) -> void: + get_node(GLOBAL_ID_NODE).text = new_text + settings_modified = true + + +func load_button_pressed() -> void: + get_node(LOAD_NODE).popup_centered() + + +func LoadObjectFileDialog_file_selected(path: String) -> void: + image_stream_texture = load(path) + + get_node(PREVIEW_NODE).texture = image_stream_texture + + resize_image() + + get_node(IMAGE_SIZE_NODE).text = "(%s, %s)" % [image_size.x, image_size.y] + + get_node(IMAGE_PATH_NODE).text = path + image_has_been_loaded = true + settings_modified = true + get_node(INVENTORY_PREV_NODE).visible = false + get_node(OBJECT_PREV_NODE).visible = false + + +func _on_CreateButton_pressed() -> void: + if not image_has_been_loaded: + get_node(ERROR_WINDOW_NODE).dialog_text = \ + "No image has been loaded." + get_node(ERROR_WINDOW_NODE).popup_centered() + return + + if get_node(ITEM_NAME_NODE).text == "replace_me": + get_node(ERROR_WINDOW_NODE).dialog_text = \ + "Please change the object name." + get_node(ERROR_WINDOW_NODE).popup_centered() + return + + if inventory_mode == false: + if not EditorPlugin.new().get_editor_interface().get_selection().get_selected_nodes(): + get_node(ERROR_WINDOW_NODE).dialog_text = \ + "Please select a node in the scene tree\nto attach the object to." + get_node(ERROR_WINDOW_NODE).popup_centered() + return + + var item = ESCItem.new() + item.name = get_node(ITEM_NAME_NODE).text + item.global_id = get_node(GLOBAL_ID_NODE).text + item.is_interactive = get_node(INTERACTIVE_NODE).pressed + item.tooltip_name = get_node(ITEM_NAME_NODE).text + + var selected_index = get_node(ACTION_NODE).selected + item.default_action = get_node(ACTION_NODE).get_item_text(selected_index) + + # Add Dialog Position to the background item + var interact_position = ESCLocation.new() + interact_position.name = "interact_position" + interact_position.position.y = image_size.y * 2 + item.add_child(interact_position) + + # Add Collision shape to the background item + var rectangle_shape = RectangleShape2D.new() + var collision_shape = CollisionShape2D.new() + + collision_shape.shape = rectangle_shape + collision_shape.shape.extents = image_size / 2 + item.add_child(collision_shape) + + # Add sprite to the background item + var item_sprite = Sprite.new() + item_sprite.texture = get_node(PREVIEW_NODE).texture + item.add_child(item_sprite) + + if not inventory_mode: + # Create in scene tree + # Attach to currently selected node in scene tree + var current_node = EditorPlugin.new().get_editor_interface().get_selection().get_selected_nodes()[0] + current_node.add_child(item) + var owning_node = get_tree().edited_scene_root + item.set_owner(owning_node) + # Make it so all the nodes can be seen in the scene tree + collision_shape.set_owner(owning_node) + interact_position.set_owner(owning_node) + item_sprite.set_owner(owning_node) + + get_node("Windows/CreateCompleteDialog").dialog_text = \ + "Background object %s created.\n\n" % item + \ + "Note that you can right-click the node in the\n" + \ + "scene tree and select \"Save branch as scene\"\n" + \ + "if you'd like to reuse this item." + print("Background object %s created." % item) + get_node("Windows/CreateCompleteDialog").popup_centered() + else: + get_tree().edited_scene_root.add_child(item) + # Make it so all the nodes can be seen in the scene tree + collision_shape.set_owner(item) + interact_position.set_owner(item) + item_sprite.set_owner(item) + + item.set_owner(get_tree().edited_scene_root) + # Export scene - create in inventory folder + var packed_scene = PackedScene.new() + + packed_scene.pack(get_tree().edited_scene_root.get_node(item.name)) + var inventory_path = ProjectSettings.get_setting("escoria/ui/inventory_items_path") + ResourceSaver.save("%s/%s.tscn" % [inventory_path, get_node(ITEM_NAME_NODE).text], packed_scene) + + # Flag suggestions from https://godotengine.org/qa/50437/how-to-turn-a-node-into-a-packedscene-via-gdscript + ResourceSaver.save("%s/%s.tscn" % [inventory_path, get_node(ITEM_NAME_NODE).text], packed_scene, \ + ResourceSaver.FLAG_CHANGE_PATH|ResourceSaver.FLAG_REPLACE_SUBRESOURCE_PATHS) + + item.queue_free() + get_tree().edited_scene_root.get_node(item.name).queue_free() + get_node("Windows/CreateCompleteDialog").dialog_text = \ + "Inventory item %s/%s.tscn created." % [inventory_path, get_node(ITEM_NAME_NODE).text] + print("Inventory item %s/%s.tscn created." % [inventory_path, get_node(ITEM_NAME_NODE).text]) + get_node("Windows/CreateCompleteDialog").popup_centered() + + +func Item_on_ClearButton_pressed() -> void: + if settings_modified == true: + main_menu_requested = false + get_node(CONFIRM_NODE).dialog_text = "WARNING!\n\n" + \ + "If you continue you will lose the current object." + get_node(CONFIRM_NODE).popup_centered() + + +func _on_ObjectConfirmationDialog_confirmed() -> void: + if main_menu_requested == true: + switch_to_main_menu() + else: + item_creator_reset() + + +func Item_on_ExitButton_pressed() -> void: + if settings_modified == true: + main_menu_requested = true + get_node(CONFIRM_NODE).dialog_text = "WARNING!\n\n" + \ + "If you continue you will lose the current object." + get_node(CONFIRM_NODE).popup_centered() + else: + switch_to_main_menu() + + +func switch_to_main_menu() -> void: + get_node("../Menu").visible = true + get_node("../ItemCreator").visible = false + + +func _on_StartsInteractiveCheckBox_pressed() -> void: + settings_modified = true + + +func _on_ItemGlobalID_text_changed(_new_text: String) -> void: + settings_modified = true + + +func _on_DefaultActionOption_item_selected(_index: int) -> void: + settings_modified = true + + +func _on_CreateCompleteDialog_confirmed() -> void: + item_creator_reset() + + +func _on_BackgroundObjectCheckBox_toggled(button_pressed: bool) -> void: + if button_pressed == false: + $VBoxContainer/Control/CenterContainer/HBoxContainer/InventoryItemCheckBox.set_pressed_no_signal(true) + inventory_mode = true + else: + $VBoxContainer/Control/CenterContainer/HBoxContainer/InventoryItemCheckBox.set_pressed_no_signal(false) + inventory_mode = false + + item_creator_reset() + + +func _on_InventoryItemCheckBox_toggled(button_pressed: bool) -> void: + if button_pressed == false: + $VBoxContainer/Control/CenterContainer/HBoxContainer/BackgroundObjectCheckBox.set_pressed_no_signal(true) + inventory_mode = false + else: + $VBoxContainer/Control/CenterContainer/HBoxContainer/BackgroundObjectCheckBox.set_pressed_no_signal(false) + inventory_mode = true + + item_creator_reset() diff --git a/addons/escoria-wizard/plugin.cfg b/addons/escoria-wizard/plugin.cfg new file mode 100644 index 00000000..ad7e2a23 --- /dev/null +++ b/addons/escoria-wizard/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Escoria Wizard" +description="This plugin is used to make the creation of Escoria resources easier for developers." +author="BalloonPopper" +version="1.0.0" +script="plugin.gd" diff --git a/addons/escoria-wizard/plugin.gd b/addons/escoria-wizard/plugin.gd new file mode 100644 index 00000000..6a0270db --- /dev/null +++ b/addons/escoria-wizard/plugin.gd @@ -0,0 +1,41 @@ +tool +extends EditorPlugin + +const helper_ui = preload("res://addons/escoria-wizard/escoria_wizard.tscn") + +# This is the instance of the plugin code that is instantiated by the plugin. +var helper_instance + +func _enter_tree() -> void: + helper_instance = helper_ui.instance() + helper_instance.plugin_reference = self + # Add the panel to the main viewport + get_editor_interface().get_editor_viewport().add_child(helper_instance) + make_visible(false) + + +func _exit_tree() -> void: + if helper_instance: + helper_instance.queue_free() + + +func has_main_screen() -> bool: + # Add the button to the Godot interface ribbon + return true + + +func make_visible(visible: bool) -> void: + if helper_instance: + helper_instance.visible = visible + + +func get_plugin_name() -> String: + return "Escoria Wizard" + + +func get_plugin_icon() -> Texture: + return (preload("res://addons/escoria-wizard/graphics/icon16x16.png")) + + +func open_scene(path: String) -> void: + get_editor_interface().open_scene_from_path(path) diff --git a/addons/escoria-wizard/room_script_template.esc b/addons/escoria-wizard/room_script_template.esc new file mode 100644 index 00000000..ed56af38 --- /dev/null +++ b/addons/escoria-wizard/room_script_template.esc @@ -0,0 +1,41 @@ +# Room script template + +# ":setup" is used to configure anything you want in place before the +# transition-in event runs (i.e. anything you need to set up before the player +# sees the room). Reset movable objects to their start positions here. + +:setup + + + +# ":ready" runs after any events configured in setup complete. It is used to +# configure everything that happens after the transition-in (if any) completes. +# runs. Story telling events go here (e.g. if you want the character to walk to +# a specific location in the room before giving control to the player.) + +:ready + + + +# Code examples - feel free to delete this section +# +# 1) Run this code when the player enters this room for the first time only. +# This assumes your room is called "room_hallway". Also resets the "window" +# to closed by playing the animation "close_window" using 'set_state'. +# +# > [!room_hallway_visited] +# set_global room_hallway_visited true +# set_state window close_window true +# +# +# 2) Change where the player starts depending on which doorway they entered +# the room from. Assumes your character is called "cleaner" +# +# > [eq ESC_LAST_SCENE room2] +# teleport cleaner r1_r_exit +# # Set cleaner look left +# set_angle cleaner 270 +# +# + +