forked from woofmeow/straywild
Add gathering, unified inventory, and real-time world
This commit is contained in:
parent
173371e6fc
commit
fa57edca83
113 changed files with 6700 additions and 1307 deletions
114
world/digging/diggable_area_3d.gd
Normal file
114
world/digging/diggable_area_3d.gd
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
@tool
|
||||
class_name DiggableArea3D
|
||||
extends Node3D
|
||||
|
||||
@export var area_id: StringName
|
||||
@export_node_path("Node3D") var terrain_source: NodePath
|
||||
@export var surface_materials: Array[StringName] = []
|
||||
@export var generation_bounds := Rect2(-50.0, -50.0, 100.0, 100.0)
|
||||
@export_range(-100.0, 100.0, 0.01) var minimum_global_y: float = -100.0
|
||||
@export_range(-100.0, 100.0, 0.01) var maximum_global_y: float = 100.0
|
||||
@export_range(0.0, 1.0, 0.01) var minimum_up_dot: float = 0.6
|
||||
|
||||
|
||||
func get_surface_triangles() -> Array[PackedVector3Array]:
|
||||
var triangles: Array[PackedVector3Array] = []
|
||||
if area_id.is_empty() or surface_materials.is_empty():
|
||||
return triangles
|
||||
var terrain_root: Node = get_node_or_null(terrain_source)
|
||||
if terrain_root == null:
|
||||
return triangles
|
||||
for mesh_instance: MeshInstance3D in _collect_mesh_instances(terrain_root):
|
||||
var mesh: Mesh = mesh_instance.mesh
|
||||
if mesh == null:
|
||||
continue
|
||||
for surface_index: int in mesh.get_surface_count():
|
||||
var material: Material = mesh_instance.get_active_material(surface_index)
|
||||
if (
|
||||
material == null
|
||||
or not surface_materials.has(StringName(material.resource_name))
|
||||
):
|
||||
continue
|
||||
_append_surface_triangles(
|
||||
triangles,
|
||||
mesh_instance,
|
||||
mesh.surface_get_arrays(surface_index),
|
||||
)
|
||||
return triangles
|
||||
|
||||
|
||||
func _append_surface_triangles(
|
||||
result: Array[PackedVector3Array],
|
||||
mesh_instance: MeshInstance3D,
|
||||
arrays: Array,
|
||||
) -> void:
|
||||
if arrays.size() <= Mesh.ARRAY_INDEX:
|
||||
return
|
||||
var vertices := arrays[Mesh.ARRAY_VERTEX] as PackedVector3Array
|
||||
var indices := arrays[Mesh.ARRAY_INDEX] as PackedInt32Array
|
||||
if vertices.is_empty():
|
||||
return
|
||||
if indices.is_empty():
|
||||
for vertex_index: int in range(0, vertices.size() - 2, 3):
|
||||
_append_triangle(
|
||||
result,
|
||||
mesh_instance.to_global(vertices[vertex_index]),
|
||||
mesh_instance.to_global(vertices[vertex_index + 1]),
|
||||
mesh_instance.to_global(vertices[vertex_index + 2]),
|
||||
)
|
||||
return
|
||||
for index_offset: int in range(0, indices.size() - 2, 3):
|
||||
_append_triangle(
|
||||
result,
|
||||
mesh_instance.to_global(vertices[indices[index_offset]]),
|
||||
mesh_instance.to_global(vertices[indices[index_offset + 1]]),
|
||||
mesh_instance.to_global(vertices[indices[index_offset + 2]]),
|
||||
)
|
||||
|
||||
|
||||
func _append_triangle(
|
||||
result: Array[PackedVector3Array],
|
||||
a: Vector3,
|
||||
b: Vector3,
|
||||
c: Vector3,
|
||||
) -> void:
|
||||
if (
|
||||
a.y < minimum_global_y
|
||||
or b.y < minimum_global_y
|
||||
or c.y < minimum_global_y
|
||||
or a.y > maximum_global_y
|
||||
or b.y > maximum_global_y
|
||||
or c.y > maximum_global_y
|
||||
):
|
||||
return
|
||||
var center := (a + b + c) / 3.0
|
||||
if not generation_bounds.has_point(Vector2(center.x, center.z)):
|
||||
return
|
||||
var cross := (b - a).cross(c - a)
|
||||
if cross.length_squared() <= 0.0000001:
|
||||
return
|
||||
if absf(cross.normalized().dot(Vector3.UP)) < minimum_up_dot:
|
||||
return
|
||||
result.append(PackedVector3Array([a, b, c]))
|
||||
|
||||
|
||||
func _collect_mesh_instances(root: Node) -> Array[MeshInstance3D]:
|
||||
var meshes: Array[MeshInstance3D] = []
|
||||
if root is MeshInstance3D:
|
||||
meshes.append(root as MeshInstance3D)
|
||||
for child: Node in root.get_children():
|
||||
meshes.append_array(_collect_mesh_instances(child))
|
||||
return meshes
|
||||
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings := PackedStringArray()
|
||||
if area_id.is_empty():
|
||||
warnings.append("Diggable area ID is required.")
|
||||
if get_node_or_null(terrain_source) == null:
|
||||
warnings.append("Diggable area terrain source is unavailable.")
|
||||
if surface_materials.is_empty():
|
||||
warnings.append("At least one terrain material is required.")
|
||||
if maximum_global_y < minimum_global_y:
|
||||
warnings.append("Maximum height must not be below minimum height.")
|
||||
return warnings
|
||||
1
world/digging/diggable_area_3d.gd.uid
Normal file
1
world/digging/diggable_area_3d.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://d33f4164b78ww
|
||||
Loading…
Add table
Add a link
Reference in a new issue