@tool
@icon("res://addons/func_godot/icons/icon_slipgate3d.svg")
class_name FuncGodotFGDSolidClass extends FuncGodotFGDEntityClass
## FGD SolidClass entity definition that generates a mesh from [FuncGodotData.BrushData].
##
## A [MeshInstance3D] will be generated by [FuncGodotMap] according to this definition's Visual Build settings. 
## If [member FuncGodotFGDEntityClass.node_class] inherits [CollisionObject3D] 
## then one or more [CollisionShape3D] nodes will be generated according to Collision Build settings.
##
## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
## @tutorial(Level Design Book: Entity Types and Settings): https://book.leveldesignbook.com/appendix/resources/formats/fgd#entity-types-and-settings-basic
## @tutorial(Valve Developer Wiki FGD Article): https://developer.valvesoftware.com/wiki/FGD#Class_Types_and_Properties
## @tutorial(dumptruck_ds' Quake Mapping Entities Tutorial): https://www.youtube.com/watch?v=gtL9f6_N2WM

enum SpawnType {
	WORLDSPAWN = 0, ## Builds the geometry of this entity relative to the FuncGodotMap position.
	MERGE_WORLDSPAWN = 1, ## This entity's geometry is merged with the [b]worldspawn[/b] entity and this entity is removed. Behavior mimics [b]func_group[/b] in modern Quake compilers.
	ENTITY = 2, ## This entity is built as its own object. It finds the origin of the entity based on [member origin_type].
}

enum OriginType {
	AVERAGED = 0, ## Use averaged brush vertices for center position. This is the old Qodot behavior.
	ABSOLUTE = 1, ## Use [code]origin[/code] class property in global coordinates as the center position.
	RELATIVE = 2, ## Calculate center position using [code]origin[/code] class property as an offset to the entity's bounding box center.
	BRUSH = 3, ## Calculate center position based on the bounding box center of all brushes using the 'origin' texture specified in the [FuncGodotMapSettings]. If no Origin Brush is found, fall back to BOUNDS_CENTER. This is the default option and recommended for most entities.
	BOUNDS_CENTER = 4, ## Use the center of the entity's bounding box for center position.
	BOUNDS_MINS = 5, ## Use the lowest bounding box coordinates for center position. This is standard Quake and Half-Life brush entity behavior.
	BOUNDS_MAXS = 6, ## Use the highest bounding box coordinates for center position.
}

enum CollisionShapeType {
	NONE, ## No collision shape is built. Useful for decorative geometry like vines, hanging wires, grass, etc...
	CONVEX, ## Will build a Convex CollisionShape3D for each brush used to make this Solid Class. Required for non-[StaticBody3D] nodes like [Area3D].
	CONCAVE ## Should have a concave collision shape
}

## Controls whether this Solid Class is the worldspawn, is combined with the worldspawn, or is spawned as its own free-standing entity.
@export var spawn_type: SpawnType = SpawnType.ENTITY
## Controls how this Solid Class determines its center position. Only valid if [member spawn_type] is set to ENTITY.
@export var origin_type: OriginType = OriginType.BRUSH

@export_group("Visual Build")
## Controls whether a [MeshInstance3D] is built for this Solid Class.
@export var build_visuals : bool = true
## Global illumination mode for the generated [MeshInstance3D]. Setting to [b]GI_MODE_STATIC[/b] will unwrap the mesh's UV2 during build.
@export var global_illumination_mode : GeometryInstance3D.GIMode = GeometryInstance3D.GI_MODE_STATIC
## @deprecated: Use [member global_illumination_mode] instead. [br]Sets generated [MeshInstance3D] to be available for UV2 unwrapping after [FuncGodotMap] build. Utilized in baked lightmapping.
@export var use_in_baked_light : bool = true
## Shadow casting setting allows for further lightmapping customization.
@export var shadow_casting_setting : GeometryInstance3D.ShadowCastingSetting = GeometryInstance3D.SHADOW_CASTING_SETTING_ON
## Automatically build [OccluderInstance3D] for this entity.
@export var build_occlusion : bool = false
## This Solid Class' [MeshInstance3D] will only be visible for [Camera3D]s whose cull mask includes any of these render layers.
@export_flags_3d_render var render_layers: int = 1

@export_group("Collision Build")
## Controls how collisions are built for this Solid Class.
@export var collision_shape_type: CollisionShapeType = CollisionShapeType.CONVEX
## The physics layers this Solid Class can be detected in.
@export_flags_3d_physics var collision_layer: int = 1
## The physics layers this Solid Class scans.
@export_flags_3d_physics var collision_mask: int = 1
## The priority used to solve colliding when penetration occurs. The higher the priority is, the lower the penetration into the Solid Class will be. This can for example be used to prevent the player from breaking through the boundaries of a level.
@export var collision_priority: float = 1.0
## The collision margin for the Solid Class' collision shapes. Not used in Godot Physics. See [Shape3D] for details.
@export var collision_shape_margin: float = 0.04

## The following properties tell FuncGodot to add a [i]"func_godot_mesh_data"[/i] Dictionary to the metadata of the generated node upon build. 
## This data is parallelized, so that each element of the array is ordered to reference the same face in the mesh.
@export_group("Mesh Metadata")
## Add a texture lookup table to the generated node's metadata on build.[br][br] 
## The data is split between an [Array] of [StringName] called [i]"texture_names"[/i] containing all currently used texture materials 
## and a [PackedInt32Array] called [i]"textures"[/i] where each element is an index corresponding to the [i]"texture_names"[/i] entries.
@export var add_textures_metadata: bool = false
## Add a [PackedVector3Array] called [i]"vertices"[/i] to the generated node's metadata on build.[br][br] 
## This is a list of every vertex in the generated node's [MeshInstance3D]. Every 3 vertices represent a single face.
@export var add_vertex_metadata: bool = false
## Add a [PackedVector3Array] called [i]"positions"[/i] to the generated node's metadata on build.[br][br] 
## This is a list of positions for each face, local to the generated node, calculated by averaging the vertices to find the face's center.
@export var add_face_position_metadata: bool = false
## Add a [PackedVector3Array] called [i]"normals"[/i] to the generated node's metadata on build.[br][br] 
## Contains a list of each face's normal.
@export var add_face_normal_metadata: bool = false
## Add a [Dictionary] called [i]"collision_shape_to_face_indices_map"[/i] in the generated node's metadata on build.[br][br] 
## Contains keys of strings, which are the names of child [CollisionShape3D] nodes, and values of
## [PackedInt32Array], containing indices of that child's faces.[br][br]
## For example, an element of [br][br][code]{ "entity_1_brush_0_collision_shape" : [0, 1, 3] }[/code][br][br]
## shows that this solid class has been generated with one child collision shape named 
## [i]entity_1_brush_0_collision_shape[/i] which handles 3 faces of the mesh with collision, at indices 0, 1, and 3.
@export var add_collision_shape_to_face_indices_metadata : bool = false
## [s]Add a [Dictionary] called [i]"collision_shape_to_face_range_map"[/i] in the generated node's metadata on build.[br][br] 
## Contains keys of strings, which are the names of child [CollisionShape3D] nodes, and values of
## [Vector2i], where [i]X[/i] represents the starting index of that child's faces and [i]Y[/i] represents the
## ending index.[br][br]
## For example, an element of [br][br][code]{ "entity_1_brush_0_collision_shape" : Vector2i(0, 15) }[/code][br][br]
## shows that this solid class has been generated with one child collision shape named 
## [i]entity_1_brush_0_collision_shape[/i] which handles the first 15 faces of the parts of the mesh with collision.[/s]
## @deprecated: No longer supported or planned as of 2025.7, but retained in case a contributor provides an appropriate solution in the future.
@export var add_collision_shape_face_range_metadata: bool = false

@export_group("Scripting")
## An optional [Script] file to attach to the node generated on map build.
@export var script_class: Script

func _init():
	prefix = "@SolidClass"
