This commit is contained in:
2025-09-25 08:55:24 +02:00
parent 57deb8403c
commit ef8d6eb1a9
4 changed files with 162 additions and 31 deletions

View File

@ -3,20 +3,59 @@ extends EditorPlugin
var builder_dock: Control = null
var builder_dock_scene = preload("res://addons/module_builder_plugin/builder_dock.tscn")
const MAIN_EDITOR_SCENE = preload("res://addons/module_builder_plugin/module_editor.tscn")
# --- Node References from the main screen scene ---
var main_screen: Control = null
var main_viewport_control: SubViewportContainer
# --- State Variables ---
var preview_piece: StructuralPiece = null
var active_piece_scene: PackedScene = null
var rotation_angle: float = 0.0
var grid_size: float = 50.0
func _enter_tree():
# This function is called when the plugin is enabled.
# It instantiates the custom editor scene and adds it to the editor's dock.
builder_dock = builder_dock_scene.instantiate()
# Instantiate the main scene for our plugin.
main_screen = MAIN_EDITOR_SCENE.instantiate()
add_control_to_bottom_panel(builder_dock, "Ship Builder")
# Add the main screen to the editor's main screen.
EditorInterface.get_editor_main_screen().add_child(main_screen)
# Get references to the viewport and hide the screen.
main_viewport_control = main_screen.find_child("MainViewport")
main_screen.hide()
func _exit_tree():
# This function is called when the plugin is disabled.
# It cleans up the custom editor scene and frees its memory.
if builder_dock:
remove_control_from_bottom_panel(builder_dock)
builder_dock.queue_free()
if main_screen:
main_screen.queue_free()
func _has_main_screen() -> bool:
return true
func _make_visible(visible):
if main_screen:
main_screen.visible = visible
_setup_gui_input_listener(visible)
if visible:
if builder_dock_scene:
builder_dock = builder_dock_scene.instantiate()
add_control_to_bottom_panel(builder_dock, "Ship Builder")
if not visible and builder_dock:
remove_control_from_bottom_panel(builder_dock)
builder_dock.queue_free()
func _get_plugin_name():
return "Ship Builder"
func _get_plugin_icon():
return EditorInterface.get_editor_theme().get_icon("Node", "EditorIcons")
func _handles(object: Object) -> bool:
return true
@ -25,3 +64,101 @@ func _forward_canvas_gui_input(event):
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
return true
return false
# --- GUI Input Handling ---
func _setup_gui_input_listener(connect: bool):
if main_screen:
if connect:
main_screen.gui_input.connect(_on_viewport_input)
else:
main_screen.gui_input.disconnect(_on_viewport_input)
func _on_viewport_input(event: InputEvent) -> void:
if not active_piece_scene:
return
if event is InputEventMouseMotion:
_update_preview_position()
if event is InputEventKey and event.is_pressed() and event.as_text() == "R":
rotation_angle = wrapf(rotation_angle + PI / 2, 0, TAU)
if preview_piece:
preview_piece.rotation = rotation_angle
_update_preview_position()
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
_place_piece_from_preview()
# --- Public API for builder_dock.gd ---
# This function is called by builder_dock.gd to set the active piece.
func set_active_piece(scene: PackedScene):
if is_instance_valid(preview_piece):
preview_piece.queue_free()
active_piece_scene = scene
preview_piece = active_piece_scene.instantiate() as StructuralPiece
preview_piece.is_preview = true
get_tree().get_edited_scene_root().add_child(preview_piece)
_update_preview_position()
# --- Placement and Position Logic ---
func _update_preview_position():
if not is_instance_valid(preview_piece):
return
var viewport = main_screen.find_child("SubViewport")
if not viewport: return
var snapped_pos = viewport.get_mouse_position().snapped(Vector2(grid_size, grid_size))
preview_piece.global_position = viewport.get_world_2d().canvas.transform.xform(snapped_pos)
preview_piece.rotation = rotation_angle
func _place_piece_from_preview():
if not is_instance_valid(preview_piece):
return
var viewport = main_screen.find_child("SubViewport")
if not viewport: return
var snapped_pos = viewport.get_mouse_position().snapped(Vector2(grid_size, grid_size))
var nearby_module = _find_nearby_modules(snapped_pos)
var target_module: Module
if is_instance_valid(nearby_module):
target_module = nearby_module
else:
var new_module_scene = preload("res://scenes/ship/builder/module.tscn")
target_module = new_module_scene.instantiate() as Module
get_tree().get_edited_scene_root().add_child(target_module)
target_module.global_position = viewport.get_world_2d().canvas.transform.xform(snapped_pos)
target_module.owner = get_tree().get_edited_scene_root()
preview_piece.is_preview = false
var piece_to_place = active_piece_scene.instantiate()
target_module.add_child(piece_to_place)
piece_to_place.owner = target_module.owner
piece_to_place.position = target_module.structural_container.to_local(snapped_pos)
target_module._recalculate_physics_properties()
# Clear the preview piece as a new one will be set by the button.
if is_instance_valid(preview_piece):
preview_piece.queue_free()
preview_piece = null
# --- Helper Functions ---
func _find_nearby_modules(position: Vector2) -> Module:
for node in get_tree().get_edited_scene_root().get_children():
if node is Module:
for piece in node.structural_container.get_children():
if piece is StructuralPiece:
if piece.global_position.distance_to(position) <= grid_size + 1:
return node
return null
func get_active_piece_scene() -> PackedScene:
return active_piece_scene

View File

@ -8,22 +8,24 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MainViewport" type="SubViewportContainer" parent="."]
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="Toolbar" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="MainViewport" type="SubViewportContainer" parent="VBoxContainer"]
layout_mode = 2
offset_left = -121.0
offset_top = -170.0
offset_right = 1273.0
offset_bottom = 818.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="SubViewport" type="SubViewport" parent="MainViewport"]
[node name="SubViewport" type="SubViewport" parent="VBoxContainer/MainViewport"]
transparent_bg = true
handle_input_locally = false
size = Vector2i(1394, 988)
render_target_update_mode = 4
[node name="Camera2D" type="Camera2D" parent="MainViewport/SubViewport"]
[node name="Camera2D" type="Camera2D" parent="VBoxContainer/MainViewport/SubViewport"]
zoom = Vector2(0.5, 0.5)
[node name="CustomGrid" type="Node2D" parent="MainViewport/SubViewport"]

View File

@ -1,12 +1,12 @@
[gd_scene load_steps=8 format=3 uid="uid://dogqi2c58qdc0"]
[ext_resource type="Script" uid="uid://j3j483itissq" path="res://scripts/star_system_generator.gd" id="1_h2yge"]
[ext_resource type="PackedScene" uid="uid://5uqp4amjj7ww" path="res://scenes/star.tscn" id="2_7mycd"]
[ext_resource type="PackedScene" uid="uid://clt4qlsjcfgln" path="res://scenes/planet.tscn" id="3_272bh"]
[ext_resource type="PackedScene" uid="uid://74ppvxcw8an4" path="res://scenes/moon.tscn" id="4_5vw27"]
[ext_resource type="PackedScene" uid="uid://dm3s33o4xhqfv" path="res://scenes/station.tscn" id="5_kek77"]
[ext_resource type="PackedScene" uid="uid://bawsujtlpmh5r" path="res://scenes/asteroid.tscn" id="6_4c57u"]
[ext_resource type="PackedScene" uid="uid://dlck1lyrn1xvp" path="res://scenes/spaceship/spaceship.tscn" id="7_5vw27"]
[ext_resource type="PackedScene" uid="uid://5uqp4amjj7ww" path="res://scenes/celestial_bodies/star.tscn" id="2_7mycd"]
[ext_resource type="PackedScene" uid="uid://clt4qlsjcfgln" path="res://scenes/celestial_bodies/planet.tscn" id="3_272bh"]
[ext_resource type="PackedScene" uid="uid://74ppvxcw8an4" path="res://scenes/celestial_bodies/moon.tscn" id="4_5vw27"]
[ext_resource type="PackedScene" uid="uid://dm3s33o4xhqfv" path="res://scenes/celestial_bodies/station.tscn" id="5_kek77"]
[ext_resource type="PackedScene" uid="uid://bawsujtlpmh5r" path="res://scenes/celestial_bodies/asteroid.tscn" id="6_4c57u"]
[ext_resource type="PackedScene" uid="uid://dlck1lyrn1xvp" path="res://scenes/ship/spaceship.tscn" id="7_5vw27"]
[node name="StarSystem" type="Node2D"]
script = ExtResource("1_h2yge")
@ -21,4 +21,3 @@ moon_scene = ExtResource("4_5vw27")
station_scene = ExtResource("5_kek77")
asteroid_scene = ExtResource("6_4c57u")
spaceship_scene = ExtResource("7_5vw27")
sim_scale = 0.21

View File

@ -1,10 +1,3 @@
[gd_scene load_steps=3 format=3 uid="uid://bvogqgqig1hps"]
[ext_resource type="PackedScene" uid="uid://cm0rohkr6khd1" path="res://scenes/ship/builder/module.tscn" id="1_23uw4"]
[ext_resource type="Script" uid="uid://6co67nfy8ngb" path="res://scenes/ship/builder/module.gd" id="2_anlqm"]
[gd_scene format=3 uid="uid://bvogqgqig1hps"]
[node name="ShipBuildingTest" type="Node2D"]
[node name="Module" type="RigidBody2D" parent="." instance=ExtResource("1_23uw4")]
position = Vector2(-250, -150)
script = ExtResource("2_anlqm")