diff --git a/addons/escoria-core/game/esc_inputs_manager.gd b/addons/escoria-core/game/esc_inputs_manager.gd index c24588eb..b4b8a85d 100644 --- a/addons/escoria-core/game/esc_inputs_manager.gd +++ b/addons/escoria-core/game/esc_inputs_manager.gd @@ -3,6 +3,9 @@ extends Resource class_name ESCInputsManager +## Emitted when input mode changes. +signal input_mode_changed(new_mode) + ## Valid input flags.[br] ## INPUT_ALL: All input is allowed.[br] ## INPUT_NONE: No input is allowed at all.[br] @@ -22,7 +25,12 @@ const ESC_SHOW_DEBUG_PROMPT = "esc_show_debug_prompt" const ESC_UI_PRIMARY_ACTION = "esc_ui_primary_action" ## The current input mode. -var input_mode = INPUT_ALL +var input_mode = INPUT_ALL: + get: + return input_mode + set(new_mode): + input_mode = new_mode + input_mode_changed.emit(new_mode) ## A LIFO stack of hovered items. var hover_stack: HoverStack @@ -46,12 +54,14 @@ var custom_input_handler = null ## The currently hovered element. Usually the one on top of the hover stack. var _hovered_element = null + ## Constructor. func _init(): escoria.event_manager.connect("event_finished", Callable(self, "_on_event_finished")) hover_stack = HoverStack.new() hover_stack.connect("hover_stack_changed", Callable(self, "_on_hover_stack_changed")) + ## Called when an event is finished, so that the current hotspot is reset.[br] ## [br] ## #### Parameters[br] @@ -62,10 +72,12 @@ func _on_event_finished(return_code: int, event_name: String): if _hovered_element == null: hotspot_focused = "" + ## Register core signals (from escoria.gd). func register_core(): escoria.game_scene.request_pause_menu.connect(_on_pause_menu_requested) + ## Connect the item signals to the local methods.[br] ## [br] ## #### Parameters[br] @@ -78,6 +90,7 @@ func register_inventory_item(item: Node): item.inventory_item_focused.connect(_on_mouse_entered_inventory_item) item.inventory_item_unfocused.connect(_on_mouse_exited_inventory_item) + ## Connect background signals to local methods.[br] ## [br] ## #### Parameters[br] @@ -103,7 +116,7 @@ func register_background(background: ESCBackground): ## - is_default_state: Whether the current state is escoria.GAME_STATE.DEFAULT[br] ## - returns whether the function processed the event[br] ##[br] -## `callback` is responsible for calling `get_tree().set_input_as_handled()`, +## `callback` is responsible for calling `get_tree().set_input_as_handled()`, ## if appropriate.[br] ##[br] ## #### Parameters[br] @@ -111,6 +124,7 @@ func register_background(background: ESCBackground): func register_custom_input_handler(callback) -> void: custom_input_handler = callback + ## If a callback was specified via register_custom_input_handler(),[br] ## forwards the event to the callback and returns its result; otherwise,[br] ## returns false.[br] @@ -127,6 +141,7 @@ func try_custom_input_handler(event: InputEvent, is_default_state: bool) -> bool else: return false + ## Callback called by hover stack content change. func _on_hover_stack_changed(): if hover_stack.is_empty(): @@ -134,6 +149,7 @@ func _on_hover_stack_changed(): else: set_hovered_node(hover_stack.get_top_item()) + ## Sets the hovered node and calls its mouse_entered() method if it was the top[br] ## most item in hover_stack.[br] ## [br] @@ -143,17 +159,20 @@ func _on_hover_stack_changed(): ## [br] ## *Returns* True if item is the new top hovered object.[br] func set_hovered_node(item: ESCItem) -> bool: - if _hovered_element != item \ - and escoria.action_manager.is_object_actionable(item.global_id) \ - or (item is ESCPlayer and not (item as ESCPlayer).selectable): + if ( + _hovered_element != item and escoria.action_manager.is_object_actionable(item.global_id) + or (item is ESCPlayer and not (item as ESCPlayer).selectable) + ): _hovered_element = item _hovered_element.mouse_entered() return true # If tested item was already hovered # or is not actionable (not selectable for ESCPlayer) then do nothing - if _hovered_element == item \ - or not escoria.action_manager.is_object_actionable(item.global_id) \ - or (item is ESCPlayer and not (item as ESCPlayer).selectable): + if ( + _hovered_element == item + or not escoria.action_manager.is_object_actionable(item.global_id) + or (item is ESCPlayer and not (item as ESCPlayer).selectable) + ): return true if not is_instance_valid(_hovered_element) or hover_stack.get_top_item() != item: _hovered_element = item @@ -163,6 +182,7 @@ func set_hovered_node(item: ESCItem) -> bool: else: return false + ## Unsets the hovered node.[br] ## [br] ## #### Parameters[br] @@ -176,10 +196,12 @@ func unset_hovered_node(item: ESCItem): _hovered_element = null hotspot_focused = "" + ## Background was hovered. func _on_hover_bg() -> void: escoria.main.current_scene.game.hovered_bg() + ## The background was clicked with the LMB.[br] ## [br] ## #### Parameters[br] @@ -188,12 +210,10 @@ func _on_hover_bg() -> void: func _on_left_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL: hotspot_focused = "" - escoria.logger.info( - self, - "Left click on background at %s." % str(position) - ) + escoria.logger.info(self, "Left click on background at %s." % str(position)) escoria.main.current_scene.game.left_click_on_bg(position) + ## The background was double-clicked with the LMB.[br] ## [br] ## #### Parameters[br] @@ -202,12 +222,10 @@ func _on_left_click_on_bg(position: Vector2) -> void: func _on_double_left_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL: hotspot_focused = "" - escoria.logger.info( - self, - "Double left click on background at %s." % str(position) - ) + escoria.logger.info(self, "Double left click on background at %s." % str(position)) escoria.main.current_scene.game.left_double_click_on_bg(position) + ## The background was clicked with the RMB.[br] ## [br] ## #### Parameters[br] @@ -215,12 +233,10 @@ func _on_double_left_click_on_bg(position: Vector2) -> void: ## - position: Position of the click. func _on_right_click_on_bg(position: Vector2) -> void: if input_mode == INPUT_ALL and hotspot_focused.is_empty(): - escoria.logger.info( - self, - "Right click on background at %s." % str(position) - ) + escoria.logger.info(self, "Right click on background at %s." % str(position)) escoria.main.current_scene.game.right_click_on_bg(position) + ## An inventory item was clicked with the LMB.[br] ## [br] ## #### Parameters[br] @@ -228,17 +244,11 @@ func _on_right_click_on_bg(position: Vector2) -> void: ## - inventory_item_global_id: The global id of the clicked inventory item.[br] ## - event: The input event received. func _on_mouse_left_click_inventory_item( - inventory_item_global_id: String, - event: InputEvent + inventory_item_global_id: String, event: InputEvent ) -> void: - escoria.logger.info( - self, - "Inventory item %s left clicked." % inventory_item_global_id - ) - escoria.main.current_scene.game.left_click_on_inventory_item( - inventory_item_global_id, - event - ) + escoria.logger.info(self, "Inventory item %s left clicked." % inventory_item_global_id) + escoria.main.current_scene.game.left_click_on_inventory_item(inventory_item_global_id, event) + ## An inventory item was clicked with the RMB.[br] ## [br] @@ -247,19 +257,15 @@ func _on_mouse_left_click_inventory_item( ## - inventory_item_global_id: The global id of the clicked inventory item.[br] ## - event: The input event received. func _on_mouse_right_click_inventory_item( - inventory_item_global_id: String, - event: InputEvent + inventory_item_global_id: String, event: InputEvent ) -> void: if input_mode == INPUT_ALL: - escoria.logger.info( - self, - "Inventory item %s right clicked." % inventory_item_global_id - ) + escoria.logger.info(self, "Inventory item %s right clicked." % inventory_item_global_id) escoria.main.current_scene.game.right_click_on_inventory_item( - inventory_item_global_id, - event + inventory_item_global_id, event ) + ## An inventory item was double-clicked with the LMB.[br] ## [br] ## #### Parameters[br] @@ -267,41 +273,33 @@ func _on_mouse_right_click_inventory_item( ## - inventory_item_global_id: The global id of the clicked inventory item.[br] ## - event: The input event received. func _on_mouse_double_left_click_inventory_item( - inventory_item_global_id: String, - event: InputEvent + inventory_item_global_id: String, event: InputEvent ) -> void: if input_mode == INPUT_ALL: escoria.logger.info( - self, - "Inventory item %s double left clicked." % inventory_item_global_id + self, "Inventory item %s double left clicked." % inventory_item_global_id ) escoria.main.current_scene.game.left_double_click_on_inventory_item( - inventory_item_global_id, - event + inventory_item_global_id, event ) + ## The mouse entered an inventory item.[br] ## [br] ## #### Parameters[br] ## [br] ## - inventory_item_global_id: The global id of the inventory item that is hovered. func _on_mouse_entered_inventory_item(inventory_item_global_id: String) -> void: - escoria.logger.info( - self, - "Inventory item %s focused." % inventory_item_global_id - ) - escoria.main.current_scene.game.inventory_item_focused( - inventory_item_global_id - ) + escoria.logger.info(self, "Inventory item %s focused." % inventory_item_global_id) + escoria.main.current_scene.game.inventory_item_focused(inventory_item_global_id) + ## The mouse exited an inventory item. func _on_mouse_exited_inventory_item() -> void: - escoria.logger.info( - self, - "Inventory item unfocused." - ) + escoria.logger.info(self, "Inventory item unfocused.") escoria.main.current_scene.game.inventory_item_unfocused() + ## The mouse entered an Escoria item.[br] ## [br] ## #### Parameters[br] @@ -310,8 +308,7 @@ func _on_mouse_exited_inventory_item() -> void: func _on_mouse_entered_item(item: ESCItem) -> void: if item as ESCPlayer and not (item as ESCPlayer).selectable: escoria.logger.trace( - self, - "Ignoring mouse entering player %s: Player not selectable." % [item.global_id] + self, "Ignoring mouse entering player %s: Player not selectable." % [item.global_id] ) if hover_stack.is_empty(): hotspot_focused = "" @@ -322,20 +319,15 @@ func _on_mouse_entered_item(item: ESCItem) -> void: return if not escoria.action_manager.is_object_actionable(item.global_id): - escoria.logger.debug( - self, - "Ignoring mouse entering item %s." % [item.global_id] - ) + escoria.logger.debug(self, "Ignoring mouse entering item %s." % [item.global_id]) return - escoria.logger.info( - self, - "Item focused: %s" % item.global_id - ) + escoria.logger.info(self, "Item focused: %s" % item.global_id) hotspot_focused = item.global_id escoria.main.current_scene.game.element_focused(item.global_id) + ## The mouse exited an Escoria item.[br] ## [br] ## #### Parameters[br] @@ -350,14 +342,16 @@ func _on_mouse_exited_item(item: ESCItem) -> void: if object and not object.interactive: return - if object and is_instance_valid(object.node) and object.node is ESCPlayer and not (object.node as ESCPlayer).selectable: + if ( + object + and is_instance_valid(object.node) + and object.node is ESCPlayer + and not (object.node as ESCPlayer).selectable + ): hotspot_focused = "" return - escoria.logger.info( - self, - "Item unfocused: %s" % hotspot_focused - ) + escoria.logger.info(self, "Item unfocused: %s" % hotspot_focused) if hover_stack.is_empty(): hotspot_focused = "" @@ -366,6 +360,7 @@ func _on_mouse_exited_item(item: ESCItem) -> void: hotspot_focused = hover_stack.get_top_item().global_id escoria.main.current_scene.game.element_focused(hotspot_focused) + ## Function called when the item is set interactive, to re-trigger an input on[br] ## underlying item.[br] ## [br] @@ -382,9 +377,12 @@ func on_item_non_interactive(item: ESCItem) -> void: return else: var new_item = hover_stack.get_top_item() - escoria.action_manager.set_action_input_state(ESCActionManager.ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM) + escoria.action_manager.set_action_input_state( + ESCActionManager.ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM + ) new_item.mouse_entered() + ## An Escoria item was clicked with the LMB.[br] ## [br] ## #### Parameters[br] @@ -396,34 +394,32 @@ func _on_mouse_left_clicked_item(item: ESCItem, event: InputEvent) -> void: # Manage clicking through ESCPlayer (if ESCPlayer.selectable is false) if item as ESCPlayer and not (item as ESCPlayer).selectable: escoria.logger.trace( - self, - "Ignoring left click on player %s: Player not selectable." - % [item.global_id] + self, "Ignoring left click on player %s: Player not selectable." % [item.global_id] ) # Get next object in hover stack and forward event to it if not hover_stack.is_empty(): var next_item = hover_stack.pop_top_item() _on_mouse_left_clicked_item(next_item, event) - else: # if no next object, consider this click as background click + else: # if no next object, consider this click as background click hotspot_focused = "" _on_left_click_on_bg(event.position) return # Clicked object can't be actioned and there is no other object behind # We consider this click as a background click - if not escoria.action_manager.is_object_actionable(item.global_id) \ - and hover_stack.is_empty(): + if ( + not escoria.action_manager.is_object_actionable(item.global_id) + and hover_stack.is_empty() + ): hotspot_focused = "" _on_left_click_on_bg(event.position) return # Finally, execute the action on the ESCItem hotspot_focused = item.global_id - escoria.main.current_scene.game.left_click_on_item( - item.global_id, - event - ) + escoria.main.current_scene.game.left_click_on_item(item.global_id, event) + ## An Escoria item was double-clicked with the LMB.[br] ## [br] @@ -431,42 +427,38 @@ func _on_mouse_left_clicked_item(item: ESCItem, event: InputEvent) -> void: ## [br] ## - item: The Escoria item clicked.[br] ## - event: The input event from the click. -func _on_mouse_left_double_clicked_item( - item: ESCItem, - event: InputEvent -) -> void: +func _on_mouse_left_double_clicked_item(item: ESCItem, event: InputEvent) -> void: if input_mode == INPUT_ALL: # Manage clicking through ESCPlayer (if ESCPlayer.selectable is false) if item as ESCPlayer and not (item as ESCPlayer).selectable: escoria.logger.trace( self, - "Ignoring double left click on player %s: Player not selectable." - % [item.global_id] + "Ignoring double left click on player %s: Player not selectable." % [item.global_id] ) # Get next object in hover stack and forward event to it if not hover_stack.is_empty(): var next_item = hover_stack.pop_top_item() _on_mouse_left_double_clicked_item(next_item, event) - else: # if no next object, consider this click as background click + else: # if no next object, consider this click as background click hotspot_focused = "" _on_double_left_click_on_bg(event.position) return # Clicked object can't be actioned and there is no other object behind # We consider this click as a background click - if not escoria.action_manager.is_object_actionable(item.global_id) \ - and hover_stack.is_empty(): + if ( + not escoria.action_manager.is_object_actionable(item.global_id) + and hover_stack.is_empty() + ): hotspot_focused = "" _on_double_left_click_on_bg(event.position) return # Finally, execute the action on the ESCItem hotspot_focused = item.global_id - escoria.main.current_scene.game.left_double_click_on_item( - item.global_id, - event - ) + escoria.main.current_scene.game.left_double_click_on_item(item.global_id, event) + ## An Escoria item was clicked with the RMB.[br] ## [br] @@ -478,8 +470,7 @@ func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void: if input_mode == INPUT_ALL: if item as ESCPlayer and not (item as ESCPlayer).selectable: escoria.logger.debug( - self, - "Ignoring right click on player %s: Player not selectable." % [item.global_id] + self, "Ignoring right click on player %s: Player not selectable." % [item.global_id] ) if not hover_stack.is_empty(): @@ -487,9 +478,11 @@ func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void: _on_mouse_right_clicked_item(next_item, event) return - if not escoria.action_manager.is_object_actionable(item.global_id) \ - and hover_stack.is_empty(): - # Treat this as a background click now + if ( + not escoria.action_manager.is_object_actionable(item.global_id) + and hover_stack.is_empty() + ): + # Treat this as a background click now hotspot_focused = "" _on_right_click_on_bg(event.position) return @@ -508,22 +501,27 @@ func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void: if event.position: (escoria.main.current_scene.game as ESCGame).right_click_on_bg(event.position) else: - escoria.logger.info( - self, - "Clicked item %s with event %s cannot be activated (player not selectable or not interactive).\n" - % [item.global_id, event] + - "No valid item found in the items stack. Action canceled." + ( + escoria + . logger + . info( + self, + ( + ( + "Clicked item %s with event %s cannot be activated (player not selectable or not interactive).\n" + % [item.global_id, event] + ) + + "No valid item found in the items stack. Action canceled." + ) + ) ) else: escoria.logger.info( - self, - "Item %s right clicked with event %s." % [actual_item.global_id, event] + self, "Item %s right clicked with event %s." % [actual_item.global_id, event] ) hotspot_focused = actual_item.global_id - escoria.main.current_scene.game.right_click_on_item( - actual_item.global_id, - event - ) + escoria.main.current_scene.game.right_click_on_item(actual_item.global_id, event) + ## The mousewheel was turned.[br] ## [br] @@ -533,13 +531,14 @@ func _on_mouse_right_clicked_item(item: ESCItem, event: InputEvent) -> void: func _on_mousewheel_action(direction: int): escoria.main.current_scene.game.mousewheel_action(direction) + ## Event when the pause menu was requested. func _on_pause_menu_requested(): escoria.main.current_scene.game.pause_game() + ## Hover Stack implementation. class HoverStack: - ## Emitted when the content of the hover stack has changed. signal hover_stack_changed @@ -562,7 +561,6 @@ class HoverStack: _sort() hover_stack_changed.emit() - ## Add the items contained in given list to the stack if not already in it.[br] ## [br] ## #### Parameters[br] @@ -573,7 +571,6 @@ class HoverStack: if escoria.action_manager.is_object_actionable(item.global_id): add_item(item) - ## Clean the hover stack. func clean(): for e in hover_stack: @@ -581,7 +578,6 @@ class HoverStack: hover_stack.erase(e) hover_stack_changed.emit() - ## Pops the top element of the hover stack and returns it.[br] ## [br] ## *Returns* The top element of the hover stack. @@ -591,14 +587,12 @@ class HoverStack: hover_stack_changed.emit() return ret - ## Returns the top element of the hover stack.[br] ## [br] ## *Returns* The top element of the hover stack. func get_top_item(): return hover_stack.back() - ## Remove the given item from the stack.[br] ## [br] ## #### Parameters[br] @@ -610,25 +604,21 @@ class HoverStack: _sort() hover_stack_changed.emit() - ## Clear the stack of hovered items. func clear(): hover_stack = [] hover_stack_emptied.emit() - ## Returns true if the hover stack is empty, else false.[br] ## [br] ## *Returns* True if hover stack is empty, else false. func is_empty() -> bool: return hover_stack.is_empty() - ## Sort the hover stack by items' z-index. func _sort(): hover_stack.sort_custom(Callable(HoverStackSorter, "sort_ascending_z_index")) - ## Returns true if the hover stack contains the given item.[br] ## [br] ## #### Parameters[br] @@ -639,7 +629,6 @@ class HoverStack: func has(item) -> bool: return hover_stack.has(item) - ## Returns the hover stack array. ## [br] ## *Returns* The hover stack array.