Functional plugin

This commit is contained in:
olof.pettersson
2025-10-03 06:04:33 +02:00
parent 7c689f6023
commit 09a4003839
5 changed files with 91 additions and 40 deletions

View File

@ -28,7 +28,7 @@ var save_button: Button
var builder_scene_root: Node2D
var builder_camera: Camera2D
# --- NEW: State Management Enum ---
# --- State Management Enum ---
enum BuilderState {
IDLE,
PLACING_STRUCTURAL,
@ -45,6 +45,8 @@ var grid_size: float = 50.0
var undo_redo: EditorUndoRedoManager
# --- Most of the setup functions remain the same ---
func _enter_tree():
main_screen = MAIN_EDITOR_SCENE.instantiate()
EditorInterface.get_editor_main_screen().add_child(main_screen)
@ -179,7 +181,6 @@ func _on_viewport_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
_update_preview_position()
# --- REFACTORED: Use match statement for state-based input handling ---
match current_state:
BuilderState.IDLE:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed():
@ -198,7 +199,6 @@ func _on_viewport_input(event: InputEvent) -> void:
on_clear_preview()
BuilderState.WIRING:
# Placeholder for future wiring logic
pass
@ -227,8 +227,6 @@ func _on_component_selected(component_scene: PackedScene):
current_state = BuilderState.PLACING_COMPONENT
active_scene = component_scene
preview_node = component_scene.instantiate() as Component
# You might want a specific material or modulation for component previews
# preview_node.modulate = Color(0.5, 1.0, 0.5, 0.5)
builder_scene_root.add_child(preview_node)
print("Now placing component: ", component_scene.resource_path)
@ -256,20 +254,18 @@ func _update_preview_position():
preview_node.global_position = snapped_pos
preview_node.rotation = rotation_angle
BuilderState.PLACING_COMPONENT:
# For components, we snap to the closest attachment point
var target_module = _find_first_module()
if target_module:
var closest_point = _find_closest_attachment_point(target_module, world_mouse_pos)
if closest_point:
preview_node.global_position = closest_point.position
# You might want to handle rotation differently for components
# preview_node.rotation = closest_point.rotation
else:
preview_node.global_position = world_mouse_pos # Or hide it
preview_node.global_position = world_mouse_pos
else:
preview_node.global_position = world_mouse_pos # Or hide it
preview_node.global_position = world_mouse_pos
# --- REFACTORED: Piece Placement ---
func _place_piece_from_preview():
if not is_instance_valid(preview_node) or not is_instance_valid(active_scene):
return
@ -288,19 +284,22 @@ func _place_piece_from_preview():
target_module.owner = builder_scene_root
var piece_to_place = active_scene.instantiate()
target_module.structural_container.add_child(piece_to_place)
# --- The main change: Add as a direct child of the module ---
target_module.add_child(piece_to_place)
piece_to_place.owner = target_module
piece_to_place.rotation = rotation_angle
piece_to_place.global_position = snapped_pos
undo_redo.create_action("Place Structural Piece")
undo_redo.add_do_method(target_module.structural_container, "add_child", piece_to_place)
undo_redo.add_do_method(target_module, "add_child", piece_to_place)
undo_redo.add_do_method(piece_to_place, "set_owner", target_module)
undo_redo.add_do_method(target_module, "_recalculate_collision_shape")
undo_redo.add_undo_method(target_module.structural_container, "remove_child", piece_to_place)
undo_redo.add_undo_method(target_module, "remove_child", piece_to_place)
undo_redo.add_undo_method(target_module, "_recalculate_collision_shape")
undo_redo.commit_action()
# --- Component Placement remains the same ---
func _place_component_from_preview():
if not is_instance_valid(preview_node) or not is_instance_valid(active_scene):
push_error("Cannot place component: Invalid preview or scene.")
@ -334,6 +333,7 @@ func _place_component_from_preview():
preview_node.global_position = closest_point.position
# --- Find Nearby Modules remains the same ---
func _find_nearby_modules(position: Vector2) -> Module:
const OVERLAP_MARGIN = 20.0
@ -367,8 +367,9 @@ func _find_nearby_modules(position: Vector2) -> Module:
if not result.is_empty():
var collider = result[0].get("collider")
if collider is StructuralPiece:
if collider.get_parent() and collider.get_parent().get_parent() is Module:
return collider.get_parent().get_parent()
# --- REFACTORED: The module is now the direct parent/owner ---
if is_instance_valid(collider.owner) and collider.owner is Module:
return collider.owner
return null
@ -383,7 +384,6 @@ func _remove_piece_under_mouse():
if not viewport: return
var world_mouse_pos = viewport.get_canvas_transform().affine_inverse() * viewport.get_mouse_position()
# Point query to find what's under the mouse
var space_state = builder_world.direct_space_state
var query = PhysicsPointQueryParameters2D.new()
query.position = world_mouse_pos
@ -394,33 +394,35 @@ func _remove_piece_under_mouse():
if collider is StructuralPiece:
_remove_piece_with_undo_redo(collider)
elif collider is Component:
# Add logic to remove components here
pass
# --- REFACTORED: Piece Removal ---
func _remove_piece_with_undo_redo(piece: StructuralPiece):
var module = piece.owner as Module
var parent = piece.get_parent()
if not is_instance_valid(module) or not module is Module:
return
undo_redo.create_action("Remove Structural Piece")
if module.structural_container.get_child_count(false) == 1 and module.get_child_count() > 2 : # Structural and HullVolume containers
# If it's the last piece, remove the whole module
# If this is the last structural piece of the module...
if module.get_structural_pieces().size() == 1:
# ...remove the entire module.
undo_redo.add_do_method(builder_scene_root, "remove_child", module)
undo_redo.add_undo_method(builder_scene_root, "add_child", module)
undo_redo.add_undo_method(module, "set_owner", builder_scene_root)
else:
# Otherwise, just remove the piece
undo_redo.add_do_method(parent, "remove_child", piece)
# Otherwise, just remove the single piece from its parent (the module).
undo_redo.add_do_method(module, "remove_child", piece)
undo_redo.add_do_method(module, "_recalculate_collision_shape")
undo_redo.add_undo_method(parent, "add_child", piece)
undo_redo.add_undo_method(module, "add_child", piece)
undo_redo.add_undo_method(piece, "set_owner", module) # Re-assign owner on undo
undo_redo.add_undo_method(module, "_recalculate_collision_shape")
undo_redo.commit_action()
# --- Toolbar Button Functions ---
# --- Toolbar Button Functions (No changes needed) ---
func _on_rotate_button_pressed():
rotation_angle = wrapf(rotation_angle + PI / 2, 0, TAU)
if is_instance_valid(preview_node):
@ -480,7 +482,8 @@ func _perform_save(file_path: String, module_to_save: Module):
func _on_undo_redo_action_committed():
_refresh_tree_display()
# --- REFACTORED: Tree Display ---
func _refresh_tree_display():
if not is_instance_valid(tree_control):
return
@ -489,25 +492,23 @@ func _refresh_tree_display():
var root_item = tree_control.create_item()
root_item.set_text(0, builder_scene_root.name)
# Iterate through all modules and populate the tree.
for module in builder_scene_root.get_children():
if module is Module:
print(module)
var module_item = tree_control.create_item(root_item)
module_item.set_text(0, module.name)
module_item.set_meta("node", module)
for piece in module.structural_container.get_children():
if piece is StructuralPiece:
var piece_item = tree_control.create_item(module_item)
piece_item.set_text(0, piece.name)
piece_item.set_meta("node", piece)
# Also show components in the tree
for component in module.get_children():
if component is Component:
var component_item = tree_control.create_item(module_item)
component_item.set_text(0, component.name)
component_item.set_meta("node", component)
# Use the module's helper functions to find children
for piece in module.get_structural_pieces():
var piece_item = tree_control.create_item(module_item)
piece_item.set_text(0, piece.name)
piece_item.set_meta("node", piece)
for component in module.get_components():
var component_item = tree_control.create_item(module_item)
component_item.set_text(0, component.name)
component_item.set_meta("node", component)
func _find_closest_attachment_point(module: Module, world_pos: Vector2):

49
modules/Tube.tscn Normal file
View File

@ -0,0 +1,49 @@
[gd_scene load_steps=4 format=3 uid="uid://didt2nsdtbmra"]
[ext_resource type="Script" uid="uid://6co67nfy8ngb" path="res://scenes/ship/builder/module.gd" id="1_nqe0s"]
[ext_resource type="PackedScene" uid="uid://bho8x10x4oab7" path="res://scenes/ship/builder/pieces/hullplate.tscn" id="2_foqop"]
[ext_resource type="PackedScene" uid="uid://d3hitk62fice4" path="res://scenes/ship/builder/pieces/bulkhead.tscn" id="4_dmrms"]
[node name="Module" type="Node2D"]
script = ExtResource("1_nqe0s")
metadata/_custom_type_script = "uid://0isnsk356que"
[node name="StructuralContainer" type="Node2D" parent="."]
[node name="HullVolumeContainer" type="Node2D" parent="."]
[node name="AtmosphereVisualizer" type="Node2D" parent="."]
[node name="Hullplate" parent="." instance=ExtResource("2_foqop")]
[node name="@StaticBody2D@30634" parent="." instance=ExtResource("2_foqop")]
position = Vector2(0, 100)
[node name="@StaticBody2D@30635" parent="." instance=ExtResource("2_foqop")]
position = Vector2(0, -100)
[node name="Bulkhead" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(-50, 100)
[node name="@StaticBody2D@30636" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(-50, 0)
[node name="@StaticBody2D@30637" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(-50, -100)
[node name="@StaticBody2D@30638" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(50, -100)
[node name="@StaticBody2D@30639" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(0, -150)
rotation = 1.5708
[node name="@StaticBody2D@30640" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(0, 150)
rotation = 4.71239
[node name="@StaticBody2D@30641" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(50, 100)
[node name="@StaticBody2D@30642" parent="." instance=ExtResource("4_dmrms")]
position = Vector2(50, 0)

View File

@ -1,3 +1,4 @@
@tool
class_name Module
extends OrbitalBody2D

View File

@ -1,6 +1,6 @@
# Thruster.gd
class_name Thruster
extends ShipComponent
extends Component
@onready var pin_joint_a: PinJoint2D = $PinJointA
@onready var pin_joint_b: PinJoint2D = $PinJointB

View File

@ -31,7 +31,7 @@ func _ready():
# FIX: Enable _physics_process for ALL OrbitalBody2D nodes (including Thrusters).
# The 'if is_sim_root' inside _physics_process will prevent integration for children.
set_physics_process(true)
set_physics_process(Engine.is_editor_hint())
# --- PUBLIC FORCE APPLICATION METHODS ---
# This method is called by a component (like Thruster) at its global position.