Plugin
This commit is contained in:
@ -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
|
||||
|
||||
@ -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"]
|
||||
|
||||
13
main.tscn
13
main.tscn
@ -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
|
||||
|
||||
@ -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")
|
||||
|
||||
Reference in New Issue
Block a user