actual initial commit lmao
This commit is contained in:
136
addons/func_godot/src/util/func_godot_local_config.gd
Normal file
136
addons/func_godot/src/util/func_godot_local_config.gd
Normal file
@@ -0,0 +1,136 @@
|
||||
@tool
|
||||
@icon("res://addons/func_godot/icons/icon_godot_ranger.svg")
|
||||
## Local machine project wide settings. Can define global defaults for some FuncGodot properties.
|
||||
## DO NOT CREATE A NEW RESOURCE! This resource works by saving a configuration file to your game's *user://* folder and pulling the properties from that config file rather than this resource.
|
||||
## Use the premade `addons/func_godot/func_godot_local_config.tres` instead.
|
||||
class_name FuncGodotLocalConfig
|
||||
extends Resource
|
||||
|
||||
enum PROPERTY {
|
||||
FGD_OUTPUT_FOLDER,
|
||||
TRENCHBROOM_GAME_CONFIG_FOLDER,
|
||||
NETRADIANT_CUSTOM_GAMEPACKS_FOLDER,
|
||||
MAP_EDITOR_GAME_PATH,
|
||||
GAME_PATH_MODELS_FOLDER,
|
||||
DEFAULT_INVERSE_SCALE
|
||||
}
|
||||
|
||||
@export var export_func_godot_settings: bool: set = _save_settings
|
||||
|
||||
const CONFIG_PROPERTIES: Array[Dictionary] = [
|
||||
{
|
||||
"name": "fgd_output_folder",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"hint": PROPERTY_HINT_GLOBAL_DIR,
|
||||
"func_godot_type": PROPERTY.FGD_OUTPUT_FOLDER
|
||||
},
|
||||
{
|
||||
"name": "trenchbroom_game_config_folder",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"hint": PROPERTY_HINT_GLOBAL_DIR,
|
||||
"func_godot_type": PROPERTY.TRENCHBROOM_GAME_CONFIG_FOLDER
|
||||
},
|
||||
{
|
||||
"name": "netradiant_custom_gamepacks_folder",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"hint": PROPERTY_HINT_GLOBAL_DIR,
|
||||
"func_godot_type": PROPERTY.NETRADIANT_CUSTOM_GAMEPACKS_FOLDER
|
||||
},
|
||||
{
|
||||
"name": "map_editor_game_path",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"hint": PROPERTY_HINT_GLOBAL_DIR,
|
||||
"func_godot_type": PROPERTY.MAP_EDITOR_GAME_PATH
|
||||
},
|
||||
{
|
||||
"name": "game_path_models_folder",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"func_godot_type": PROPERTY.GAME_PATH_MODELS_FOLDER
|
||||
},
|
||||
{
|
||||
"name": "default_inverse_scale_factor",
|
||||
"usage": PROPERTY_USAGE_EDITOR,
|
||||
"type": TYPE_FLOAT,
|
||||
"func_godot_type": PROPERTY.DEFAULT_INVERSE_SCALE
|
||||
}
|
||||
]
|
||||
|
||||
var settings_dict: Dictionary
|
||||
var loaded := false
|
||||
|
||||
static func get_setting(name: PROPERTY) -> Variant:
|
||||
var settings = load("res://addons/func_godot/func_godot_local_config.tres")
|
||||
if not settings.loaded:
|
||||
settings._load_settings()
|
||||
return settings.settings_dict.get(PROPERTY.keys()[name], '') as Variant
|
||||
|
||||
func _get_property_list() -> Array:
|
||||
return CONFIG_PROPERTIES.duplicate()
|
||||
|
||||
func _get(property: StringName) -> Variant:
|
||||
var config = _get_config_property(property)
|
||||
if config == null and not config is Dictionary:
|
||||
return null
|
||||
_try_loading()
|
||||
return settings_dict.get(PROPERTY.keys()[config['func_godot_type']], _get_default_value(config['type']))
|
||||
|
||||
func _set(property: StringName, value: Variant) -> bool:
|
||||
var config = _get_config_property(property)
|
||||
if config == null and not config is Dictionary:
|
||||
return false
|
||||
settings_dict[PROPERTY.keys()[config['func_godot_type']]] = value
|
||||
return true
|
||||
|
||||
func _get_default_value(type) -> Variant:
|
||||
match type:
|
||||
TYPE_STRING: return ''
|
||||
TYPE_INT: return 0
|
||||
TYPE_FLOAT: return 0.0
|
||||
TYPE_BOOL: return false
|
||||
TYPE_VECTOR2: return Vector2.ZERO
|
||||
TYPE_VECTOR3: return Vector3.ZERO
|
||||
TYPE_ARRAY: return []
|
||||
TYPE_DICTIONARY: return {}
|
||||
push_error("Invalid setting type. Returning null")
|
||||
return null
|
||||
|
||||
func _get_config_property(name: StringName) -> Variant:
|
||||
for config in CONFIG_PROPERTIES:
|
||||
if config['name'] == name:
|
||||
return config
|
||||
return null
|
||||
|
||||
func _load_settings() -> void:
|
||||
loaded = true
|
||||
var path = _get_path()
|
||||
if not FileAccess.file_exists(path): return
|
||||
var settings = FileAccess.get_file_as_string(path)
|
||||
settings_dict = {}
|
||||
if not settings or settings.is_empty(): return
|
||||
settings = JSON.parse_string(settings)
|
||||
for key in settings.keys():
|
||||
settings_dict[key] = settings[key]
|
||||
notify_property_list_changed()
|
||||
|
||||
func _try_loading() -> void:
|
||||
if not loaded: _load_settings()
|
||||
|
||||
func _save_settings(_s = null) -> void:
|
||||
if settings_dict.size() == 0:
|
||||
return
|
||||
var path = _get_path()
|
||||
var file = FileAccess.open(path, FileAccess.WRITE)
|
||||
var json = JSON.stringify(settings_dict)
|
||||
file.store_line(json)
|
||||
loaded = false
|
||||
print("Saved settings to ", path)
|
||||
|
||||
func _get_path() -> String:
|
||||
var application_name: String = ProjectSettings.get('application/config/name')
|
||||
application_name = application_name.replace(" ", "_")
|
||||
return 'user://' + application_name + '_FuncGodotConfig.json'
|
||||
@@ -0,0 +1 @@
|
||||
uid://bjtqjywscfgdy
|
||||
184
addons/func_godot/src/util/func_godot_texture_loader.gd
Normal file
184
addons/func_godot/src/util/func_godot_texture_loader.gd
Normal file
@@ -0,0 +1,184 @@
|
||||
class_name FuncGodotTextureLoader
|
||||
|
||||
enum PBRSuffix {
|
||||
ALBEDO,
|
||||
NORMAL,
|
||||
METALLIC,
|
||||
ROUGHNESS,
|
||||
EMISSION,
|
||||
AO,
|
||||
HEIGHT
|
||||
}
|
||||
|
||||
# Suffix string / Godot enum / StandardMaterial3D property
|
||||
const PBR_SUFFIX_NAMES: Dictionary = {
|
||||
PBRSuffix.ALBEDO: 'albedo',
|
||||
PBRSuffix.NORMAL: 'normal',
|
||||
PBRSuffix.METALLIC: 'metallic',
|
||||
PBRSuffix.ROUGHNESS: 'roughness',
|
||||
PBRSuffix.EMISSION: 'emission',
|
||||
PBRSuffix.AO: 'ao',
|
||||
PBRSuffix.HEIGHT: 'height',
|
||||
}
|
||||
|
||||
const PBR_SUFFIX_PATTERNS: Dictionary = {
|
||||
PBRSuffix.ALBEDO: '%s_albedo.%s',
|
||||
PBRSuffix.NORMAL: '%s_normal.%s',
|
||||
PBRSuffix.METALLIC: '%s_metallic.%s',
|
||||
PBRSuffix.ROUGHNESS: '%s_roughness.%s',
|
||||
PBRSuffix.EMISSION: '%s_emission.%s',
|
||||
PBRSuffix.AO: '%s_ao.%s',
|
||||
PBRSuffix.HEIGHT: '%s_height.%s'
|
||||
}
|
||||
|
||||
var PBR_SUFFIX_TEXTURES: Dictionary = {
|
||||
PBRSuffix.ALBEDO: StandardMaterial3D.TEXTURE_ALBEDO,
|
||||
PBRSuffix.NORMAL: StandardMaterial3D.TEXTURE_NORMAL,
|
||||
PBRSuffix.METALLIC: StandardMaterial3D.TEXTURE_METALLIC,
|
||||
PBRSuffix.ROUGHNESS: StandardMaterial3D.TEXTURE_ROUGHNESS,
|
||||
PBRSuffix.EMISSION: StandardMaterial3D.TEXTURE_EMISSION,
|
||||
PBRSuffix.AO: StandardMaterial3D.TEXTURE_AMBIENT_OCCLUSION,
|
||||
PBRSuffix.HEIGHT: StandardMaterial3D.TEXTURE_HEIGHTMAP
|
||||
}
|
||||
|
||||
const PBR_SUFFIX_PROPERTIES: Dictionary = {
|
||||
PBRSuffix.NORMAL: 'normal_enabled',
|
||||
PBRSuffix.EMISSION: 'emission_enabled',
|
||||
PBRSuffix.AO: 'ao_enabled',
|
||||
PBRSuffix.HEIGHT: 'heightmap_enabled',
|
||||
}
|
||||
|
||||
var map_settings: FuncGodotMapSettings = FuncGodotMapSettings.new()
|
||||
var texture_wad_resources: Array = []
|
||||
|
||||
# Overrides
|
||||
func _init(new_map_settings: FuncGodotMapSettings) -> void:
|
||||
map_settings = new_map_settings
|
||||
load_texture_wad_resources()
|
||||
|
||||
# Business Logic
|
||||
func load_texture_wad_resources() -> void:
|
||||
texture_wad_resources.clear()
|
||||
for texture_wad in map_settings.texture_wads:
|
||||
if texture_wad and not texture_wad in texture_wad_resources:
|
||||
texture_wad_resources.append(texture_wad)
|
||||
|
||||
func load_textures(texture_list: Array) -> Dictionary:
|
||||
var texture_dict: Dictionary = {}
|
||||
for texture_name in texture_list:
|
||||
texture_dict[texture_name] = load_texture(texture_name)
|
||||
return texture_dict
|
||||
|
||||
func load_texture(texture_name: String) -> Texture2D:
|
||||
# Load albedo texture if it exists
|
||||
for texture_extension in map_settings.texture_file_extensions:
|
||||
var texture_path: String = "%s/%s.%s" % [map_settings.base_texture_dir, texture_name, texture_extension]
|
||||
if ResourceLoader.exists(texture_path, "Texture2D"):
|
||||
return load(texture_path) as Texture2D
|
||||
|
||||
var texture_name_lower: String = texture_name.to_lower()
|
||||
for texture_wad in texture_wad_resources:
|
||||
if texture_name_lower in texture_wad.textures:
|
||||
return texture_wad.textures[texture_name_lower]
|
||||
|
||||
return load("res://addons/func_godot/textures/default_texture.png") as Texture2D
|
||||
|
||||
func create_materials(texture_list: Array) -> Dictionary:
|
||||
var texture_materials: Dictionary = {}
|
||||
#prints("TEXLI", texture_list)
|
||||
for texture in texture_list:
|
||||
texture_materials[texture] = create_material(texture)
|
||||
return texture_materials
|
||||
|
||||
func create_material(texture_name: String) -> Material:
|
||||
# Autoload material if it exists
|
||||
var material_dict: Dictionary = {}
|
||||
|
||||
var material_path: String = "%s/%s.%s" % [map_settings.base_texture_dir, texture_name, map_settings.material_file_extension]
|
||||
if not material_path in material_dict and FileAccess.file_exists(material_path):
|
||||
var loaded_material: Material = load(material_path)
|
||||
if loaded_material:
|
||||
material_dict[material_path] = loaded_material
|
||||
|
||||
# If material already exists, use it
|
||||
if material_path in material_dict:
|
||||
return material_dict[material_path]
|
||||
|
||||
var material: Material = null
|
||||
|
||||
if map_settings.default_material:
|
||||
material = map_settings.default_material.duplicate()
|
||||
else:
|
||||
material = StandardMaterial3D.new()
|
||||
var texture: Texture2D = load_texture(texture_name)
|
||||
if not texture:
|
||||
return material
|
||||
|
||||
if material is BaseMaterial3D:
|
||||
material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED if map_settings.unshaded else BaseMaterial3D.SHADING_MODE_PER_PIXEL
|
||||
|
||||
if material is StandardMaterial3D:
|
||||
material.set_texture(StandardMaterial3D.TEXTURE_ALBEDO, texture)
|
||||
elif material is ShaderMaterial && map_settings.default_material_albedo_uniform != "":
|
||||
material.set_shader_parameter(map_settings.default_material_albedo_uniform, texture)
|
||||
|
||||
var pbr_textures : Dictionary = get_pbr_textures(texture_name)
|
||||
|
||||
for pbr_suffix in PBRSuffix.values():
|
||||
var suffix: int = pbr_suffix
|
||||
var tex: Texture2D = pbr_textures[suffix]
|
||||
if tex:
|
||||
if material is ShaderMaterial:
|
||||
material = StandardMaterial3D.new()
|
||||
material.set_texture(StandardMaterial3D.TEXTURE_ALBEDO, texture)
|
||||
var enable_prop: String = PBR_SUFFIX_PROPERTIES[suffix] if suffix in PBR_SUFFIX_PROPERTIES else ""
|
||||
if(enable_prop != ""):
|
||||
material.set(enable_prop, true)
|
||||
material.set_texture(PBR_SUFFIX_TEXTURES[suffix], tex)
|
||||
|
||||
material_dict[material_path] = material
|
||||
|
||||
if (map_settings.save_generated_materials and material
|
||||
and texture_name != map_settings.clip_texture
|
||||
and texture_name != map_settings.skip_texture
|
||||
and texture.resource_path != "res://addons/func_godot/textures/default_texture.png"):
|
||||
ResourceSaver.save(material, material_path)
|
||||
|
||||
return material
|
||||
|
||||
# PBR texture fetching
|
||||
func get_pbr_suffix_pattern(suffix: int) -> String:
|
||||
if not suffix in PBR_SUFFIX_NAMES:
|
||||
return ''
|
||||
|
||||
var pattern_setting: String = "%s_map_pattern" % [PBR_SUFFIX_NAMES[suffix]]
|
||||
if pattern_setting in map_settings:
|
||||
return map_settings.get(pattern_setting)
|
||||
|
||||
return PBR_SUFFIX_PATTERNS[suffix]
|
||||
|
||||
func get_pbr_texture(texture: String, suffix: PBRSuffix) -> Texture2D:
|
||||
var texture_comps: PackedStringArray = texture.split('/')
|
||||
if texture_comps.size() == 0:
|
||||
return null
|
||||
|
||||
for texture_extension in map_settings.texture_file_extensions:
|
||||
var path: String = "%s/%s/%s" % [
|
||||
map_settings.base_texture_dir,
|
||||
'/'.join(texture_comps),
|
||||
get_pbr_suffix_pattern(suffix) % [
|
||||
texture_comps[-1],
|
||||
texture_extension
|
||||
]
|
||||
]
|
||||
|
||||
if(FileAccess.file_exists(path)):
|
||||
return load(path) as Texture2D
|
||||
|
||||
return null
|
||||
|
||||
func get_pbr_textures(texture_name: String) -> Dictionary:
|
||||
var pbr_textures: Dictionary = {}
|
||||
for pbr_suffix in PBRSuffix.values():
|
||||
pbr_textures[pbr_suffix] = get_pbr_texture(texture_name, pbr_suffix)
|
||||
return pbr_textures
|
||||
@@ -0,0 +1 @@
|
||||
uid://pfjqfqn3imye
|
||||
40
addons/func_godot/src/util/func_godot_util.gd
Normal file
40
addons/func_godot/src/util/func_godot_util.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
## General-purpose utility functions namespaced to FuncGodot for compatibility
|
||||
class_name FuncGodotUtil
|
||||
|
||||
## Print debug messages. True to print, false to ignore
|
||||
const DEBUG : bool = true
|
||||
|
||||
## Const-predicated print function to avoid excess log spam. Print msg if [constant DEBUG] is `true`.
|
||||
static func debug_print(msg) -> void:
|
||||
if(DEBUG):
|
||||
print(msg)
|
||||
|
||||
## Return a string that corresponds to the current OS's newline control character(s)
|
||||
static func newline() -> String:
|
||||
if OS.get_name() == "Windows":
|
||||
return "\r\n"
|
||||
else:
|
||||
return "\n"
|
||||
|
||||
## Create a dictionary suitable for creating a category with name when overriding [method Object._get_property_list]
|
||||
static func category_dict(name: String) -> Dictionary:
|
||||
return property_dict(name, TYPE_STRING, -1, "", PROPERTY_USAGE_CATEGORY)
|
||||
|
||||
## Creates a property with name and type from [enum @GlobalScope.Variant.Type].
|
||||
## Optionally, provide hint from [enum @GlobalScope.PropertyHint] and corresponding hint_string, and usage from [enum @GlobalScope.PropertyUsageFlags].
|
||||
static func property_dict(name: String, type: int, hint: int = -1, hint_string: String = "", usage: int = -1) -> Dictionary:
|
||||
var dict := {
|
||||
'name': name,
|
||||
'type': type
|
||||
}
|
||||
|
||||
if hint != -1:
|
||||
dict['hint'] = hint
|
||||
|
||||
if hint_string != "":
|
||||
dict['hint_string'] = hint_string
|
||||
|
||||
if usage != -1:
|
||||
dict['usage'] = usage
|
||||
|
||||
return dict
|
||||
1
addons/func_godot/src/util/func_godot_util.gd.uid
Normal file
1
addons/func_godot/src/util/func_godot_util.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dy80wnu2py4dk
|
||||
Reference in New Issue
Block a user