mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-16 16:33:47 +00:00
Updated func_godot
This commit is contained in:
parent
d8d348640c
commit
01a852de9b
170 changed files with 1705 additions and 2296 deletions
|
|
@ -1,5 +1,5 @@
|
|||
@icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
|
||||
class_name FuncGodotFGDEntityClass extends Resource
|
||||
@abstract class_name FuncGodotFGDEntityClass extends Resource
|
||||
## Entity definition template. WARNING! Not to be used directly! Use [FuncGodotFGDBaseClass], [FuncGodotFGDSolidClass], or [FuncGodotFGDPointClass] instead.
|
||||
##
|
||||
## Entity definition template. It holds all of the common entity class properties shared between [FuncGodotFGDBaseClass], [FuncGodotFGDSolidClass], or [FuncGodotFGDPointClass].
|
||||
|
|
@ -28,24 +28,24 @@ var prefix: String = ""
|
|||
|
||||
## Key value pair properties that will appear in the map editor. After building the [FuncGodotMap] in Godot, these properties will be added to a [Dictionary]
|
||||
## that gets applied to the generated node, as long as that node is a tool script with an exported `func_godot_properties` Dictionary.
|
||||
@export var class_properties : Dictionary = {}
|
||||
@export var class_properties : Dictionary[String, Variant] = {}
|
||||
|
||||
## Map editor descriptions for previously defined key value pair properties. Optional but recommended.
|
||||
@export var class_property_descriptions : Dictionary = {}
|
||||
@export var class_property_descriptions : Dictionary[String, Variant] = {}
|
||||
|
||||
## Automatically applies entity class properties to matching properties in the generated node.
|
||||
## When using this feature, class properties need to be the correct type or you may run into errors on map build.
|
||||
@export var auto_apply_to_matching_node_properties : bool = false
|
||||
|
||||
## Appearance properties for the map editor. See the Valve Developer Wiki and TrenchBroom documentation for more information.
|
||||
@export var meta_properties : Dictionary = {
|
||||
@export var meta_properties : Dictionary[String, Variant] = {
|
||||
"size": AABB(Vector3(-8, -8, -8), Vector3(8, 8, 8)),
|
||||
"color": Color(0.8, 0.8, 0.8)
|
||||
}
|
||||
|
||||
@export_group("Node Generation")
|
||||
|
||||
## Node to generate on map build. This can be a built-in Godot class, a GDScript class, or a GDExtension class.
|
||||
## Node to generate on map build. This can be a built-in Godot class, a Script class, or a GDExtension class.
|
||||
## For Point Class entities that use Scene File instantiation leave this blank.
|
||||
@export var node_class := ""
|
||||
|
||||
|
|
@ -54,6 +54,9 @@ var prefix: String = ""
|
|||
## Nodes will be named `"entity_" + name_property`. An entity's name should be unique, otherwise you may run into unexpected behavior.
|
||||
@export var name_property := ""
|
||||
|
||||
## Optional array of node groups to add the generated node to.
|
||||
@export var node_groups : Array[String] = []
|
||||
|
||||
## Parses the definition and outputs it into the FGD format.
|
||||
func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
|
||||
# Class prefix
|
||||
|
|
@ -231,3 +234,17 @@ func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors =
|
|||
res += "]" + FuncGodotUtil.newline()
|
||||
|
||||
return res
|
||||
|
||||
func retrieve_all_class_properties(properties: Dictionary[String, Variant] = {}) -> Dictionary[String, Variant]:
|
||||
for key in class_properties.keys():
|
||||
properties[key] = class_properties[key]
|
||||
for b in base_classes:
|
||||
properties = b.retrieve_all_class_properties(properties)
|
||||
return properties
|
||||
|
||||
func retrieve_all_class_property_descriptions(descriptions: Dictionary[String, Variant] = {}) -> Dictionary[String, Variant]:
|
||||
for key in class_property_descriptions.keys():
|
||||
descriptions[key] = class_property_descriptions[key]
|
||||
for b in base_classes:
|
||||
descriptions = b.retrieve_all_class_property_descriptions(descriptions)
|
||||
return descriptions
|
||||
|
|
|
|||
|
|
@ -23,28 +23,25 @@ func export_button() -> void:
|
|||
do_export_file(target_map_editor)
|
||||
|
||||
func do_export_file(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM, fgd_output_folder: String = "") -> void:
|
||||
if not Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
if fgd_output_folder.is_empty():
|
||||
fgd_output_folder = FuncGodotLocalConfig.get_setting(FuncGodotLocalConfig.PROPERTY.FGD_OUTPUT_FOLDER) as String
|
||||
if fgd_output_folder.is_empty():
|
||||
print("Skipping export: No game config folder")
|
||||
printerr("Skipping export: No game config folder")
|
||||
return
|
||||
|
||||
if fgd_name == "":
|
||||
print("Skipping export: Empty FGD name")
|
||||
printerr("Skipping export: Empty FGD name")
|
||||
|
||||
if not DirAccess.dir_exists_absolute(fgd_output_folder):
|
||||
if DirAccess.make_dir_recursive_absolute(fgd_output_folder) != OK:
|
||||
print("Skipping export: Failed to create directory")
|
||||
printerr("Skipping export: Failed to create directory")
|
||||
return
|
||||
|
||||
var fgd_file = fgd_output_folder.path_join(fgd_name + ".fgd")
|
||||
|
||||
var file_obj := FileAccess.open(fgd_file, FileAccess.WRITE)
|
||||
if not file_obj:
|
||||
print("Failed to open file for writing: ", fgd_file)
|
||||
printerr("Failed to open file for writing: ", fgd_file)
|
||||
return
|
||||
|
||||
print("Exporting FGD to ", fgd_file)
|
||||
|
|
@ -76,6 +73,9 @@ func do_export_file(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMa
|
|||
## Array of resources that inherit from [FuncGodotFGDEntityClass]. This array defines the entities that will be added to the exported FGD file and the nodes that will be generated in a [FuncGodotMap].
|
||||
@export var entity_definitions: Array[Resource] = []
|
||||
|
||||
## Toggles whether [FuncGodotFGDModelPointClass] resources will generate models from their [PackedScene] files.
|
||||
@export var generate_model_point_class_models: bool = true
|
||||
|
||||
func build_class_text(target_editor: FuncGodotTargetMapEditors = FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
|
||||
var res : String = ""
|
||||
|
||||
|
|
@ -91,6 +91,8 @@ func build_class_text(target_editor: FuncGodotTargetMapEditors = FuncGodotTarget
|
|||
continue
|
||||
if ent.func_godot_internal:
|
||||
continue
|
||||
if ent is FuncGodotFGDModelPointClass:
|
||||
ent._model_generation_enabled = generate_model_point_class_models
|
||||
|
||||
var ent_text = ent.build_def_text(target_editor)
|
||||
res += ent_text
|
||||
|
|
@ -127,9 +129,9 @@ func get_entity_definitions() -> Dictionary[String, FuncGodotFGDEntityClass]:
|
|||
|
||||
if ent is FuncGodotFGDPointClass or ent is FuncGodotFGDSolidClass:
|
||||
var entity_def = ent.duplicate()
|
||||
var meta_properties := {}
|
||||
var class_properties := {}
|
||||
var class_property_descriptions := {}
|
||||
var meta_properties: Dictionary[String, Variant] = {}
|
||||
var class_properties: Dictionary[String, Variant] = {}
|
||||
var class_property_descriptions: Dictionary[String, Variant] = {}
|
||||
|
||||
for base_class in _generate_base_class_list(entity_def):
|
||||
for meta_property in base_class.meta_properties:
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ enum TargetMapEditor {
|
|||
## Creates a .gdignore file in the model export folder to prevent Godot importing the display models. Only needs to be generated once.
|
||||
@export_tool_button("Generate GD Ignore File", "FileAccess") var generate_gd_ignore_file : Callable = _generate_gd_ignore_file
|
||||
|
||||
var _model_generation_enabled: bool = false
|
||||
|
||||
func _generate_gd_ignore_file() -> void:
|
||||
if Engine.is_editor_hint():
|
||||
var path: String = _get_game_path().path_join(_get_model_folder())
|
||||
|
|
@ -45,7 +47,9 @@ func _generate_gd_ignore_file() -> void:
|
|||
|
||||
## Builds and saves the display model into the specified destination, then parses the definition and outputs it into the FGD format.
|
||||
func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
|
||||
_generate_model()
|
||||
if _model_generation_enabled:
|
||||
_generate_model()
|
||||
_model_generation_enabled = false
|
||||
return super()
|
||||
|
||||
func _generate_model() -> void:
|
||||
|
|
@ -65,7 +69,10 @@ func _generate_model() -> void:
|
|||
if target_map_editor == TargetMapEditor.TRENCHBROOM:
|
||||
const model_key: String = "model"
|
||||
if scale_expression.is_empty():
|
||||
meta_properties[model_key] = '"%s"' % _get_local_path()
|
||||
meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [
|
||||
_get_local_path(),
|
||||
ProjectSettings.get_setting("func_godot/default_inverse_scale_factor", 32.0) as float
|
||||
]
|
||||
else:
|
||||
meta_properties[model_key] = '{"path": "%s", "scale": %s }' % [
|
||||
_get_local_path(),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
class_name FuncGodotFGDPointClass extends FuncGodotFGDEntityClass
|
||||
## FGD PointClass entity definition.
|
||||
##
|
||||
## A resource used to define an FGD PointClass entity. PointClass entities can use either the [member FuncGodotFGDEntityClass.node_class]
|
||||
## A resource used to define an FGD Point Class entity. PointClass entities can use either the [member FuncGodotFGDEntityClass.node_class]
|
||||
## or the [member scene_file] property to tell [FuncGodotMap] what to generate on map build.
|
||||
##
|
||||
## @tutorial(Quake Wiki Entity Article): https://quakewiki.org/wiki/Entity
|
||||
|
|
@ -17,15 +17,12 @@ class_name FuncGodotFGDPointClass extends FuncGodotFGDEntityClass
|
|||
func _init() -> void:
|
||||
prefix = "@PointClass"
|
||||
|
||||
@export_group ("Scene")
|
||||
## An optional [PackedScene] file to instantiate on map build. Overrides [member FuncGodotFGDEntityClass.node_class] and [member script_class].
|
||||
@export var scene_file: PackedScene
|
||||
|
||||
@export_group ("Scripting")
|
||||
## An optional [Script] resource to attach to the node generated on map build. Ignored if [member scene_file] is specified.
|
||||
@export var script_class: Script
|
||||
|
||||
@export_group("Build")
|
||||
## Toggles whether entity will use `angles`, `mangle`, or `angle` to determine rotations on [FuncGodotMap] build, prioritizing the key value pairs in that order.
|
||||
## Set to [code]false[/code] if you would like to define how the generated node is rotated yourself.
|
||||
@export var apply_rotation_on_map_build : bool = true
|
||||
|
|
@ -33,3 +30,91 @@ func _init() -> void:
|
|||
## Toggles whether entity will use `scale` to determine the generated node or scene's scale. This is performed on the top level node.
|
||||
## The property can be a [float], [Vector3], or [Vector2]. Set to [code]false[/code] if you would like to define how the generated node is scaled yourself.
|
||||
@export var apply_scale_on_map_build: bool = true
|
||||
|
||||
## An optional [Array] of [FuncGodotFGDPointClassDisplayDescriptor] that describes how this Point Entity should appear in the map editor.
|
||||
## When using multiple display descriptors, only the first element found without [member FuncGodotFGDPointClassDisplayDescriptor.conditional]
|
||||
## will be used as the default display asset. If no descriptor is found without a condition, the last descriptor will become the default.[br][br]
|
||||
## Conditional display descriptors will be written to the FGD in the order set in the array.[br][br]
|
||||
## [color=orange]WARNING:[/color] Multiple descriptors are only supported by TrenchBroom! They will be omitted on export when
|
||||
## [member FuncGodotFGDFile.target_map_editor] is not set to [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM].
|
||||
@export var display_descriptors: Array[FuncGodotFGDPointClassDisplayDescriptor] = []
|
||||
|
||||
func _build_model_branch_text(descriptor: FuncGodotFGDPointClassDisplayDescriptor) -> String:
|
||||
if not descriptor:
|
||||
return ''
|
||||
|
||||
var model_string: String = ''
|
||||
var uses_options: bool = false
|
||||
|
||||
if not descriptor.scale.is_empty() or not descriptor.skin.is_empty() or not descriptor.frame.is_empty():
|
||||
uses_options = true
|
||||
|
||||
if not uses_options:
|
||||
return descriptor.display_asset_path
|
||||
|
||||
model_string = '{ \"path\": %s' % descriptor.display_asset_path
|
||||
|
||||
if not descriptor.skin.is_empty():
|
||||
model_string += ', \"skin\": %s' % descriptor.skin
|
||||
if not descriptor.frame.is_empty():
|
||||
model_string += ', \"frame\": %s' % descriptor.frame
|
||||
if not descriptor.scale.is_empty():
|
||||
model_string += ', \"scale\": %s' % descriptor.scale
|
||||
|
||||
model_string += " }"
|
||||
|
||||
return model_string
|
||||
|
||||
func _build_model_text() -> String:
|
||||
var model_string: String = ''
|
||||
|
||||
if display_descriptors.is_empty():
|
||||
return model_string
|
||||
|
||||
if display_descriptors.size() == 1:
|
||||
return _build_model_branch_text(display_descriptors[0])
|
||||
|
||||
model_string = '{{'
|
||||
var default_display: FuncGodotFGDPointClassDisplayDescriptor
|
||||
for i in display_descriptors.size():
|
||||
var d: FuncGodotFGDPointClassDisplayDescriptor = display_descriptors[i]
|
||||
|
||||
# Only set the first discovered descriptor without a condition to the default, which must be the last option in a list.
|
||||
# If a conditional is not set, skip it.
|
||||
if d.conditional.is_empty():
|
||||
if not default_display:
|
||||
default_display = d
|
||||
else:
|
||||
printerr(classname + " has a Point Class Display Descriptor without required conditionals set. Must have only 1 conditionless Display Descriptor!")
|
||||
continue
|
||||
|
||||
model_string += '%s -> %s, ' % [d.conditional, _build_model_branch_text(d)]
|
||||
|
||||
if default_display:
|
||||
model_string += '%s }}' % _build_model_branch_text(default_display)
|
||||
else:
|
||||
model_string = model_string.trim_suffix(', ')
|
||||
model_string += ' }}'
|
||||
|
||||
return model_string
|
||||
|
||||
func _build_studio_text() -> String:
|
||||
var display_string = ""
|
||||
for d in display_descriptors:
|
||||
if d.display_asset_path.find('\"') != -1:
|
||||
display_string = d.display_asset_path
|
||||
else:
|
||||
printerr(classname + " attempting to set an invalid value to @studio format during FGD export. Only relative file paths encapsulated by quotations are valid.")
|
||||
return display_string
|
||||
|
||||
func build_def_text(target_editor: FuncGodotFGDFile.FuncGodotTargetMapEditors = FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM) -> String:
|
||||
if not display_descriptors.is_empty():
|
||||
if target_editor == FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM:
|
||||
var display_string: String = _build_model_text()
|
||||
if not display_string.is_empty():
|
||||
meta_properties["model"] = display_string
|
||||
else:
|
||||
var display_string: String = _build_studio_text()
|
||||
if not display_string.is_empty():
|
||||
meta_properties["studio"] = display_string
|
||||
return super(target_editor)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
@tool
|
||||
@icon("res://addons/func_godot/icons/icon_godambler3d.svg")
|
||||
class_name FuncGodotFGDPointClassDisplayDescriptor extends Resource
|
||||
## Resource that describes how to display an FGD Point Class entity.
|
||||
##
|
||||
## A resource for [FuncGodotFGDPointClass] that describes how to display a point entity in a map editor.
|
||||
## Values entered into the different options are taken literally: paths should be enclosed within quotation marks,
|
||||
## while class property keys and integer values should omit them.[br][br]
|
||||
##
|
||||
## Most editors only support the [member display_asset] option. Exporting an FGD compatible with these editors will
|
||||
## automatically omit the unsupported options introduced by TrenchBroom when exporting from their respective game configuration resources
|
||||
## or setting [member FuncGodotFGDFile.target_map_editor] away from [enum FuncGodotFGDFile.FuncGodotTargetMapEditors.TRENCHBROOM].
|
||||
##
|
||||
## The extra options are considered advanced features and are unable to be evaluated by FuncGodot to ensure they were input correctly.
|
||||
## Exercise caution, care, and patience when attempting to use these, especially the [member conditional] option.
|
||||
##
|
||||
## @tutorial(Level Design Book: Display Models for Entities): https://book.leveldesignbook.com/appendix/resources/formats/fgd#display-models-for-entities
|
||||
## @tutorial(Valve Developer Wiki FGD Article: Entity Description Section): https://developer.valvesoftware.com/wiki/FGD#Entity_Description
|
||||
## @tutorial(TrenchBroom Manual: Display Models for Entities): https://trenchbroom.github.io/manual/latest/#display-models-for-entities
|
||||
## @tutorial(TrenchBroom Manual: Expression Language): https://trenchbroom.github.io/manual/latest/#expression_language
|
||||
|
||||
## Either a file path to the asset that will be displayed for this point entity, relative to the map editor's game path,
|
||||
## or a class property key that can contain the path.[br][br]
|
||||
## For paths, you must surround the path with quotes, e.g: [code]"models/marsfrog.glb"[/code].
|
||||
## For properties, you must omit the quotes, e.g: [code]display_model_path[/code].[br][br]
|
||||
## Different editors support different file types: common ones include MDL, GLB, SPR, and PNG.
|
||||
@export var display_asset_path: String = ""
|
||||
|
||||
@export_group("TrenchBroom Options")
|
||||
## Optional string that determines the scale of the display asset. This can be a number, a class property key, or
|
||||
## a scale expression in accordance with TrenchBroom's Expression Language. Leave blank to use the game configuration's default scale expression.[br][br]
|
||||
## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
|
||||
@export var scale: String = ""
|
||||
|
||||
## Optional string that determines which skin the display asset should use. This can be either a number or a class property key.[br][br]
|
||||
## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
|
||||
@export var skin: String = ""
|
||||
|
||||
## Optional string that determines the appearance of a display asset based on its file type. This can be either a number or a class property key.[br][br]
|
||||
## Traditional Quake MDL files will set the display to that frame of its animations (all animations in a Quake MDL are compiled into a single animation).
|
||||
## GLBs meanwhile seem to set themselves to the animation assigned to an index that matches the [code]frame[/code] value.[br][br]
|
||||
## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
|
||||
@export var frame: String = ""
|
||||
|
||||
## Optional evaluation string that, when true, will force the Point Class to display the asset defined by [member display_asset_path].
|
||||
## Format should be [code]property == value[/code] or some other valid expression in accordance with TrenchBroom's Expression Language.[br][br]
|
||||
## [color=orange]WARNING:[/color] Only utilized by TrenchBroom!
|
||||
@export var conditional: String = ""
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://d1nwwgcrner8b
|
||||
Loading…
Add table
Add a link
Reference in a new issue