first flow field resource draft

This commit is contained in:
2025-09-10 21:55:51 +10:00
parent c0859e26cb
commit 703e75d1d8
13 changed files with 208 additions and 24 deletions

View File

@@ -94,6 +94,11 @@ func set_zoom_factor(value: float) -> void:
func _ready() -> void: func _ready() -> void:
hud.disable_card_gameplay_ui()
if game_manager:
if game_manager.card_gameplay:
hud.enable_card_gameplay_ui()
if is_multiplayer_authority(): if is_multiplayer_authority():
ears.make_current() ears.make_current()
camera.make_current() camera.make_current()

View File

@@ -48,6 +48,14 @@ func _ready() -> void:
energy_label.visible = true energy_label.visible = true
func enable_card_gameplay_ui() -> void:
energy_label.visible = true
func disable_card_gameplay_ui() -> void:
energy_label.visible = false
func show_hot_wheel() -> void: func show_hot_wheel() -> void:
hot_wheel.visible = true hot_wheel.visible = true

View File

@@ -3,12 +3,16 @@ extends Node3D
signal path_updated() signal path_updated()
@export var data_file: FlowFieldData
@export var flow_node_scene: PackedScene @export var flow_node_scene: PackedScene
@export var nodes: Array[FlowNode] = [] @export var start_points: Array[Node3D]
@export var goals: Array[FlowNode] = [] @export var goal_points: Array[Node3D]
@export var starts: Array[FlowNode] = []
@export var nodes_visible: bool = false @export var nodes_visible: bool = false
var nodes: Array[FlowNode] = []
var start_nodes: Array[FlowNode] = []
var goal_nodes: Array[FlowNode] = []
func _ready() -> void: func _ready() -> void:
if !nodes_visible: if !nodes_visible:
@@ -16,6 +20,27 @@ func _ready() -> void:
node.visible = false node.visible = false
func load_from_data(data: FlowFieldData = data_file) -> void:
for node: FlowNode in nodes:
delete_node(node)
nodes = []
start_nodes = []
goal_nodes = []
var dict: Dictionary[FlowNodeData, FlowNode] = {}
for node_data: FlowNodeData in data_file.nodes:
var new_flow_node: FlowNode = create_node(node_data.position)
new_flow_node.buildable = node_data.buildable
dict[node_data] = new_flow_node
nodes.append(new_flow_node)
if node_data.type == FlowNodeData.NodeType.START:
start_nodes.append(new_flow_node)
elif node_data.type == FlowNodeData.NodeType.GOAL:
goal_nodes.append(new_flow_node)
for node_data: FlowNodeData in dict.keys():
for neighbor: FlowNodeData in node_data.connected_nodes:
dict[node_data].add_connection(dict[neighbor])
@warning_ignore("unused_parameter") @warning_ignore("unused_parameter")
func _process(delta: float) -> void: func _process(delta: float) -> void:
if !nodes_visible: if !nodes_visible:
@@ -27,9 +52,9 @@ func _process(delta: float) -> void:
node.set_color(Color.CORAL) node.set_color(Color.CORAL)
else: else:
node.set_color(Color.BLACK) node.set_color(Color.BLACK)
if goals.has(node): if goal_nodes.has(node):
node.set_color(Color.BLUE) node.set_color(Color.BLUE)
if starts.has(node): if start_nodes.has(node):
node.set_color(Color.PINK) node.set_color(Color.PINK)
if magic_node: if magic_node:
magic_node.set_color(Color.DEEP_PINK) magic_node.set_color(Color.DEEP_PINK)
@@ -66,7 +91,7 @@ func get_closest_buildable_point(pos: Vector3) -> FlowNode:
func test_traversability() -> bool: func test_traversability() -> bool:
for node: FlowNode in starts: for node: FlowNode in start_nodes:
while node.best_path != null: while node.best_path != null:
if node.best_path.traversable: if node.best_path.traversable:
node = node.best_path node = node.best_path
@@ -88,7 +113,7 @@ func iterate_search(search_frontier: Array[FlowNode], reached: Array[FlowNode])
func calculate() -> void: func calculate() -> void:
var reached: Array[FlowNode] = [] var reached: Array[FlowNode] = []
var search_frontier: Array[FlowNode] = [] var search_frontier: Array[FlowNode] = []
for node: FlowNode in goals: for node: FlowNode in goal_nodes:
node.best_path = null node.best_path = null
reached.append(node) reached.append(node)
search_frontier.append(node) search_frontier.append(node)
@@ -135,18 +160,18 @@ func connect_many_nodes(common_node: FlowNode, child_nodes: Array[FlowNode]) ->
func toggle_goal(nodes_to_toggle: Array[FlowNode]) -> void: func toggle_goal(nodes_to_toggle: Array[FlowNode]) -> void:
for node: FlowNode in nodes_to_toggle: for node: FlowNode in nodes_to_toggle:
if goals.has(node): if goal_nodes.has(node):
goals.erase(node) goal_nodes.erase(node)
else: else:
goals.append(node) goal_nodes.append(node)
func toggle_start(nodes_to_toggle: Array[FlowNode]) -> void: func toggle_start(nodes_to_toggle: Array[FlowNode]) -> void:
for node: FlowNode in nodes_to_toggle: for node: FlowNode in nodes_to_toggle:
if starts.has(node): if start_nodes.has(node):
starts.erase(node) start_nodes.erase(node)
else: else:
starts.append(node) start_nodes.append(node)
func toggle_traversable(node: FlowNode) -> bool: func toggle_traversable(node: FlowNode) -> bool:

View File

@@ -6,7 +6,8 @@
ambient_light_source = 2 ambient_light_source = 2
ambient_light_color = Color(0.728822, 0.728822, 0.728822, 1) ambient_light_color = Color(0.728822, 0.728822, 0.728822, 1)
[node name="FlowFieldTool" type="Node" unique_id=730814717 node_paths=PackedStringArray("raycast", "project_raycast", "camera", "camera_pivot", "position_field", "x_field", "y_field", "z_field", "x_size_field", "y_size_field", "gap_field")]
[node name="FlowFieldTool" type="Node" node_paths=PackedStringArray("raycast", "project_raycast", "camera", "camera_pivot", "position_field", "x_field", "y_field", "z_field", "x_size_field", "y_size_field", "gap_field", "save_path")]
script = ExtResource("1_e7pmn") script = ExtResource("1_e7pmn")
raycast = NodePath("CameraFocus/Camera3D/RayCast3D") raycast = NodePath("CameraFocus/Camera3D/RayCast3D")
project_raycast = NodePath("RayCast3D") project_raycast = NodePath("RayCast3D")
@@ -19,6 +20,7 @@ z_field = NodePath("Position/z")
x_size_field = NodePath("VBoxContainer/HBoxContainer/x_size") x_size_field = NodePath("VBoxContainer/HBoxContainer/x_size")
y_size_field = NodePath("VBoxContainer/HBoxContainer/y_size") y_size_field = NodePath("VBoxContainer/HBoxContainer/y_size")
gap_field = NodePath("VBoxContainer/HBoxContainer/gap") gap_field = NodePath("VBoxContainer/HBoxContainer/gap")
save_path = NodePath("VBoxContainer/FileNameInput")
metadata/_custom_type_script = "uid://05c5q1v2nv8p" metadata/_custom_type_script = "uid://05c5q1v2nv8p"
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1159336300] [node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1159336300]
@@ -87,9 +89,27 @@ text = "Extrude"
layout_mode = 2 layout_mode = 2
text = "Calculate" text = "Calculate"
<<<<<<< HEAD
[node name="Finalize" type="Button" parent="VBoxContainer" unique_id=1604655281] [node name="Finalize" type="Button" parent="VBoxContainer" unique_id=1604655281]
=======
[node name="FileNameInput" type="LineEdit" parent="VBoxContainer"]
>>>>>>> 48b1add (first flow field resource draft)
layout_mode = 2 layout_mode = 2
text = "Finalize" placeholder_text = "level title"
alignment = 1
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="Save" type="Button" parent="VBoxContainer/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Save"
[node name="Load" type="Button" parent="VBoxContainer/HBoxContainer2"]
layout_mode = 2
size_flags_horizontal = 3
text = "Load"
[node name="Position" type="HBoxContainer" parent="." unique_id=1194117729] [node name="Position" type="HBoxContainer" parent="." unique_id=1194117729]
visible = false visible = false
@@ -134,7 +154,8 @@ collision_mask = 64
[connection signal="pressed" from="VBoxContainer/ToggleBuildable" to="." method="_on_toggle_buildable_button_pressed"] [connection signal="pressed" from="VBoxContainer/ToggleBuildable" to="." method="_on_toggle_buildable_button_pressed"]
[connection signal="pressed" from="VBoxContainer/Extrude" to="." method="_on_extrude_button_pressed"] [connection signal="pressed" from="VBoxContainer/Extrude" to="." method="_on_extrude_button_pressed"]
[connection signal="pressed" from="VBoxContainer/Calculate" to="." method="_on_calculate_button_pressed"] [connection signal="pressed" from="VBoxContainer/Calculate" to="." method="_on_calculate_button_pressed"]
[connection signal="pressed" from="VBoxContainer/Finalize" to="." method="_on_finalize_button_pressed"] [connection signal="pressed" from="VBoxContainer/HBoxContainer2/Save" to="." method="_on_save_button_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/Load" to="." method="_on_load_button_pressed"]
[connection signal="text_changed" from="Position/x" to="." method="_on_x_field_changed"] [connection signal="text_changed" from="Position/x" to="." method="_on_x_field_changed"]
[connection signal="text_changed" from="Position/y" to="." method="_on_y_field_changed"] [connection signal="text_changed" from="Position/y" to="." method="_on_y_field_changed"]
[connection signal="text_changed" from="Position/z" to="." method="_on_z_field_changed"] [connection signal="text_changed" from="Position/z" to="." method="_on_z_field_changed"]

View File

@@ -0,0 +1,4 @@
class_name FlowFieldData
extends Resource
@export var nodes: Array[FlowNodeData]

View File

@@ -0,0 +1 @@
uid://ds7m1p5666qby

View File

@@ -0,0 +1,13 @@
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]

View File

@@ -0,0 +1 @@
uid://udtpnemisl0t

View File

@@ -13,6 +13,7 @@ extends Node
@export var x_size_field: LineEdit @export var x_size_field: LineEdit
@export var y_size_field: LineEdit @export var y_size_field: LineEdit
@export var gap_field: LineEdit @export var gap_field: LineEdit
@export var save_path: LineEdit
var hover: FlowNode = null var hover: FlowNode = null
var selected: Array[FlowNode] = [] var selected: Array[FlowNode] = []
@@ -44,9 +45,9 @@ func _process(delta: float) -> void:
node.set_color(Color.CORAL) node.set_color(Color.CORAL)
else: else:
node.set_color(Color.BLACK) node.set_color(Color.BLACK)
if flow_field.goals.has(node): if flow_field.goal_nodes.has(node):
node.set_color(Color.BLUE) node.set_color(Color.BLUE)
if flow_field.starts.has(node): if flow_field.start_nodes.has(node):
node.set_color(Color.PINK) node.set_color(Color.PINK)
if selected.has(node): if selected.has(node):
node.set_color(Color.GREEN) node.set_color(Color.GREEN)
@@ -70,6 +71,14 @@ func _unhandled_input(event: InputEvent) -> void:
vector_dirty = true vector_dirty = true
if event is InputEventMouseButton and event.button_index == 2 and selected.size() > 0: if event is InputEventMouseButton and event.button_index == 2 and selected.size() > 0:
selected = [] 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: func _on_x_field_changed(text: String) -> void:
@@ -138,11 +147,6 @@ func _on_toggle_buildable_button_pressed() -> void:
flow_field.toggle_buildable(node) flow_field.toggle_buildable(node)
func _on_finalize_button_pressed() -> void:
var packed_scene: PackedScene = PackedScene.new()
packed_scene.pack(flow_field)
ResourceSaver.save(packed_scene, "res://flow_field_tool_output.tscn")
#TODO: This doesnt work as you'd expect because of physics frames #TODO: This doesnt work as you'd expect because of physics frames
func _on_project_downwards_button_pressed() -> void: func _on_project_downwards_button_pressed() -> void:
for node: FlowNode in selected: for node: FlowNode in selected:
@@ -154,3 +158,32 @@ func _on_project_downwards_button_pressed() -> void:
await get_tree().physics_frame await get_tree().physics_frame
if project_raycast.is_colliding(): if project_raycast.is_colliding():
node.global_position = project_raycast.get_collision_point() 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)

View File

@@ -3,9 +3,10 @@ extends StaticBody3D
@export var connections: Array[FlowNode] @export var connections: Array[FlowNode]
@export var visualisers: Array[Node3D] @export var visualisers: Array[Node3D]
var visual_scene: PackedScene = preload("res://Scenes/FlowField/cube2.tscn")
@export var traversable: bool = true @export var traversable: bool = true
@export var buildable: bool = true @export var buildable: bool = true
var visual_scene: PackedScene = preload("res://Scenes/FlowField/cube2.tscn")
var best_path: FlowNode : var best_path: FlowNode :
get(): get():
return best_path return best_path

Binary file not shown.

View File

@@ -0,0 +1,37 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bhroqr4s1qso5"
path="res://.godot/imported/cave_level.glb-2f9529a411c81ae92670ed22d2cc2ea3.scn"
[deps]
source_file="res://Worlds/GreenPlanet/Levels/Cave/cave_level.glb"
dest_files=["res://.godot/imported/cave_level.glb-2f9529a411c81ae92670ed22d2cc2ea3.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

35
cave.tscn Normal file
View File

@@ -0,0 +1,35 @@
[gd_scene load_steps=7 format=3 uid="uid://8jabmf7c6p71"]
[ext_resource type="PackedScene" uid="uid://bhroqr4s1qso5" path="res://Worlds/GreenPlanet/Levels/Cave/cave_level.glb" id="1_yhhov"]
[ext_resource type="PackedScene" uid="uid://b7dwsqfmdqr8" path="res://Scenes/FlowField/flow_field.tscn" id="2_shk3w"]
[ext_resource type="PackedScene" uid="uid://cccowrgelgswj" path="res://Scenes/FlowField/flow_field_tool.tscn" id="3_23xot"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ads45"]
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
[sub_resource type="Sky" id="Sky_shk3w"]
sky_material = SubResource("ProceduralSkyMaterial_ads45")
[sub_resource type="Environment" id="Environment_23xot"]
background_mode = 2
sky = SubResource("Sky_shk3w")
tonemap_mode = 2
glow_enabled = true
[node name="Cave" type="Node3D"]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_23xot")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
shadow_enabled = true
[node name="cave_level" parent="." instance=ExtResource("1_yhhov")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.99917, 0)
[node name="FlowField" parent="." instance=ExtResource("2_shk3w")]
[node name="FlowFieldTool" parent="." node_paths=PackedStringArray("flow_field") instance=ExtResource("3_23xot")]
flow_field = NodePath("../FlowField")