-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.gd
346 lines (307 loc) · 14.2 KB
/
main.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
extends Node3D
var selected_primitive: CSGPrimitive3D = null
var primitive_container: Node3D # Node3D to hold and manipulate the selected primitive
var csg_combiner: CSGCombiner3D
var camera: Camera3D
var camera_speed = 10.0
var mouse_sensitivity = 0.05
var is_mouse_dragging = false # Track if the mouse button is pressed for dragging
var is_transforming = false # Track if transforming the primitive
var transform_mode = 0 # 0 = position, 1 = rotation, 2 = scale
var ui_control: Control # Reference to the Control node for toggling visibility
var toggle_ui_button: CheckButton # Reference to the toggle button
var is_ui_visible = true # Track UI visibility state
# UI field references for position, rotation, and scale
var position_edit: LineEdit
var rotation_edit: LineEdit
var scale_edit: LineEdit
# Transformation speed for in-game manipulation
var transform_speed = 0.1
# test comment
func _ready():
camera = get_node("Camera3D")
ui_control = get_node("Control") # Get the Control node for UI
toggle_ui_button = get_node("Control/HBoxContainer/VBoxContainer/ButtonsHBox/ToggleUIVisibility") # Get the CheckButton
csg_combiner = CSGCombiner3D.new()
csg_combiner.operation = CSGCombiner3D.OPERATION_UNION
add_child(csg_combiner)
# Create a Node3D to hold the primitive for manipulation
primitive_container = Node3D.new()
primitive_container.name = "PrimitiveContainer"
add_child(primitive_container)
# Connect the toggled signal of the CheckButton to toggle UI visibility
if toggle_ui_button:
toggle_ui_button.toggled.connect(_on_toggle_ui_toggled)
# Connect button signals to create primitives
var buttons_hbox = get_node("Control/HBoxContainer/VBoxContainer/ButtonsHBox")
if buttons_hbox:
var box_button = buttons_hbox.get_node("BoxButton") as Button
var cylinder_button = buttons_hbox.get_node("CylinderButton") as Button
var sphere_button = buttons_hbox.get_node("SphereButton") as Button
var torus_button = buttons_hbox.get_node("TorusButton") as Button
var polygon_button = buttons_hbox.get_node("PolygonButton") as Button
var mesh_button = buttons_hbox.get_node("MeshButton") as Button
var remove_button = buttons_hbox.get_node("RemoveButton") as Button
if box_button:
box_button.pressed.connect(func(): create_primitive("box"))
if cylinder_button:
cylinder_button.pressed.connect(func(): create_primitive("cylinder"))
if sphere_button:
sphere_button.pressed.connect(func(): create_primitive("sphere"))
if torus_button:
torus_button.pressed.connect(func(): create_primitive("torus"))
if polygon_button:
polygon_button.pressed.connect(func(): create_primitive("polygon"))
if mesh_button:
mesh_button.pressed.connect(func(): create_primitive("mesh"))
if remove_button:
remove_button.pressed.connect(remove_primitive)
# Get references to UI fields
var input_fields_hbox = get_node("Control/HBoxContainer/VBoxContainer/InputFieldsHBox")
if input_fields_hbox:
position_edit = input_fields_hbox.get_node("PositionEdit") as LineEdit
rotation_edit = input_fields_hbox.get_node("RotationEdit") as LineEdit
scale_edit = input_fields_hbox.get_node("ScaleEdit") as LineEdit
# Connect UI field signals to update primitive properties
if position_edit:
position_edit.text_submitted.connect(_on_position_submitted)
if rotation_edit:
rotation_edit.text_submitted.connect(_on_rotation_submitted)
if scale_edit:
scale_edit.text_submitted.connect(_on_scale_submitted)
# Set initial UI visibility
if ui_control:
ui_control.visible = is_ui_visible
func _on_toggle_ui_toggled(toggled_on: bool):
# Update UI visibility based on CheckButton state
is_ui_visible = toggled_on
if ui_control:
ui_control.visible = is_ui_visible
func create_primitive(type: String):
print("create_primitive called with type: ", type)
if selected_primitive != null:
remove_primitive()
match type:
"box":
selected_primitive = CSGBox3D.new()
print("Box primitive created")
selected_primitive.size = Vector3(10, 10, 10)
"cylinder":
selected_primitive = CSGCylinder3D.new()
selected_primitive.height = 10 # Set a default height
selected_primitive.radius = 5 # Set a default radius
"sphere":
selected_primitive = CSGSphere3D.new()
selected_primitive.radius = 5 # Set a default radius
"torus":
selected_primitive = CSGTorus3D.new()
selected_primitive.inner_radius = 2 # Set default inner radius
selected_primitive.outer_radius = 5 # Set default outer radius
"polygon":
selected_primitive = CSGPolygon3D.new()
selected_primitive.polygon = PackedVector2Array([-2, -2, 2, -2, 2, 2, -2, 2]) # Default square polygon
"mesh":
selected_primitive = CSGMesh3D.new() # Needs more setup, implement later
printerr("Mesh primitive not fully implemented yet")
return
_:
printerr("Invalid primitive type")
return
# Position the primitive on top of the terrain and add it to the container
selected_primitive.position = Vector3(0, 0, 0) # Center at origin, adjusted for terrain height
selected_primitive.use_collision = true
primitive_container.add_child(selected_primitive)
selected_primitive.owner = self # Ensure the primitive is owned by the scene
# Enable in-game transform manipulation
update_ui_fields() # Update UI fields with the primitive's initial values
# Adjust position based on terrain
adjust_primitive_to_terrain()
func _process(_delta): # Renamed delta to _delta to suppress the warning
# Handle in-game transform manipulation when is_transforming is true
if is_transforming and selected_primitive:
var movement = Vector3.ZERO
if Input.is_key_pressed(KEY_UP):
if transform_mode == 0: # Position
movement.z -= transform_speed
elif transform_mode == 1: # Rotation
selected_primitive.rotation_degrees.z -= transform_speed * 10 # Adjust rotation speed
elif transform_mode == 2: # Scale
selected_primitive.scale.z += transform_speed
if Input.is_key_pressed(KEY_DOWN):
if transform_mode == 0: # Position
movement.z += transform_speed
elif transform_mode == 1: # Rotation
selected_primitive.rotation_degrees.z += transform_speed * 10 # Adjust rotation speed
elif transform_mode == 2: # Scale
selected_primitive.scale.z -= transform_speed
if Input.is_key_pressed(KEY_LEFT):
if transform_mode == 0: # Position
movement.x -= transform_speed
elif transform_mode == 1: # Rotation
selected_primitive.rotation_degrees.y += transform_speed * 10 # Adjust rotation speed
elif transform_mode == 2: # Scale
selected_primitive.scale.x -= transform_speed
if Input.is_key_pressed(KEY_RIGHT):
if transform_mode == 0: # Position
movement.x += transform_speed
elif transform_mode == 1: # Rotation
selected_primitive.rotation_degrees.y -= transform_speed * 10 # Adjust rotation speed
elif transform_mode == 2: # Scale
selected_primitive.scale.x += transform_speed
if Input.is_key_pressed(KEY_PAGEUP):
if transform_mode == 0: # Position
movement.y += transform_speed
elif transform_mode == 2: # Scale
selected_primitive.scale.y += transform_speed
if Input.is_key_pressed(KEY_PAGEDOWN):
if transform_mode == 0: # Position
movement.y -= transform_speed
elif transform_mode == 2: # Scale
selected_primitive.scale.y -= transform_speed
# Apply position changes and adjust for terrain
if movement != Vector3.ZERO and transform_mode == 0:
selected_primitive.position += movement
adjust_primitive_to_terrain()
update_ui_fields()
# Update UI fields for rotation and scale changes
if transform_mode == 1 or transform_mode == 2:
update_ui_fields()
func adjust_primitive_to_terrain():
if selected_primitive and has_node("Terrain"):
var terrain = get_node("Terrain") as CSGPolygon3D
if terrain:
# For a flat terrain at y = -0.5, position the primitive's base at y = 0
# Adjust y based on the primitive's height to place its base on the terrain surface
var primitive_height = get_primitive_height(selected_primitive)
selected_primitive.position.y = -0.5 + (primitive_height / 2.0) # Center the primitive on the terrain surface
# Update the container's position to match the primitive
primitive_container.position = selected_primitive.position
func get_primitive_height(primitive: CSGPrimitive3D) -> float:
# Determine the height of the primitive based on its type
if primitive is CSGBox3D:
return (primitive as CSGBox3D).size.y
elif primitive is CSGCylinder3D:
return (primitive as CSGCylinder3D).height
elif primitive is CSGSphere3D:
return (primitive as CSGSphere3D).radius * 2 # Diameter as height
elif primitive is CSGTorus3D:
return (primitive as CSGTorus3D).outer_radius * 2 # Approximate height
elif primitive is CSGPolygon3D:
# For simplicity, assume a flat polygon with no height (adjust if needed)
return 0.0
return 0.0 # Default height if type not handled
func remove_primitive():
if selected_primitive != null:
primitive_container.remove_child(selected_primitive)
selected_primitive.queue_free()
selected_primitive = null
update_ui_fields() # Clear UI fields when no primitive is selected
is_transforming = false # Stop transforming when removing the primitive
func set_primitive_position(text: String):
if selected_primitive != null:
var values = parse_vector3(text)
if values != null:
selected_primitive.position = values
adjust_primitive_to_terrain() # Ensure the primitive stays on the terrain after repositioning
update_ui_fields() # Update UI fields to reflect the new position
func set_primitive_rotation(text: String):
if selected_primitive != null:
var values = parse_vector3(text)
if values != null:
selected_primitive.rotation_degrees = values
update_ui_fields() # Update UI fields to reflect the new rotation
func set_primitive_scale(text: String):
if selected_primitive != null:
var values = parse_vector3(text)
if values != null:
selected_primitive.scale = values
adjust_primitive_to_terrain() # Ensure the primitive stays on the terrain after scaling
update_ui_fields() # Update UI fields to reflect the new scale
func parse_vector3(text: String) -> Vector3:
var parts = text.split(",")
if parts.size() == 3:
var x = parts[0].to_float()
var y = parts[1].to_float()
var z = parts[2].to_float()
if typeof(x) == TYPE_FLOAT and typeof(y) == TYPE_FLOAT and typeof(z) == TYPE_FLOAT:
return Vector3(x, y, z)
return Vector3(0, 0, 0)
func update_ui_fields():
# Update UI fields to reflect the current state of the selected primitive
if selected_primitive:
position_edit.text = "%f,%f,%f" % [selected_primitive.position.x, selected_primitive.position.y, selected_primitive.position.z]
rotation_edit.text = "%f,%f,%f" % [selected_primitive.rotation_degrees.x, selected_primitive.rotation_degrees.y, selected_primitive.rotation_degrees.z]
scale_edit.text = "%f,%f,%f" % [selected_primitive.scale.x, selected_primitive.scale.y, selected_primitive.scale.z]
else:
position_edit.text = ""
rotation_edit.text = ""
scale_edit.text = ""
func _on_position_submitted(new_text: String):
set_primitive_position(new_text)
func _on_rotation_submitted(new_text: String):
set_primitive_rotation(new_text)
func _on_scale_submitted(new_text: String):
set_primitive_scale(new_text)
func _unhandled_input(event):
# Toggle UI visibility with the Tab key
if event is InputEventKey and event.pressed and event.keycode == KEY_TAB:
is_ui_visible = !is_ui_visible
if ui_control:
ui_control.visible = is_ui_visible
# Update the CheckButton state to match (if UI is visible)
if toggle_ui_button and ui_control.visible:
toggle_ui_button.button_pressed = is_ui_visible
# Toggle transform mode (position, rotation, scale) with number keys
if event is InputEventKey and event.pressed:
if event.keycode == KEY_1:
transform_mode = 0 # Position
is_transforming = true
print("Transform mode: Position")
elif event.keycode == KEY_2:
transform_mode = 1 # Rotation
is_transforming = true
print("Transform mode: Rotation")
elif event.keycode == KEY_3:
transform_mode = 2 # Scale
is_transforming = true
print("Transform mode: Scale")
elif event.keycode == KEY_0:
is_transforming = false # Exit transform mode
print("Transform mode: Off")
# Handle mouse button for dragging only if not interacting with UI elements
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not get_viewport().gui_is_dragging():
is_mouse_dragging = event.pressed
if is_mouse_dragging:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) # Lock cursor for dragging
else:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) # Show cursor when not dragging
elif event is InputEventMouseMotion and is_mouse_dragging:
print("Mouse motion detected, relative: ", event.relative) # Debug print
rotate_camera(event.relative)
if event is InputEventKey:
handle_camera_movement(event)
func rotate_camera(relative_motion):
# Rotate only the Camera3D directly for cleaner behavior
if camera:
camera.rotate_y(deg_to_rad(-relative_motion.x * mouse_sensitivity))
camera.rotate_x(deg_to_rad(-relative_motion.y * mouse_sensitivity))
camera.rotation_degrees.x = clamp(camera.rotation_degrees.x, -89, 89)
func handle_camera_movement(event):
var forward_direction = -camera.global_transform.basis.z
var right_direction = camera.global_transform.basis.x
var up_direction = camera.global_transform.basis.y
if event.pressed:
if event.keycode == KEY_W and Input.is_action_pressed("forward_direction"):
camera.position += forward_direction * camera_speed * get_process_delta_time()
if event.keycode == KEY_S and Input.is_action_pressed("back_direction"):
camera.position -= forward_direction * camera_speed * get_process_delta_time()
if event.keycode == KEY_A and Input.is_action_pressed("left_direction"):
camera.position -= right_direction * camera_speed * get_process_delta_time()
if event.keycode == KEY_D and Input.is_action_pressed("right_direction"):
camera.position += right_direction * camera_speed * get_process_delta_time()
if event.keycode == KEY_SPACE and Input.is_action_pressed("up_direction"):
camera.position += up_direction * camera_speed * get_process_delta_time()
if event.keycode == KEY_SHIFT and Input.is_action_pressed("down_direction"):
camera.position -= up_direction * camera_speed * get_process_delta_time()
func get_transform_mode() -> int:
return transform_mode