From 703e75d1d8503da635ebcffdb8430e34b1d9c1c1 Mon Sep 17 00:00:00 2001 From: Lexi Quinn Date: Wed, 10 Sep 2025 21:55:51 +1000 Subject: [PATCH] first flow field resource draft --- PCs/hero.gd | 5 ++ PCs/hud.gd | 8 +++ Scenes/FlowField/flow_field.gd | 51 +++++++++++++----- Scenes/FlowField/flow_field_tool.tscn | 27 ++++++++-- Scripts/Resources/flow_field_data.gd | 4 ++ Scripts/Resources/flow_field_data.gd.uid | 1 + Scripts/Resources/flow_node_data.gd | 13 +++++ Scripts/Resources/flow_node_data.gd.uid | 1 + Scripts/flow_field_tool.gd | 47 +++++++++++++--- Scripts/flow_node.gd | 3 +- Worlds/GreenPlanet/Levels/Cave/cave_level.glb | Bin 0 -> 12692 bytes .../Levels/Cave/cave_level.glb.import | 37 +++++++++++++ cave.tscn | 35 ++++++++++++ 13 files changed, 208 insertions(+), 24 deletions(-) create mode 100644 Scripts/Resources/flow_field_data.gd create mode 100644 Scripts/Resources/flow_field_data.gd.uid create mode 100644 Scripts/Resources/flow_node_data.gd create mode 100644 Scripts/Resources/flow_node_data.gd.uid create mode 100644 Worlds/GreenPlanet/Levels/Cave/cave_level.glb create mode 100644 Worlds/GreenPlanet/Levels/Cave/cave_level.glb.import create mode 100644 cave.tscn diff --git a/PCs/hero.gd b/PCs/hero.gd index 67b2cf3..f3e4c6b 100644 --- a/PCs/hero.gd +++ b/PCs/hero.gd @@ -94,6 +94,11 @@ func set_zoom_factor(value: float) -> 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(): ears.make_current() camera.make_current() diff --git a/PCs/hud.gd b/PCs/hud.gd index 29d1c96..6d156cf 100644 --- a/PCs/hud.gd +++ b/PCs/hud.gd @@ -48,6 +48,14 @@ func _ready() -> void: 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: hot_wheel.visible = true diff --git a/Scenes/FlowField/flow_field.gd b/Scenes/FlowField/flow_field.gd index 12fb385..f7aa77b 100644 --- a/Scenes/FlowField/flow_field.gd +++ b/Scenes/FlowField/flow_field.gd @@ -3,12 +3,16 @@ extends Node3D signal path_updated() +@export var data_file: FlowFieldData @export var flow_node_scene: PackedScene -@export var nodes: Array[FlowNode] = [] -@export var goals: Array[FlowNode] = [] -@export var starts: Array[FlowNode] = [] +@export var start_points: Array[Node3D] +@export var goal_points: Array[Node3D] @export var nodes_visible: bool = false +var nodes: Array[FlowNode] = [] +var start_nodes: Array[FlowNode] = [] +var goal_nodes: Array[FlowNode] = [] + func _ready() -> void: if !nodes_visible: @@ -16,6 +20,27 @@ func _ready() -> void: 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") func _process(delta: float) -> void: if !nodes_visible: @@ -27,9 +52,9 @@ func _process(delta: float) -> void: node.set_color(Color.CORAL) else: node.set_color(Color.BLACK) - if goals.has(node): + if goal_nodes.has(node): node.set_color(Color.BLUE) - if starts.has(node): + if start_nodes.has(node): node.set_color(Color.PINK) if magic_node: magic_node.set_color(Color.DEEP_PINK) @@ -66,7 +91,7 @@ func get_closest_buildable_point(pos: Vector3) -> FlowNode: func test_traversability() -> bool: - for node: FlowNode in starts: + for node: FlowNode in start_nodes: while node.best_path != null: if node.best_path.traversable: node = node.best_path @@ -88,7 +113,7 @@ func iterate_search(search_frontier: Array[FlowNode], reached: Array[FlowNode]) func calculate() -> void: var reached: Array[FlowNode] = [] var search_frontier: Array[FlowNode] = [] - for node: FlowNode in goals: + for node: FlowNode in goal_nodes: node.best_path = null reached.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: for node: FlowNode in nodes_to_toggle: - if goals.has(node): - goals.erase(node) + if goal_nodes.has(node): + goal_nodes.erase(node) else: - goals.append(node) + goal_nodes.append(node) func toggle_start(nodes_to_toggle: Array[FlowNode]) -> void: for node: FlowNode in nodes_to_toggle: - if starts.has(node): - starts.erase(node) + if start_nodes.has(node): + start_nodes.erase(node) else: - starts.append(node) + start_nodes.append(node) func toggle_traversable(node: FlowNode) -> bool: diff --git a/Scenes/FlowField/flow_field_tool.tscn b/Scenes/FlowField/flow_field_tool.tscn index a56dfb7..2e18015 100644 --- a/Scenes/FlowField/flow_field_tool.tscn +++ b/Scenes/FlowField/flow_field_tool.tscn @@ -6,7 +6,8 @@ ambient_light_source = 2 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") raycast = NodePath("CameraFocus/Camera3D/RayCast3D") project_raycast = NodePath("RayCast3D") @@ -19,6 +20,7 @@ z_field = NodePath("Position/z") x_size_field = NodePath("VBoxContainer/HBoxContainer/x_size") y_size_field = NodePath("VBoxContainer/HBoxContainer/y_size") gap_field = NodePath("VBoxContainer/HBoxContainer/gap") +save_path = NodePath("VBoxContainer/FileNameInput") metadata/_custom_type_script = "uid://05c5q1v2nv8p" [node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1159336300] @@ -87,9 +89,27 @@ text = "Extrude" layout_mode = 2 text = "Calculate" +<<<<<<< HEAD [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 -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] 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/Extrude" to="." method="_on_extrude_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/y" to="." method="_on_y_field_changed"] [connection signal="text_changed" from="Position/z" to="." method="_on_z_field_changed"] diff --git a/Scripts/Resources/flow_field_data.gd b/Scripts/Resources/flow_field_data.gd new file mode 100644 index 0000000..b0728e8 --- /dev/null +++ b/Scripts/Resources/flow_field_data.gd @@ -0,0 +1,4 @@ +class_name FlowFieldData +extends Resource + +@export var nodes: Array[FlowNodeData] diff --git a/Scripts/Resources/flow_field_data.gd.uid b/Scripts/Resources/flow_field_data.gd.uid new file mode 100644 index 0000000..335f8d6 --- /dev/null +++ b/Scripts/Resources/flow_field_data.gd.uid @@ -0,0 +1 @@ +uid://ds7m1p5666qby diff --git a/Scripts/Resources/flow_node_data.gd b/Scripts/Resources/flow_node_data.gd new file mode 100644 index 0000000..43819a3 --- /dev/null +++ b/Scripts/Resources/flow_node_data.gd @@ -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] diff --git a/Scripts/Resources/flow_node_data.gd.uid b/Scripts/Resources/flow_node_data.gd.uid new file mode 100644 index 0000000..bb6626d --- /dev/null +++ b/Scripts/Resources/flow_node_data.gd.uid @@ -0,0 +1 @@ +uid://udtpnemisl0t diff --git a/Scripts/flow_field_tool.gd b/Scripts/flow_field_tool.gd index fd0f829..3aaf020 100644 --- a/Scripts/flow_field_tool.gd +++ b/Scripts/flow_field_tool.gd @@ -13,6 +13,7 @@ extends Node @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] = [] @@ -44,9 +45,9 @@ func _process(delta: float) -> void: node.set_color(Color.CORAL) else: node.set_color(Color.BLACK) - if flow_field.goals.has(node): + if flow_field.goal_nodes.has(node): node.set_color(Color.BLUE) - if flow_field.starts.has(node): + if flow_field.start_nodes.has(node): node.set_color(Color.PINK) if selected.has(node): node.set_color(Color.GREEN) @@ -70,6 +71,14 @@ func _unhandled_input(event: InputEvent) -> void: 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: @@ -138,11 +147,6 @@ func _on_toggle_buildable_button_pressed() -> void: 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 func _on_project_downwards_button_pressed() -> void: for node: FlowNode in selected: @@ -154,3 +158,32 @@ func _on_project_downwards_button_pressed() -> void: 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) diff --git a/Scripts/flow_node.gd b/Scripts/flow_node.gd index 3a8d431..965006b 100644 --- a/Scripts/flow_node.gd +++ b/Scripts/flow_node.gd @@ -3,9 +3,10 @@ extends StaticBody3D @export var connections: Array[FlowNode] @export var visualisers: Array[Node3D] -var visual_scene: PackedScene = preload("res://Scenes/FlowField/cube2.tscn") @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 diff --git a/Worlds/GreenPlanet/Levels/Cave/cave_level.glb b/Worlds/GreenPlanet/Levels/Cave/cave_level.glb new file mode 100644 index 0000000000000000000000000000000000000000..0964657e1f082c7885ab2e5c1d653a4f5ba7fb97 GIT binary patch literal 12692 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