diff --git a/Stations/Hob.tscn b/Stations/Hob.tscn index 6cbe246..0e07746 100644 --- a/Stations/Hob.tscn +++ b/Stations/Hob.tscn @@ -47,7 +47,7 @@ properties/2/spawn = true properties/2/replication_mode = 1 [sub_resource type="BoxShape3D" id="BoxShape3D_vlqg6"] -size = Vector3(0.6, 1, 0.6) +size = Vector3(0.5, 1, 0.5) [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vlqg6"] transparency = 1 @@ -247,7 +247,7 @@ script = ExtResource("15_trny8") [node name="MoveGhost" type="Area3D" parent="." unique_id=2098037388] visible = false collision_layer = 0 -collision_mask = 589831 +collision_mask = 524295 [node name="CollisionShape3D" type="CollisionShape3D" parent="MoveGhost" unique_id=486115686] shape = SubResource("BoxShape3D_vlqg6") diff --git a/Stations/station_movement.gd b/Stations/station_movement.gd index 6d50dd7..04a16de 100644 --- a/Stations/station_movement.gd +++ b/Stations/station_movement.gd @@ -7,11 +7,15 @@ extends Node @export var station: StaticBody3D var move_handle_rigid: RigidBody3D -var original_collision_layer -var original_y_pos: float +var original_collision_layer: int = 0 +var original_y_pos: float = 0.0 +var original_station_transform: Transform3D = Transform3D.IDENTITY +var moving: bool = false +var ghost_materials: Array[StandardMaterial3D] = [] + +const GHOST_COLOR_VALID: Color = Color(0, 1, 0, 0.35) +const GHOST_COLOR_INVALID: Color = Color(1, 0, 0, 0.35) -# TODO: Reject placing station in occupied spot. -# TODO: Make ghost version of station that is displayed instead of model. # TODO: public toggle to disable handle in build mode. # TODO: If game exits build mode, drop the handle before disabling it. @@ -19,28 +23,111 @@ var original_y_pos: float func _ready() -> void: if not station: push_error("StationMovement is missing referece to station") - + if not move_handle: + push_error("StationMovement is missing reference to move_handle") + if not move_ghost: + push_error("StationMovement is missing reference to move_ghost") + move_handle_rigid = move_handle as RigidBody3D original_collision_layer = station.collision_layer original_y_pos = move_handle.transform.origin.y + original_station_transform = station.global_transform move_handle.picked_up.connect(_handle_pickup) move_handle.dropped.connect(_handle_drop) + move_ghost.monitoring = true + move_ghost.visible = false + _cache_ghost_materials() + _set_ghost_color(GHOST_COLOR_VALID) -func _handle_pickup(_by): + +func _cache_ghost_materials() -> void: + var combiner = move_ghost.get_node_or_null("CSGCombiner3D") + if not combiner: + return + _collect_ghost_materials(combiner) + + +func _collect_ghost_materials(node: Node) -> void: + if node is CSGCombiner3D: + # Combiner nodes do not expose a material property to modify. + for child in node.get_children(): + _collect_ghost_materials(child) + return + + if node is CSGShape3D: + var material = node.material + if material and material is StandardMaterial3D: + var instance = material.duplicate() as StandardMaterial3D + instance.transparency = material.transparency + instance.albedo_color = material.albedo_color + node.material = instance + ghost_materials.append(instance) + + for child in node.get_children(): + _collect_ghost_materials(child) + + +func _set_ghost_color(color: Color) -> void: + for material in ghost_materials: + material.albedo_color = color + + +func _handle_pickup(_by: Node) -> void: print("StationMovement handle pickup") - station.collision_layer = 0 - - -func _handle_drop(_by): + moving = true + move_ghost.visible = true + station.visible = false + station.collision_layer = 0 + original_station_transform = station.global_transform + move_ghost.global_transform = original_station_transform + + +func _handle_drop(_by: Node) -> void: print("StationMovement handle drop") + moving = false + move_ghost.visible = false + station.visible = true station.collision_layer = original_collision_layer + if _is_move_position_valid(): + station.global_transform = move_ghost.global_transform + else: + station.global_transform = original_station_transform move_handle.global_position = station.global_position + Vector3(0, original_y_pos, 0) move_handle.rotation = station.rotation func _process(_delta: float) -> void: - station.global_position.x = snappedf(move_handle.global_position.x, snap_grid_size) - station.global_position.z = snappedf(move_handle.global_position.z, snap_grid_size) - station.global_rotation_degrees.y = snappedf(move_handle.global_rotation_degrees.y, 90) - + if not moving: + return + + var target_transform: Transform3D = move_handle.global_transform + target_transform.origin.x = snappedf(target_transform.origin.x, snap_grid_size) + target_transform.origin.z = snappedf(target_transform.origin.z, snap_grid_size) + target_transform.origin.y = original_station_transform.origin.y + var target_yaw: float = snappedf(move_handle.global_rotation_degrees.y, 90) + target_transform.basis = Basis(Vector3.UP, deg_to_rad(target_yaw)) + + move_ghost.global_transform = target_transform + if _is_move_position_valid(): + _set_ghost_color(GHOST_COLOR_VALID) + else: + _set_ghost_color(GHOST_COLOR_INVALID) + + +func _is_move_position_valid() -> bool: + for body in move_ghost.get_overlapping_bodies(): + print("Overlapping body: ", body) + if body == move_handle: + continue + if body == station: + continue + return false + + for area in move_ghost.get_overlapping_areas(): + print("Overlapping area: ", area) + if area == move_ghost: + continue + return false + + return true