1
Fork 0
mirror of https://github.com/Steffo99/swear-jar.git synced 2024-11-25 09:04:19 +00:00
swear-jar/interface/ghost.gd

122 lines
3.9 KiB
GDScript3
Raw Normal View History

2023-10-02 13:12:08 +00:00
extends Area2D
class_name Ghost
2023-10-02 15:53:13 +00:00
## Ghost previewing the instantiation of a scene.
2023-10-02 13:12:08 +00:00
2023-10-02 15:53:13 +00:00
## The [CollisionShape2D] to use to check for placement checks.
##
## MUST consist of a [RectangleShape2D].
@onready var placement_shape: CollisionShape2D = $PlacementShape
2023-10-02 14:22:03 +00:00
2023-10-02 15:53:13 +00:00
## The [Sprite2D] node previewing the scene.
@onready var preview_sprite: Sprite2D = $PlacementShape/PreviewSprite
2023-10-02 14:22:03 +00:00
2023-10-02 16:29:05 +00:00
## The collision mask of objects that should prevent this object's placement.
@export_flags_2d_physics var collision_mask_prevent_placement: int
## The collision mask of objects that should be deleted on this object's placement.
@export_flags_2d_physics var collision_mask_delete_placement: int
2023-10-02 15:53:13 +00:00
## The texture that the preview sprite should display.
@export var preview_texture: Texture2D:
get:
return preview_texture
set(value):
preview_texture = value
2023-10-02 16:29:05 +00:00
# Quick priority fix
if preview_sprite:
preview_sprite.texture = value
2023-10-02 14:22:03 +00:00
2023-10-02 15:53:13 +00:00
## Whether the ghost can be placed at the current location of the ghost.
##
## Computed by checking if [placement_shape] overlaps any entity and is inside the [PlacementArea] of the [Bottle].
var can_place: bool:
2023-10-02 14:22:03 +00:00
get:
return can_place
set(value):
2023-10-02 18:28:08 +00:00
can_place = value
2023-10-02 14:22:03 +00:00
if value:
2023-10-02 15:53:13 +00:00
preview_sprite.modulate = Color(1.0, 1.0, 1.0, 0.5)
2023-10-02 14:22:03 +00:00
else:
2023-10-02 15:53:13 +00:00
preview_sprite.modulate = Color(1.0, 0.0, 0.0, 0.5)
## The last input event of the input that's dragging the ghost around, or null if the ghost isn't being dragged.
var last_input_event: InputEvent
2023-10-02 16:29:05 +00:00
func _ready():
collision_mask = collision_mask_prevent_placement | collision_mask_delete_placement
preview_sprite.texture = preview_texture
2023-10-02 15:53:13 +00:00
func _input(event: InputEvent):
# Handle mouse click
if event is InputEventMouseButton:
last_input_event = event if event.pressed else null
# Handle touch begin
elif event is InputEventScreenTouch:
2023-10-02 21:56:28 +00:00
last_input_event = event if event.pressed else null
2023-10-02 15:53:13 +00:00
# If is dragging
2023-10-02 19:25:11 +00:00
elif last_input_event:
2023-10-02 15:53:13 +00:00
# Handle mouse drag
if last_input_event is InputEventMouse and event is InputEventMouse:
var delta = event.position - last_input_event.position
position += delta
last_input_event = event
# Handle touch drag
elif (last_input_event is InputEventScreenTouch or last_input_event is InputEventScreenDrag) and event is InputEventScreenDrag:
if event.index == last_input_event.index:
var delta = event.position - last_input_event.position
position += delta
last_input_event = event
2023-10-02 18:28:08 +00:00
## Update the value of [can_place].
2023-10-02 16:29:05 +00:00
# DIRTY HACK: Relies on the placeable area being perfectly surrounded by solid bodies.
2023-10-02 18:28:08 +00:00
func update_can_place():
2023-10-02 16:29:05 +00:00
var no_overlapping_bodies: bool = true
2023-10-02 15:53:13 +00:00
var overlapping_bodies = get_overlapping_bodies()
2023-10-02 16:29:05 +00:00
for body in overlapping_bodies:
if body is TileMap:
no_overlapping_bodies = false
elif body is PhysicsBody2D:
var body_prevents_placement = bool(body.collision_layer & collision_mask_prevent_placement)
no_overlapping_bodies = no_overlapping_bodies and not body_prevents_placement
2023-10-02 14:22:03 +00:00
2023-10-02 16:29:05 +00:00
var is_in_placeable_area: bool = false
2023-10-02 15:53:13 +00:00
var overlapping_areas = get_overlapping_areas()
for area in overlapping_areas:
2023-10-02 16:29:05 +00:00
if area is PlaceableArea:
is_in_placeable_area = true
can_place = no_overlapping_bodies and is_in_placeable_area
## The [PackedScene] that this node should instantiate.
@export var scene_to_instantiate: PackedScene
## The [Node] instatiated scenes should be added as children to.
@export var target: Node
## Emitted when the [materialize] function has finished executing.
signal materialized(node: Node)
2023-10-02 18:28:08 +00:00
func _physics_process(_delta: float):
update_can_place()
2023-10-02 16:29:05 +00:00
func materialize():
2023-10-02 18:28:08 +00:00
if not can_place:
return null
var overlapping_bodies = get_overlapping_bodies()
for body in overlapping_bodies:
if body is PhysicsBody2D:
if body.collision_layer & collision_mask_delete_placement:
body.queue_free()
2023-10-02 16:29:05 +00:00
var instantiated = scene_to_instantiate.instantiate()
instantiated.global_position = global_position
instantiated.rotation = rotation
target.add_child(instantiated)
materialized.emit(instantiated)
2023-10-02 17:49:55 +00:00
return instantiated