Pull Qodot changes for Trenchbroom game config version 8

This commit is contained in:
Jarrod Doyle 2024-02-22 21:05:13 +00:00
parent dda7f70ca8
commit 944c446e60
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
1 changed files with 61 additions and 83 deletions

View File

@ -1,10 +1,9 @@
@tool @tool
## Defines a new game in Trenchbroom to express a set of entity definitions ## Defines a new game in TrenchBroom to express a set of entity definitions and editor behaviors.
## and editor behaviors.
class_name TrenchBroomGameConfig class_name TrenchBroomGameConfig
extends Resource extends Resource
## Button to export/update this game's folder in the Trenchbroom Games Path. ## Button to export/update this game's folder in the TrenchBroom Games Path.
@export var export_file: bool: @export var export_file: bool:
get: get:
return export_file return export_file
@ -13,17 +12,16 @@ extends Resource
if Engine.is_editor_hint(): if Engine.is_editor_hint():
do_export_file() do_export_file()
## The /games folder in either your Trenchbroom installation or your OS' user ## The /games folder in either your TrenchBroom installation or your OS' user data folder.
## data folder.
@export_global_dir var trenchbroom_games_folder : String @export_global_dir var trenchbroom_games_folder : String
## Name of the game in Trenchbroom's game list. ## Name of the game in TrenchBroom's game list.
@export var game_name := "Qodot" @export var game_name : String = "Qodot"
## Icon for Trenchbroom's game list. ## Icon for TrenchBroom's game list.
@export var icon : Texture2D @export var icon : Texture2D
## Available map formats when creating a new map in Trenchbroom. The order of elements in the array is respected by Trenchbroom. The `initialmap` key value is optional. ## Available map formats when creating a new map in TrenchBroom. The order of elements in the array is respected by TrenchBroom. The `initialmap` key value is optional.
@export var map_formats: Array[Dictionary] = [ @export var map_formats: Array[Dictionary] = [
{ "format": "Valve", "initialmap": "initial_valve.map" }, { "format": "Valve", "initialmap": "initial_valve.map" },
{ "format": "Standard", "initialmap": "initial_standard.map" }, { "format": "Standard", "initialmap": "initial_standard.map" },
@ -31,60 +29,48 @@ extends Resource
{ "format": "Quake3" } { "format": "Quake3" }
] ]
## Array of FGD resources to include with this game. ## Textures matching these patterns will be hidden from TrenchBroom.
@export var fgd_files : Array[Resource] = [ @export var texture_exclusion_patterns: Array[String] = ["*_ao", "*_emission", "*_heightmap", "*_metallic", "*_normal", "*_orm", "*_roughness", "*_sss"]
preload("res://addons/qodot/game_definitions/fgd/qodot_fgd.tres")
]
## Scale expression that modifies the default display scale of entities in Trenchbroom. See the [**Trenchbroom Documentation**](https://trenchbroom.github.io/manual/latest/#game_configuration_files_entities) for more information. ## FGD resource to include with this game. If using multiple FGD resources, this should be the master FGD that contains them in the `base_fgd_files` resource array.
@export var fgd_file : QodotFGDFile = load("res://addons/qodot/game_definitions/fgd/qodot_fgd.tres")
## Scale expression that modifies the default display scale of entities in TrenchBroom. See the [**TrenchBroom Documentation**](https://trenchbroom.github.io/manual/latest/#game_configuration_files_entities) for more information.
@export var entity_scale: String = "1" @export var entity_scale: String = "1"
## Scale of textures on new brushes. ## Scale of textures on new brushes.
@export var default_uv_scale : Vector2 = Vector2(1, 1) @export var default_uv_scale : Vector2 = Vector2(1, 1)
## Arrays containing the TrenchbroomTag resource type. ## Arrays containing the TrenchBroomTag resource type.
@export_category("Editor hint tags") @export_category("Editor hint tags")
## Container for TrenchbroomTag resources that apply to brush entities. ## Container for TrenchBroomTag resources that apply to brush entities.
@export var brush_tags : Array[Resource] = [] @export var brush_tags : Array[TrenchBroomTag] = []
## Container for TrenchbroomTag resources that apply to textures. ## Container for TrenchBroomTag resources that apply to textures.
@export var face_tags : Array[Resource] = [] @export var face_tags : Array[TrenchBroomTag] = []
## Arrays containing the TrenchbroomFaceAttrib resource type. Currently not parsed by Qodot.
@export_category("Quake 2 compatibility")
## Map-wide bitflags toggleable for each face. Currently not parsed by Qodot.
@export var face_attrib_surface_flags : Array[Resource] = []
## Map-wide bitflags toggleable for each brush. Currently not parsed by Qodot.
@export var face_attrib_content_flags : Array[Resource] = []
## Private variable for storing fgd names, used in build_class_text().
var _fgd_filenames : Array = []
## Private default .cfg contents. ## Private default .cfg contents.
## See also: https://trenchbroom.github.io/manual/latest/#game_configuration_files ## See also: https://trenchbroom.github.io/manual/latest/#game_configuration_files
var _base_text: String = """{ const _base_text : String = """{
version: 3, "version": 8,
name: "%s", "name": "%s",
icon: "icon.png", "icon": "icon.png",
"fileformats": [ "fileformats": [
%s %s
], ],
"filesystem": { "filesystem": {
"searchpath": ".", "searchpath": ".",
"packageformat": { "extension": "pak", "format": "idpak" } "packageformat": { "extension": ".zip", "format": "zip" }
}, },
"textures": { "textures": {
"package": { "type": "directory", "root": "textures" }, "root": "textures",
"format": { "extensions": ["bmp", "exr", "hdr", "jpeg", "jpg", "png", "tga", "webp"], "format": "image" }, "extensions": [".bmp", ".exr", ".hdr", ".jpeg", ".jpg", ".png", ".tga", ".webp"],
"attribute": "_tb_textures" "excludes": [ %s ]
}, },
"entities": { "entities": {
"definitions": [ %s ], "definitions": [ %s ],
"defaultcolor": "0.6 0.6 0.6 1.0", "defaultcolor": "0.6 0.6 0.6 1.0",
"modelformats": [ "mdl", "md2", "md3", "bsp", "dkm" ],
"scale": %s "scale": %s
}, },
"tags": { "tags": {
@ -99,35 +85,31 @@ var _base_text: String = """{
"defaults": { "defaults": {
%s %s
}, },
"surfaceflags": [ "contentflags": [],
%s "surfaceflags": []
],
"contentflags": [
%s
]
} }
} }
""" """
func _init(): func _init() -> void:
if not icon: if not icon:
if ResourceLoader.exists("res://addons/qodot/icon.png"): if ResourceLoader.exists("res://addons/qodot/icon.png"):
icon = ResourceLoader.load("res://addons/qodot/icon.png") icon = ResourceLoader.load("res://addons/qodot/icon.png")
## Matches tag key enum to the String name used in .cfg ## Matches tag key enum to the String name used in .cfg
static func get_match_key(tag_match_type: int) -> String: static func get_match_key(tag_match_type: int) -> String:
var tag_keys = { match tag_match_type:
0: "texture", TrenchBroomTag.TagMatchType.TEXTURE:
1: "contentflag", return "texture"
2: "surfaceflag", TrenchBroomTag.TagMatchType.CLASSNAME:
3: "surfaceparm", return "classname"
4: "classname" _:
} push_error("Tag match type %s is not valid" % [tag_match_type])
return tag_keys[tag_match_type] return "ERROR"
## Generates completed text for a .cfg file. ## Generates completed text for a .cfg file.
func build_class_text() -> String: func build_class_text() -> String:
var map_formats_str := "" var map_formats_str : String = ""
for map_format in map_formats: for map_format in map_formats:
map_formats_str += "{ \"format\": \"" + map_format.format + "\"" map_formats_str += "{ \"format\": \"" + map_format.format + "\""
if map_format.has("initialmap"): if map_format.has("initialmap"):
@ -137,33 +119,34 @@ func build_class_text() -> String:
else: else:
map_formats_str += " }" map_formats_str += " }"
var fgd_filename_str := "" var texture_exclusion_patterns_str := ""
for fgd_filename in _fgd_filenames: for tex_pattern in texture_exclusion_patterns:
fgd_filename_str += "\"%s\"" % fgd_filename texture_exclusion_patterns_str += "\"" + tex_pattern + "\""
if fgd_filename != _fgd_filenames[-1]: if tex_pattern != texture_exclusion_patterns[-1]:
fgd_filename_str += ", " texture_exclusion_patterns_str += ", "
var fgd_filename_str : String = "\"" + fgd_file.fgd_name + ".fgd\""
var brush_tags_str = parse_tags(brush_tags) var brush_tags_str = parse_tags(brush_tags)
var face_tags_str = parse_tags(face_tags) var face_tags_str = parse_tags(face_tags)
var surface_flags_str = parse_flags(face_attrib_surface_flags)
var content_flags_str = parse_flags(face_attrib_content_flags)
var uv_scale_str = parse_default_uv_scale(default_uv_scale) var uv_scale_str = parse_default_uv_scale(default_uv_scale)
return _base_text % [ return _base_text % [
game_name, game_name,
map_formats_str, map_formats_str,
texture_exclusion_patterns_str,
fgd_filename_str, fgd_filename_str,
entity_scale, entity_scale,
brush_tags_str, brush_tags_str,
face_tags_str, face_tags_str,
uv_scale_str, uv_scale_str
surface_flags_str,
content_flags_str
] ]
## Converts brush, face, and attribute tags into a .cfg-usable String. ## Converts brush, face, and attribute tags into a .cfg-usable String.
func parse_tags(tags: Array) -> String: func parse_tags(tags: Array) -> String:
var tags_str := "" var tags_str := ""
for brush_tag in tags: for brush_tag in tags:
if brush_tag.tag_match_type >= TrenchBroomTag.TagMatchType.size():
continue
tags_str += "{\n" tags_str += "{\n"
tags_str += "\t\t\t\t\"name\": \"%s\",\n" % brush_tag.tag_name tags_str += "\t\t\t\t\"name\": \"%s\",\n" % brush_tag.tag_name
var attribs_str := "" var attribs_str := ""
@ -204,13 +187,19 @@ func parse_default_uv_scale(texture_scale : Vector2) -> String:
}) })
## Exports or updates a folder in the /games directory, with an icon, .cfg, and all accompanying FGDs. ## Exports or updates a folder in the /games directory, with an icon, .cfg, and all accompanying FGDs.
func do_export_file(): func do_export_file() -> void:
var folder = trenchbroom_games_folder var folder = trenchbroom_games_folder
if folder.is_empty(): if folder.is_empty():
folder = QodotProjectConfig.get_setting(QodotProjectConfig.PROPERTY.TRENCHBROOM_GAMES_FOLDER) folder = QodotProjectConfig.get_setting(QodotProjectConfig.PROPERTY.TRENCHBROOM_GAMES_FOLDER)
if folder.is_empty(): if folder.is_empty():
print("Skipping export: No TrenchBroom games folder") print("Skipping export: No TrenchBroom games folder")
return return
# Make sure FGD file is set
if !fgd_file:
print("Skipping export: No FGD file")
return
# Create config folder name by combining games folder with the game name as a directory # Create config folder name by combining games folder with the game name as a directory
var config_folder = folder + "/" + game_name var config_folder = folder + "/" + game_name
var config_dir := DirAccess.open(config_folder) var config_dir := DirAccess.open(config_folder)
@ -221,9 +210,6 @@ func do_export_file():
print("Skipping export: Failed to create directory") print("Skipping export: Failed to create directory")
return return
config_dir = DirAccess.open(config_folder) config_dir = DirAccess.open(config_folder)
if fgd_files.size() == 0:
print("Skipping export: No FGD files")
return
print("Exporting TrenchBroom Game Config Folder to ", config_folder) print("Exporting TrenchBroom Game Config Folder to ", config_folder)
# Icon # Icon
@ -236,22 +222,14 @@ func do_export_file():
# .cfg # .cfg
var export_config_file: Dictionary = {} var export_config_file: Dictionary = {}
export_config_file.game_name = game_name export_config_file.game_name = game_name
_fgd_filenames = []
for fgd_file in fgd_files:
_fgd_filenames.append(fgd_file.fgd_name + ".fgd")
print("Exported %s" % [fgd_file.fgd_name + ".fgd"])
export_config_file.target_file = config_folder + "/GameConfig.cfg" export_config_file.target_file = config_folder + "/GameConfig.cfg"
print("Exporting Trenchbroom Game Config File to ", export_config_file.target_file) print("Exporting TrenchBroom Game Config File to ", export_config_file.target_file)
var file = FileAccess.open(export_config_file.target_file, FileAccess.WRITE) var file = FileAccess.open(export_config_file.target_file, FileAccess.WRITE)
file.store_string(build_class_text()) file.store_string(build_class_text())
file = null # Official way to close files in GDscript 2 file = null # Official way to close files in GDscript 2
# FGDs # FGD
for fgd_file in fgd_files: var export_fgd : QodotFGDFile = fgd_file.duplicate()
if not fgd_file is QodotFGDFile: export_fgd.target_folder = config_folder
print("Skipping %s: Not a valid FGD file" % [fgd_file]) export_fgd.do_export_file()
continue
var export_fgd : QodotFGDFile = fgd_file.duplicate()
export_fgd.target_folder = config_folder
export_fgd.do_export_file()
print("Export complete\n") print("Export complete\n")