diff options
| author | Radio <radiohotline@disroot.org> | 2026-06-04 15:15:11 +0300 |
|---|---|---|
| committer | Radio <radiohotline@disroot.org> | 2026-06-04 15:15:11 +0300 |
| commit | 9d74b49ab62908d4acf53dde444413886b8b28e5 (patch) | |
| tree | 0cb785267ea7e239b19d88684c0d64b9bd5d52f0 /addons/escoria-ui-simplemouse/game.gd | |
| parent | 2c85d452ad02a5f89cd43bad7f9de31d0e4fa0c1 (diff) | |
escoria setup and old branch archives
Diffstat (limited to 'addons/escoria-ui-simplemouse/game.gd')
| -rw-r--r-- | addons/escoria-ui-simplemouse/game.gd | 485 |
1 files changed, 485 insertions, 0 deletions
diff --git a/addons/escoria-ui-simplemouse/game.gd b/addons/escoria-ui-simplemouse/game.gd new file mode 100644 index 0000000..3730d78 --- /dev/null +++ b/addons/escoria-ui-simplemouse/game.gd @@ -0,0 +1,485 @@ +extends ESCGame + + +const VERB_USE = "use" +const VERB_WALK = "walk" + + +""" +Implement methods to react to inputs. + +- left_click_on_bg(position: Vector2) +- right_click_on_bg(position: Vector2) +- left_double_click_on_bg(position: Vector2) + +- element_focused(element_id: String) +- element_unfocused() + +- left_click_on_item(item_global_id: String, event: InputEvent) +- right_click_on_item(item_global_id: String, event: InputEvent) +- left_double_click_on_item(item_global_id: String, event: InputEvent) + +- left_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) +- right_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) +- left_double_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) +- inventory_item_focused(inventory_item_global_id: String) +- inventory_item_unfocused() +- open_inventory() +- close_inventory() + +- mousewheel_action(direction: int) + +- hide_ui() +- show_ui() + +- pause_game() +- unpause_game() +- show_main_menu() +- hide_main_menu() + +- apply_custom_settings() + +- _on_event_done(event_name: String) +""" + +# Value to use for `device` argument to various `Input.get_joy` methods. +const JOY_DEVICE = 0 + +# See https://docs.godotengine.org/en/stable/tutorials/inputs/controllers_gamepads_joysticks.html?#dead-zone +const DEADZONE = 0.2 + +# Multiplier to apply to axis when it exceeds DEADZONE. +const AXIS_WEIGHT = 50.0 + +# JOY_BUTTON_X corresponds to the "X" button on an XBox controller +# or the Square button on a Playstation controller. These appear to +# map to the "primary action," in practice, so we treat it like a left click. +const PRIMARY_ACTION_BUTTON = JOY_BUTTON_X + +# JOY_BUTTON_Y corresponds to the "Y" button on an XBox controller +# or the Triangle button on a Playstation controller. These appear to +# map to the "secondary action," in practice, so we treat it like a right click. +const CHANGE_VERB_BUTTON = JOY_BUTTON_Y + +# Input action for use by InputMap +const ESC_UI_CHANGE_VERB_ACTION = "esc_change_verb" + +# true when a gamepad is connected. +var _is_gamepad_connected = false + +# Tracks the mouse's current position onscreen. +var _current_mouse_pos: Vector2 = Vector2.ZERO + +var targeted_node: Node + + +func _ready(): + hide_ui() + $ui/tooltip.connect("tooltip_size_updated", Callable(self, "update_tooltip_following_mouse_position")) + +func _enter_tree(): + initialize_esc_game() + + var room_selector_parent = $ui/HBoxContainer/VBoxContainer + + if ESCProjectSettingsManager.get_setting(ESCProjectSettingsManager.ENABLE_ROOM_SELECTOR) \ + and room_selector_parent.get_node_or_null("room_select") == null: + + room_selector_parent.add_child( + preload( + "res://addons/escoria-core/ui_library/tools/room_select" +\ + "/room_select.tscn" + ).instantiate() + ) + + var input_handler = Callable(self._process_input) + escoria.inputs_manager.register_custom_input_handler(input_handler) + + _is_gamepad_connected = Input.is_joy_known(JOY_DEVICE) + if _is_gamepad_connected: + _on_gamepad_connected() + + Input.connect("joy_connection_changed", Callable(self, "_on_joy_connection_changed")) + + +func _exit_tree(): + escoria.inputs_manager.register_custom_input_handler(null) + Input.disconnect("joy_connection_changed", Callable(self, "_on_joy_connection_changed")) + if _is_gamepad_connected: + _on_gamepad_disconnected() + + +func _input(event: InputEvent) -> void: + super._input(event) + if escoria.get_escoria().is_ready_for_inputs(): + if event is InputEventMouseMotion: + _current_mouse_pos = get_global_mouse_position() + update_tooltip_following_mouse_position() + + +# https://github.com/godotengine/godot-demo-projects/blob/3.4-585455e/misc/joypads/joypads.gd +# was informative in wiring up the gamepad properly. + +func _on_gamepad_connected(): + set_physics_process(true) + + var primary_event = InputEventJoypadButton.new() + primary_event.button_index = PRIMARY_ACTION_BUTTON + InputMap.add_action(escoria.inputs_manager.ESC_UI_PRIMARY_ACTION) + InputMap.action_add_event(escoria.inputs_manager.ESC_UI_PRIMARY_ACTION, primary_event) + + var verb_event = InputEventJoypadButton.new() + verb_event.button_index = CHANGE_VERB_BUTTON + InputMap.add_action(ESC_UI_CHANGE_VERB_ACTION) + InputMap.action_add_event(ESC_UI_CHANGE_VERB_ACTION, verb_event) + + +func _on_gamepad_disconnected(): + InputMap.action_erase_events(escoria.inputs_manager.ESC_UI_PRIMARY_ACTION) + InputMap.erase_action(escoria.inputs_manager.ESC_UI_PRIMARY_ACTION) + + InputMap.action_erase_events(ESC_UI_CHANGE_VERB_ACTION) + InputMap.erase_action(ESC_UI_CHANGE_VERB_ACTION) + + set_physics_process(false) + _is_gamepad_connected = false + + +func _on_joy_connection_changed(device: int, connected: bool) -> void: + if device != JOY_DEVICE: + return + elif connected: + _on_gamepad_connected() + else: + _on_gamepad_disconnected() + + +func _process(_delta) -> void: + if !_is_gamepad_connected: + return + + var x = Input.get_joy_axis(JOY_DEVICE, JOY_AXIS_LEFT_X) + var y = Input.get_joy_axis(JOY_DEVICE, JOY_AXIS_LEFT_Y) + var delta_x = int(x * AXIS_WEIGHT) if abs(x) > DEADZONE else 0 + var delta_y = int(y * AXIS_WEIGHT) if abs(y) > DEADZONE else 0 + if delta_x or delta_y: + var direction: Vector2 + direction.x = delta_x + direction.y = delta_y + escoria.logger.trace(self, "gamepad direction: %s" % [direction]) + var viewport = get_viewport() + viewport.warp_mouse(viewport.get_mouse_position() + direction) + + +func _process_input(event: InputEvent, is_default_state: bool) -> bool: + if not is_default_state: + # ESCBackground is not guaranteed to be set, as we may be on + # the "New Game" screen. + return false + elif _is_gamepad_connected and event is InputEventJoypadButton: + escoria.logger.trace(self, "InputEventJoypadButton: %s" % [event.as_text()]) + if event.is_action_pressed(escoria.inputs_manager.ESC_UI_PRIMARY_ACTION): + # Admittedly, this breaks abstraction barriers and is completely + # inappropriate, but it's what works right now. + escoria.inputs_manager._on_left_click_on_bg(get_global_mouse_position()) + return true + elif event.is_action_pressed(ESC_UI_CHANGE_VERB_ACTION): + mousewheel_action(1) + return true + return false + + +## BACKGROUND ## + +func left_click_on_bg(position: Vector2) -> void: + if escoria.main.current_scene.player: + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, + [escoria.main.current_scene.player.global_id, position], + true + ) + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + $mouse_layer/verbs_menu.clear_tool_texture() + $mouse_layer/verbs_menu.action_manually_changed = false + close_inventory() + +func right_click_on_bg(position: Vector2) -> void: + left_double_click_on_bg(position) + +func left_double_click_on_bg(position: Vector2) -> void: + if escoria.main.current_scene.player: + escoria.action_manager.do( + escoria.action_manager.ACTION.BACKGROUND_CLICK, + [escoria.main.current_scene.player.global_id, position, true], + true + ) + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + $mouse_layer/verbs_menu.clear_tool_texture() + $mouse_layer/verbs_menu.action_manually_changed = false + close_inventory() + +## ITEM/HOTSPOT FOCUS ## + +func element_focused(element_id: String) -> void: + var target_obj: ESCItem = escoria.object_manager.get_object(element_id).node + + # This code is commented to demonstrate how to implement a simple hover + # behaviour on an item. + #if target_obj.has_method("get_sprite") and target_obj.get_sprite().texture: + #targeted_node = target_obj.get_sprite() + #targeted_node.modulate = Color.GRAY + + $ui/tooltip.set_target(target_obj.tooltip_name) + + if escoria.action_manager.current_action != VERB_USE \ + and escoria.action_manager.current_tool == null \ + and target_obj is ESCItem: + + if target_obj.is_exit: + if element_id.contains("_l_"): + $mouse_layer/verbs_menu.set_by_name("exit_left", "walk") + elif element_id.contains("_r_"): + $mouse_layer/verbs_menu.set_by_name("exit_right", "walk") + else: + $mouse_layer/verbs_menu.set_by_name("walk") + elif not $mouse_layer/verbs_menu.action_manually_changed: + $mouse_layer/verbs_menu.set_by_name(target_obj.default_action) + +func element_unfocused() -> void: + $ui/tooltip.set_target("") + if not $mouse_layer/verbs_menu.action_manually_changed: + $mouse_layer/verbs_menu.set_by_name("walk") + + + # This code is commented to demonstrate how to implement a simple unhover + # behaviour on an item. + #if targeted_node != null: + #targeted_node.modulate = Color.WHITE + +## ITEMS ## +func left_click_on_item(item_global_id: String, event: InputEvent) -> void: + var target_obj = escoria.object_manager.get_object(item_global_id).node + + # current_action will be empty if an event completes between when you stop + # moving the mouse and when you click. + if escoria.action_manager.current_action == "": + if target_obj is ESCItem: + $mouse_layer/verbs_menu.set_by_name( + target_obj.default_action + ) + + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) + + $mouse_layer/verbs_menu.clear_tool_texture() + close_inventory() + + +func right_click_on_item(item_global_id: String, event: InputEvent) -> void: + element_focused(item_global_id) + var object = escoria.object_manager.get_object(item_global_id) + if object != null: + $mouse_layer/verbs_menu.set_by_name("look") + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_RIGHT_CLICK, + [item_global_id, event], + true + ) + +func left_double_click_on_item(item_global_id: String, event: InputEvent) -> void: + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [item_global_id, event], + true + ) + + +## INVENTORY ## +func left_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_LEFT_CLICK, + [inventory_item_global_id, event] + ) + + if escoria.action_manager.current_action == VERB_USE: + var object = escoria.object_manager.get_object( + inventory_item_global_id + ) + var item = object.node + if item.has_method("get_sprite") and item.get_sprite().texture: + $mouse_layer/verbs_menu.set_tool_texture( + item.get_sprite().texture + ) + elif item.inventory_item.texture_normal: + $mouse_layer/verbs_menu.set_tool_texture( + item.inventory_item.texture_normal + ) + escoria.action_manager.current_tool = object + + if escoria.action_manager.current_target != null: + $mouse_layer/verbs_menu.clear_tool_texture() + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + +func right_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: + element_focused(inventory_item_global_id) + var object = escoria.object_manager.get_object(inventory_item_global_id) + if object != null: + escoria.action_manager.set_current_action("look") + escoria.action_manager.do( + escoria.action_manager.ACTION.ITEM_RIGHT_CLICK, + [inventory_item_global_id, event], + true + ) + + +func left_double_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void: + pass + + +func inventory_item_focused(inventory_item_global_id: String) -> void: + if not $mouse_layer/verbs_menu.action_manually_changed: + var item_node: ESCItem = escoria.object_manager.get_object( + inventory_item_global_id + ).node + $ui/tooltip.set_target(item_node.tooltip_name) + $mouse_layer/verbs_menu.set_by_name(item_node.default_action_inventory) + + +func inventory_item_unfocused() -> void: + $ui/tooltip.clear() + if escoria.action_manager.current_action == VERB_WALK: + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + if $mouse_layer/verbs_menu.action_manually_changed: + $mouse_layer/verbs_menu.action_manually_changed = false + elif not $mouse_layer/verbs_menu.action_manually_changed \ + and escoria.action_manager.current_tool == null: + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + + +func open_inventory(): + $ui/inventory_ui.show_inventory() + + +func close_inventory(): + $ui/inventory_ui.hide_inventory() + + +func mousewheel_action(direction: int): + $mouse_layer/verbs_menu.iterate_actions_cursor(direction) + + +func hide_ui(): + $ui/inventory_ui.propagate_call("set_visible", [false], true) + $ui/tooltip.propagate_call("set_visible", [false], true) + $ui/HBoxContainer/VBoxContainer.visible = false + $ui/HBoxContainer/VBoxContainer/MenuButton.visible = false + + +func show_ui(): + $ui/inventory_ui.propagate_call("set_visible", [true], true) + $ui/tooltip.propagate_call("set_visible", [true], true) + $ui/HBoxContainer/VBoxContainer.visible = true + $ui/HBoxContainer/VBoxContainer/MenuButton.visible = true + + +func hide_main_menu(): + show_ui() + escoria.current_state = escoria.GAME_STATE.DEFAULT + if get_node(main_menu).visible: + get_node(main_menu).hide() + +func show_main_menu(): + if escoria.current_state == escoria.GAME_STATE.PAUSED: + return + escoria.current_state = escoria.GAME_STATE.PAUSED + hide_ui() + if not get_node(main_menu).visible: + get_node(main_menu).reset() + get_node(main_menu).show() + +func unpause_game(): + show_ui() + escoria.current_state = escoria.GAME_STATE.DEFAULT + if get_node(pause_menu).visible: + get_node(pause_menu).hide() + escoria.object_manager.get_object(ESCObjectManager.SPEECH).node.resume() + escoria.main.current_scene.game.show_ui() + escoria.main.current_scene.show() + escoria.set_game_paused(false) + +func pause_game(): + if escoria.current_state == escoria.GAME_STATE.PAUSED: + return + show_ui() + escoria.current_state = escoria.GAME_STATE.PAUSED + if not get_node(pause_menu).visible: + get_node(main_menu).reset() + get_node(pause_menu).reset() + get_node(pause_menu).set_save_enabled( + escoria.save_manager.save_enabled + ) + get_node(pause_menu).show() + escoria.object_manager.get_object(ESCObjectManager.SPEECH).node.pause() + escoria.main.current_scene.game.hide_ui() + escoria.main.current_scene.hide() + escoria.set_game_paused(true) + + +func apply_custom_settings(custom_settings: Dictionary): + if custom_settings.has("a_custom_setting"): + escoria.logger.info( + self, + "custom setting value loaded: %s." + % str(custom_settings["a_custom_setting"]) + ) + + +func get_custom_data() -> Dictionary: + return { + "ui_type": "simplemouse" + } + + +# Update the tooltip +func update_tooltip_following_mouse_position(): + _current_mouse_pos = get_viewport().get_mouse_position() + var corrected_position = _current_mouse_pos \ + + Vector2(32, -tooltip_node.size.y/2) + + # clamp TOP + if tooltip_node.tooltip_distance_to_edge_top(_current_mouse_pos) <= mouse_tooltip_margin: + corrected_position.y = mouse_tooltip_margin + + # clamp BOTTOM + if tooltip_node.tooltip_distance_to_edge_bottom(_current_mouse_pos + tooltip_node.size) <= mouse_tooltip_margin: + corrected_position.y = escoria.game_size.y - mouse_tooltip_margin - tooltip_node.size.y + + # clamp LEFT + if tooltip_node.tooltip_distance_to_edge_left(_current_mouse_pos - tooltip_node.size/2) <= mouse_tooltip_margin: + corrected_position.x = mouse_tooltip_margin + + # clamp RIGHT + if tooltip_node.tooltip_distance_to_edge_right(_current_mouse_pos + tooltip_node.size/2) <= mouse_tooltip_margin: + corrected_position.x = escoria.game_size.x - mouse_tooltip_margin - tooltip_node.size.x + + tooltip_node.position = corrected_position + tooltip_node.offset_from_cursor + + +func _on_action_finished(): + $mouse_layer/verbs_menu.clear_tool_texture() + $mouse_layer/verbs_menu.iterate_actions_cursor(0) + + +func _on_event_done(_return_code: int, _event_name: String): + if _return_code == ESCExecution.RC_OK: + escoria.action_manager.clear_current_action() + $ui/tooltip.set_target("") + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + + +func _on_room_ready(): + $mouse_layer/verbs_menu.set_by_name(VERB_WALK) + $mouse_layer/verbs_menu.action_manually_changed = false |
