From d78f353431ea78ab0a339f8d602ec9942cc36167 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 13 Oct 2023 19:21:07 +0200 Subject: [PATCH] Complete `Ghost` refactor --- game/game.gd | 1 + interface/ghost/ghost.gd | 20 ++++++++++-- interface/ghost/ghost.tscn | 10 ++++-- interface/ghost/overlap_checker.gd | 1 + interface/ghost/placeable_area_checker.gd | 1 + interface/ghost/precise_touch_placer.gd | 15 ++++++++- interface/purchasable_item.gd | 12 +++---- interface/score_ui.gd | 10 ++++++ interface/shop_ui.gd | 38 ++++++++++++----------- main.tscn | 3 +- 10 files changed, 79 insertions(+), 32 deletions(-) diff --git a/game/game.gd b/game/game.gd index 696d604..ef9f3ce 100644 --- a/game/game.gd +++ b/game/game.gd @@ -89,6 +89,7 @@ func update_counter_icon(): store_collector_texturerect.texture = null func _on_ghost_requested(item: PurchasableItem): + print("[Game] Requested ghost for: ", item) ghost.COMPAT_set_to_purchasable_item(item) ghost.process_mode = Node.PROCESS_MODE_INHERIT ghost.show() diff --git a/interface/ghost/ghost.gd b/interface/ghost/ghost.gd index 2c407c9..2430625 100644 --- a/interface/ghost/ghost.gd +++ b/interface/ghost/ghost.gd @@ -57,17 +57,23 @@ func _ready(): ## Update the value of [can_place]. func update_state(): + overlap_checker.update_is_overlapping_with() + placeable_area_checker.update_is_overlapping_with() # DIRTY HACK: Relies on the placeable area being perfectly surrounded by solid bodies. can_place = overlap_checker.is_overlapping_with == null and placeable_area_checker.is_overlapping_with != null ## For retro-compatibility, configure this for the placement of a [PurchasableItem]. func COMPAT_set_to_purchasable_item(pi: PurchasableItem): + push_warning("COMPAT_set_to_purchasable_item is deprecated.") instantiator.scene_to_instantiate = pi.item_scene - placement_shape.shape = pi.get_node("ConverterPlacementBody").get_node("FullConverterShape").shape - placement_shape.scale = pi.item_scene.scale + var item_scene = pi.item_scene.instantiate() + placement_shape.shape = item_scene.get_node("ConverterPlacementBody/FullConverterShape").shape + placement_shape.scale = item_scene.scale + item_scene.queue_free() preview_sprite.texture = pi.item_icon position = starting_position rotation = starting_rotation_radians + update_state() ## Configure this for the placement of a [ShopItem]. @@ -78,6 +84,7 @@ func set_to_shop_item(si: ShopItem): preview_sprite.texture = si.placement_texture position = starting_position rotation = starting_rotation_radians + update_state() ## Emitted when [materialize] is called. signal materialized(what: Node) @@ -88,7 +95,16 @@ signal materialized(what: Node) func materialize() -> Node: if not can_place: return null + overlap_freer.update_is_overlapping_with() overlap_freer.area_queue_free() var inst = instantiator.instantiate() materialized.emit(inst) return inst + + +func _on_moved(_from, _to): + update_state() + + +func _on_rotated_radians(_from, _to): + update_state() diff --git a/interface/ghost/ghost.tscn b/interface/ghost/ghost.tscn index dbb4e25..aa95989 100644 --- a/interface/ghost/ghost.tscn +++ b/interface/ghost/ghost.tscn @@ -26,13 +26,17 @@ z_index = 10 [node name="Instantiator" parent="." instance=ExtResource("4_f7fmh")] [node name="OverlapChecker" parent="." instance=ExtResource("5_twds7")] - -[node name="OverlapFreer" parent="." instance=ExtResource("6_y1rxa")] +overlap_mask = 8 [node name="PlaceableAreaChecker" parent="." instance=ExtResource("7_wemqm")] +overlap_mask = 16 + +[node name="OverlapFreer" parent="." instance=ExtResource("6_y1rxa")] +overlap_mask = 4 [connection signal="area_entered" from="." to="PlaceableAreaChecker" method="update_is_overlapping_with"] [connection signal="area_exited" from="." to="PlaceableAreaChecker" method="update_is_overlapping_with"] [connection signal="body_entered" from="." to="OverlapChecker" method="update_is_overlapping_with"] [connection signal="body_exited" from="." to="OverlapChecker" method="update_is_overlapping_with"] -[connection signal="overlap_changing" from="OverlapChecker" to="." method="update_state"] +[connection signal="moved" from="PreciseTouchPlacer" to="." method="_on_moved"] +[connection signal="rotated_radians" from="PreciseTouchPlacer" to="." method="_on_rotated_radians"] diff --git a/interface/ghost/overlap_checker.gd b/interface/ghost/overlap_checker.gd index c05a8ef..f735995 100644 --- a/interface/ghost/overlap_checker.gd +++ b/interface/ghost/overlap_checker.gd @@ -34,6 +34,7 @@ func get_first_overlapping_body() -> Node2D: func update_is_overlapping_with() -> void: var current_overlap = get_first_overlapping_body() if current_overlap != is_overlapping_with: + print("[OverlapChecker] Now overlapping with: ", current_overlap) overlap_changing.emit(current_overlap) is_overlapping_with = current_overlap diff --git a/interface/ghost/placeable_area_checker.gd b/interface/ghost/placeable_area_checker.gd index f06d750..f318da4 100644 --- a/interface/ghost/placeable_area_checker.gd +++ b/interface/ghost/placeable_area_checker.gd @@ -29,5 +29,6 @@ signal overlap_changing(to: PlaceableArea) func update_is_overlapping_with() -> void: var current_overlap = get_first_overlapping_placeable_area() if current_overlap != is_overlapping_with: + print("[PlaceableAreaChecker] Now overlapping with: ", current_overlap) overlap_changing.emit(current_overlap) is_overlapping_with = current_overlap diff --git a/interface/ghost/precise_touch_placer.gd b/interface/ghost/precise_touch_placer.gd index de0e8e3..9264333 100644 --- a/interface/ghost/precise_touch_placer.gd +++ b/interface/ghost/precise_touch_placer.gd @@ -26,6 +26,10 @@ var last_touch_events: Array[InputEvent] = [ ] +signal moved(from: Vector2, to: Vector2) +signal rotated_radians(from: float, to: float) + + ## Count the number of non-[null] [last_touch_events]. func count_active_touch_events() -> int: var total = 0 @@ -43,12 +47,18 @@ func _input(event: InputEvent): if count == 0: # Mouse drag if event is InputEventMouseMotion and last_mouse_event: + var from = target.position target.position += event.relative + var to = target.position + moved.emit(from, to) # Touch drag elif count == 1: # Touch drag if event is InputEventScreenDrag: + var from = target.position target.position += event.relative + var to = target.position + moved.emit(from, to) # Handle rotation elif count == 2: # Find the previous event @@ -77,7 +87,10 @@ func _input(event: InputEvent): # Find the angle between the two vectors var rotation_radians = previous_vec.angle_to(current_vec) # Apply the rotation - target.rotation += rotation_radians + var from = target.rotation + target.rotation += rotation_radians + var to = target.rotation + rotated_radians.emit(from, to) # Store last events if event is InputEventMouseButton: diff --git a/interface/purchasable_item.gd b/interface/purchasable_item.gd index 1d326ab..ac10bd2 100644 --- a/interface/purchasable_item.gd +++ b/interface/purchasable_item.gd @@ -90,25 +90,25 @@ var has_bought: bool: ## Emitted when a purchase has started. -signal purchase_begin(what: PurchasableItem) +signal purchase_begin ## Emitted when a purchase is cancelled. -signal purchase_cancel(what: PurchasableItem) +signal purchase_cancel ## Emitted when a purchase is completed. ## ## Emitted by complete_purchase(). -signal purchase_success(what: PurchasableItem) +signal purchase_success func _on_buy_button_pressed(): if is_buying: is_buying = false - purchase_cancel.emit(self) + purchase_cancel.emit() else: is_buying = true - purchase_begin.emit(self) + purchase_begin.emit() func complete_purchase(): is_buying = false - purchase_success.emit(self) + purchase_success.emit() diff --git a/interface/score_ui.gd b/interface/score_ui.gd index 131effe..b9d8232 100644 --- a/interface/score_ui.gd +++ b/interface/score_ui.gd @@ -10,6 +10,16 @@ class_name ScoreUI @onready var request: HTTPRequest = $SubmissionRequest +@onready var parent: Node = get_parent() + + +func _ready(): + if parent is SafeUI: + parent.process_mode = PROCESS_MODE_DISABLED + else: + process_mode = PROCESS_MODE_DISABLED + + func _on_game_score_changed(total: int): score_button.set_score(total) diff --git a/interface/shop_ui.gd b/interface/shop_ui.gd index 45cf411..2f621d2 100644 --- a/interface/shop_ui.gd +++ b/interface/shop_ui.gd @@ -21,39 +21,41 @@ signal purchase_cancel(what: PurchasableItem) signal purchase_success(what: PurchasableItem) ## Array of all PurchasableItems that this ShopUI should control. -@onready var purchasable_items: Array[Node] = find_children("*", "PurchasableItem") +var purchasable_items: Array[Node] = [] signal ghost_requested(what: PurchasableItem) -func _ready(): - for item in purchasable_items: - item.purchase_begin.connect(_on_any_purchase_begin) - item.purchase_cancel.connect(_on_any_purchase_cancel) - item.purchase_success.connect(_on_any_purchase_success) +@onready var parent: Node = get_parent() -func _on_any_purchase_begin(what: Node): - if not what is PurchasableItem: - push_error("Purchase began outside a PurchasableItem") - return + +func _ready(): + purchasable_items = find_children("*", "PurchasableItem", true, false) + for item in purchasable_items: + item.purchase_begin.connect(_on_any_purchase_begin.bind(item)) + item.purchase_cancel.connect(_on_any_purchase_cancel.bind(item)) + item.purchase_success.connect(_on_any_purchase_success.bind(item)) + if parent is SafeUI: + parent.process_mode = PROCESS_MODE_DISABLED + else: + process_mode = PROCESS_MODE_DISABLED + +func _on_any_purchase_begin(what: PurchasableItem): + print("[ShopUI] Beginning purchase of: ", what) delete_button.disabled = true if what.item_scene: ghost_requested.emit(what) purchase_begin.emit(what) set_all_can_buy(false, what) -func _on_any_purchase_cancel(what: Node): - if not what is PurchasableItem: - push_error("Purchase cancelled outside a PurchasableItem") - return +func _on_any_purchase_cancel(what: PurchasableItem): + print("[ShopUI] Cancelling purchase of: ", what) delete_button.disabled = false purchase_cancel.emit(what) set_all_can_buy(true, what) -func _on_any_purchase_success(what: Node): - if not what is PurchasableItem: - push_error("Purchase succeeded outside a PurchasableItem") - return +func _on_any_purchase_success(what: PurchasableItem): + print("[ShopUI] Succeeded purchase of: ", what) if what.item_scene: ghost_materialize.emit() delete_button.disabled = false diff --git a/main.tscn b/main.tscn index fc5bcee..8266061 100644 --- a/main.tscn +++ b/main.tscn @@ -72,7 +72,7 @@ apply_margin_top = true layout_mode = 2 [node name="ShopSafeUI" parent="CustomUI" instance=ExtResource("5_2uxda")] -process_mode = 4 +process_mode = 3 visible = false layout_mode = 1 apply_margin_left = true @@ -84,7 +84,6 @@ apply_margin_bottom = true layout_mode = 2 [node name="ScoreSafeUI" parent="CustomUI" instance=ExtResource("5_2uxda")] -process_mode = 4 visible = false layout_mode = 1 apply_margin_left = true