much better field edit tool, camera specifically
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
class_name FlowFieldData
|
||||
extends Resource
|
||||
|
||||
@export var nodes: Array[FlowNodeData]
|
||||
@@ -1 +0,0 @@
|
||||
uid://ds7m1p5666qby
|
||||
@@ -1,13 +0,0 @@
|
||||
class_name FlowNodeData
|
||||
extends Resource
|
||||
|
||||
enum NodeType {
|
||||
STANDARD = 0,
|
||||
START = 1,
|
||||
GOAL = 2,
|
||||
}
|
||||
|
||||
@export var position: Vector3
|
||||
@export var type: NodeType
|
||||
@export var buildable: bool
|
||||
@export var connected_nodes: Array[FlowNodeData]
|
||||
@@ -1 +0,0 @@
|
||||
uid://udtpnemisl0t
|
||||
@@ -1,189 +0,0 @@
|
||||
class_name FlowFieldTool
|
||||
extends Node
|
||||
|
||||
@export var flow_field: FlowField
|
||||
@export var raycast: RayCast3D
|
||||
@export var project_raycast: RayCast3D
|
||||
@export var camera: Camera3D
|
||||
@export var camera_pivot: Node3D
|
||||
@export var position_field: HBoxContainer
|
||||
@export var x_field: LineEdit
|
||||
@export var y_field: LineEdit
|
||||
@export var z_field: LineEdit
|
||||
@export var x_size_field: LineEdit
|
||||
@export var y_size_field: LineEdit
|
||||
@export var gap_field: LineEdit
|
||||
@export var save_path: LineEdit
|
||||
|
||||
var hover: FlowNode = null
|
||||
var selected: Array[FlowNode] = []
|
||||
var vector_dirty: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
camera.make_current()
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if raycast.is_colliding() and (!hover or hover != raycast.get_collider()):
|
||||
hover = raycast.get_collider()
|
||||
if hover and !raycast.is_colliding():
|
||||
hover = null
|
||||
if selected.size() == 1 and vector_dirty:
|
||||
position_field.visible = true
|
||||
x_field.text = str(selected[0].global_position.x)
|
||||
y_field.text = str(selected[0].global_position.y)
|
||||
z_field.text = str(selected[0].global_position.z)
|
||||
vector_dirty = false
|
||||
elif selected.size() != 1:
|
||||
position_field.visible = false
|
||||
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
if node.traversable and node.buildable:
|
||||
node.set_color(Color.WEB_GRAY)
|
||||
elif node.traversable and !node.buildable:
|
||||
node.set_color(Color.CORAL)
|
||||
else:
|
||||
node.set_color(Color.BLACK)
|
||||
if flow_field.goal_nodes.has(node):
|
||||
node.set_color(Color.BLUE)
|
||||
if flow_field.start_nodes.has(node):
|
||||
node.set_color(Color.PINK)
|
||||
if selected.has(node):
|
||||
node.set_color(Color.GREEN)
|
||||
if node == hover:
|
||||
node.set_color(Color.RED)
|
||||
|
||||
var y: float = Input.get_axis("Move Forward", "Move Backward")
|
||||
var x: float = Input.get_axis("Move Left", "Move Right")
|
||||
camera_pivot.position += Vector3(x, 0, y) * delta * 10
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
var from: Vector3 = camera.project_ray_origin(event.position)
|
||||
var to: Vector3 = camera.project_local_ray_normal(event.position)
|
||||
raycast.global_position = from
|
||||
raycast.target_position = to * 1000.0
|
||||
if event is InputEventMouseButton and event.button_index == 1 and hover:
|
||||
if !selected.has(hover):
|
||||
selected.append(hover)
|
||||
vector_dirty = true
|
||||
if event is InputEventMouseButton and event.button_index == 2 and selected.size() > 0:
|
||||
selected = []
|
||||
if event is InputEventKey and event.keycode == KEY_UP:
|
||||
var vector: Vector3 = camera.position - camera_pivot.position
|
||||
vector = vector.normalized()
|
||||
camera.position += vector
|
||||
if event is InputEventKey and event.keycode == KEY_DOWN:
|
||||
var vector: Vector3 = camera.position - camera_pivot.position
|
||||
vector = vector.normalized()
|
||||
camera.position -= vector
|
||||
|
||||
|
||||
func _on_x_field_changed(text: String) -> void:
|
||||
selected[0].global_position.x = float(text)
|
||||
|
||||
|
||||
func _on_y_field_changed(text: String) -> void:
|
||||
selected[0].global_position.y = float(text)
|
||||
|
||||
|
||||
func _on_z_field_changed(text: String) -> void:
|
||||
selected[0].global_position.z = float(text)
|
||||
|
||||
|
||||
func _on_create_button_pressed() -> void:
|
||||
flow_field.create_node()
|
||||
|
||||
|
||||
func _on_generate_grid_button_pressed() -> void:
|
||||
flow_field.create_grid(int(x_size_field.text), int(y_size_field.text), float(gap_field.text))
|
||||
selected.append_array(flow_field.nodes)
|
||||
|
||||
|
||||
func _on_calculate_button_pressed() -> void:
|
||||
flow_field.calculate()
|
||||
|
||||
|
||||
func _on_connect_button_pressed() -> void:
|
||||
flow_field.connect_many_nodes(selected[0], selected.slice(1, selected.size()))
|
||||
|
||||
|
||||
func _on_mark_goal_button_pressed() -> void:
|
||||
flow_field.toggle_goal(selected)
|
||||
selected = []
|
||||
vector_dirty = true
|
||||
|
||||
|
||||
func _on_mark_start_button_pressed() -> void:
|
||||
flow_field.toggle_start(selected)
|
||||
selected = []
|
||||
vector_dirty = true
|
||||
|
||||
|
||||
func _on_extrude_button_pressed() -> void:
|
||||
if selected.size() == 1:
|
||||
var node: FlowNode = flow_field.create_node(selected[0].position)
|
||||
node.add_connection(selected[0])
|
||||
selected[0].add_connection(node)
|
||||
selected[0].set_color(Color.WEB_GRAY)
|
||||
selected = []
|
||||
selected.append(node)
|
||||
vector_dirty = true
|
||||
|
||||
|
||||
func _on_toggle_traversable_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
if !flow_field.toggle_traversable(node):
|
||||
flow_field.toggle_traversable(node)
|
||||
selected = []
|
||||
return
|
||||
selected = []
|
||||
|
||||
|
||||
func _on_toggle_buildable_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
flow_field.toggle_buildable(node)
|
||||
|
||||
|
||||
#TODO: This doesnt work as you'd expect because of physics frames
|
||||
func _on_project_downwards_button_pressed() -> void:
|
||||
for node: FlowNode in selected:
|
||||
project_raycast.global_position = node.global_position + Vector3.UP
|
||||
project_raycast.target_position = Vector3.DOWN * 100.0
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
await get_tree().physics_frame
|
||||
if project_raycast.is_colliding():
|
||||
node.global_position = project_raycast.get_collision_point()
|
||||
|
||||
|
||||
func _on_save_button_pressed() -> void:
|
||||
var new_flow_field_data: FlowFieldData = FlowFieldData.new()
|
||||
var dict: Dictionary[FlowNode, FlowNodeData] = {}
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
var new_flow_node_data: FlowNodeData = FlowNodeData.new()
|
||||
new_flow_node_data.position = node.global_position
|
||||
new_flow_node_data.buildable = node.buildable
|
||||
if flow_field.start_nodes.has(node):
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.START
|
||||
elif flow_field.goal_nodes.has(node):
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.GOAL
|
||||
else:
|
||||
new_flow_node_data.type = FlowNodeData.NodeType.STANDARD
|
||||
dict[node] = new_flow_node_data
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
var flow_node_data: FlowNodeData = dict[node]
|
||||
for neighbor: FlowNode in node.connections:
|
||||
flow_node_data.connected_nodes.append(dict[neighbor])
|
||||
new_flow_field_data.nodes.append(flow_node_data)
|
||||
ResourceSaver.save(new_flow_field_data, save_path.text)
|
||||
|
||||
|
||||
func _on_load_button_pressed() -> void:
|
||||
if ResourceLoader.exists(save_path.text):
|
||||
var resource: Resource = ResourceLoader.load(save_path.text)
|
||||
if resource is FlowFieldData:
|
||||
flow_field.load_from_data(resource)
|
||||
@@ -1 +0,0 @@
|
||||
uid://05c5q1v2nv8p
|
||||
@@ -1,64 +0,0 @@
|
||||
class_name FlowNode
|
||||
extends StaticBody3D
|
||||
|
||||
@export var connections: Array[FlowNode]
|
||||
@export var visualisers: Array[Node3D]
|
||||
@export var traversable: bool = true
|
||||
@export var buildable: bool = true
|
||||
|
||||
var visual_scene: PackedScene = preload("res://Scenes/FlowField/cube2.tscn")
|
||||
var best_path: FlowNode :
|
||||
get():
|
||||
return best_path
|
||||
set(value):
|
||||
set_connector_color(best_path, Color.DARK_GRAY)
|
||||
best_path = value
|
||||
set_connector_color(best_path, Color.DARK_GREEN)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
visualisers = []
|
||||
for node: FlowNode in connections:
|
||||
var visual: Node3D = visual_scene.instantiate()
|
||||
add_child(visual)
|
||||
visual.owner = self
|
||||
visualisers.append(visual)
|
||||
set_connector_color(node, Color.WEB_GRAY)
|
||||
|
||||
|
||||
@warning_ignore("unused_parameter")
|
||||
func _process(delta: float) -> void:
|
||||
if visible:
|
||||
for i: int in connections.size():
|
||||
var distance: float = global_position.distance_to(connections[i].global_position)
|
||||
visualisers[i].scale = Vector3(0.3, 0.3, 1.0 * (distance / 2.0))
|
||||
visualisers[i].position = to_local(connections[i].global_position) / 4.0
|
||||
if distance >= 0.05:
|
||||
visualisers[i].look_at(connections[i].global_position)
|
||||
|
||||
|
||||
func set_color(new_color: Color) -> void:
|
||||
$flow_node/Sphere.material_override.albedo_color = new_color
|
||||
|
||||
|
||||
func set_connector_color(node: FlowNode, new_color: Color) -> void:
|
||||
if visible:
|
||||
var i: int = connections.find(node)
|
||||
visualisers[i].get_child(0).material_override.albedo_color = new_color
|
||||
|
||||
|
||||
func add_connection(node: FlowNode) -> void:
|
||||
if !connections.has(node):
|
||||
var visual: Node3D = visual_scene.instantiate()
|
||||
add_child(visual)
|
||||
visual.owner = self
|
||||
connections.append(node)
|
||||
visualisers.append(visual)
|
||||
set_connector_color(node, Color.WEB_GRAY)
|
||||
|
||||
|
||||
func remove_connection(node: FlowNode) -> void:
|
||||
if connections.has(node):
|
||||
var i: int = connections.find(node)
|
||||
visualisers.pop_at(i).queue_free()
|
||||
connections.remove_at(i)
|
||||
@@ -1 +0,0 @@
|
||||
uid://c86ygtor5tksd
|
||||
@@ -7,20 +7,21 @@ extends Node3D
|
||||
@export var enemy_spawns: Array[EnemySpawner]
|
||||
@export var enemy_goals: Array[Node3D]
|
||||
@export var corpses: Node
|
||||
@export var flow_field: FlowField
|
||||
@export var cinematic_cam: CinematicCamManager
|
||||
@export var printer: CardPrinter
|
||||
@export var shop: ShopStand
|
||||
@export var obstacle_scenes: Array[PackedScene]
|
||||
|
||||
var walls: Dictionary[FlowNode, TowerBase] = {}
|
||||
var wall_id: int = 0
|
||||
var tower_base_scene: PackedScene = load("res://Scenes/TowerBase/tower_base.tscn")
|
||||
var tower_frame_scene: PackedScene = load("res://Scenes/tower_frame.tscn")
|
||||
var tower_frames: Dictionary[FlowNode, Node3D] = {}
|
||||
var game_manager: GameManager
|
||||
var flow_field: FlowField
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
func load_flow_field() -> void:
|
||||
flow_field.path_updated.connect(enemy_spawns[0].update_path)
|
||||
for node: FlowNode in flow_field.nodes:
|
||||
if node.buildable:
|
||||
|
||||
Reference in New Issue
Block a user