diff options
Diffstat (limited to 'game/addons/zylann.hterrain/hterrain_texture_set.gd')
-rw-r--r-- | game/addons/zylann.hterrain/hterrain_texture_set.gd | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/game/addons/zylann.hterrain/hterrain_texture_set.gd b/game/addons/zylann.hterrain/hterrain_texture_set.gd new file mode 100644 index 0000000..9ae95f2 --- /dev/null +++ b/game/addons/zylann.hterrain/hterrain_texture_set.gd @@ -0,0 +1,253 @@ +@tool +extends Resource + +const MODE_TEXTURES = 0 +const MODE_TEXTURE_ARRAYS = 1 +const MODE_COUNT = 2 + +const _mode_names = ["Textures", "TextureArrays"] + +const SRC_TYPE_ALBEDO = 0 +const SRC_TYPE_BUMP = 1 +const SRC_TYPE_NORMAL = 2 +const SRC_TYPE_ROUGHNESS = 3 +const SRC_TYPE_COUNT = 4 + +const _src_texture_type_names = ["albedo", "bump", "normal", "roughness"] + +# Ground texture types (used by the terrain system) +const TYPE_ALBEDO_BUMP = 0 +const TYPE_NORMAL_ROUGHNESS = 1 +const TYPE_COUNT = 2 + +const _texture_type_names = ["albedo_bump", "normal_roughness"] + +const _type_to_src_types = [ + [SRC_TYPE_ALBEDO, SRC_TYPE_BUMP], + [SRC_TYPE_NORMAL, SRC_TYPE_ROUGHNESS] +] + +const _src_default_color_codes = [ + "#ff000000", + "#ff888888", + "#ff8888ff", + "#ffffffff" +] + +# TODO We may get rid of modes in the future, and only use TextureArrays. +# It exists for now for backward compatibility, but it makes the API a bit confusing +var _mode := MODE_TEXTURES +# [type][slot] -> StreamTexture or TextureArray +var _textures := [[], []] + + +static func get_texture_type_name(tt: int) -> String: + return _texture_type_names[tt] + + +static func get_source_texture_type_name(tt: int) -> String: + return _src_texture_type_names[tt] + + +static func get_source_texture_default_color_code(tt: int) -> String: + return _src_default_color_codes[tt] + + +static func get_import_mode_name(mode: int) -> String: + return _mode_names[mode] + + +static func get_src_types_from_type(t: int) -> Array: + return _type_to_src_types[t] + + +static func get_max_slots_for_mode(mode: int) -> int: + match mode: + MODE_TEXTURES: + # This is a legacy mode, where shaders can only have up to 4 + return 4 + MODE_TEXTURE_ARRAYS: + # Will probably be lifted some day + return 16 + return 0 + + +func _get_property_list() -> Array: + return [ + { + "name": "mode", + "type": TYPE_INT, + "usage": PROPERTY_USAGE_STORAGE + }, + { + "name": "textures", + "type": TYPE_ARRAY, + "usage": PROPERTY_USAGE_STORAGE + } + ] + + +func _get(key: StringName): + if key == &"mode": + return _mode + if key == &"textures": + return _textures + + +func _set(key: StringName, value): + if key == &"mode": + # Not using set_mode() here because otherwise it could reset stuff set before... + _mode = value + if key == &"textures": + _textures = value + + +func get_slots_count() -> int: + if _mode == MODE_TEXTURES: + return get_texture_count() + + elif _mode == MODE_TEXTURE_ARRAYS: + # TODO What if there are two texture arrays of different size? + var texarray : TextureLayered = _textures[TYPE_ALBEDO_BUMP][0] + if texarray == null: + texarray = _textures[TYPE_NORMAL_ROUGHNESS][0] + if texarray == null: + return 0 + return texarray.get_layers() + + else: + assert(false) + return 0 + + +func get_texture_count() -> int: + var texs = _textures[TYPE_ALBEDO_BUMP] + return len(texs) + + +func get_texture(slot_index: int, ground_texture_type: int) -> Texture2D: + if _mode == MODE_TEXTURE_ARRAYS: + # Can't get a single texture at once + return null + + elif _mode == MODE_TEXTURES: + var texs = _textures[ground_texture_type] + if slot_index >= len(texs): + return null + return texs[slot_index] + + else: + assert(false) + return null + + +func set_texture(slot_index: int, ground_texture_type: int, texture: Texture2D): + assert(_mode == MODE_TEXTURES) + var texs = _textures[ground_texture_type] + if texs[slot_index] != texture: + texs[slot_index] = texture + emit_changed() + + +func get_texture_array(ground_texture_type: int) -> TextureLayered: + if _mode != MODE_TEXTURE_ARRAYS: + return null + var texs = _textures[ground_texture_type] + return texs[0] + + +func set_texture_array(ground_texture_type: int, texarray: TextureLayered): + assert(_mode == MODE_TEXTURE_ARRAYS) + var texs = _textures[ground_texture_type] + if texs[0] != texarray: + texs[0] = texarray + emit_changed() + + +# TODO This function only exists because of a flaw in UndoRedo +# See https://github.com/godotengine/godot/issues/36895 +func set_texture_null(slot_index: int, ground_texture_type: int): + set_texture(slot_index, ground_texture_type, null) + + +# TODO This function only exists because of a flaw in UndoRedo +# See https://github.com/godotengine/godot/issues/36895 +func set_texture_array_null(ground_texture_type: int): + set_texture_array(ground_texture_type, null) + + +func get_mode() -> int: + return _mode + + +func set_mode(mode: int): + # This effectively clears slots + _mode = mode + clear() + + +func clear(): + match _mode: + MODE_TEXTURES: + for type in TYPE_COUNT: + _textures[type] = [] + MODE_TEXTURE_ARRAYS: + for type in TYPE_COUNT: + _textures[type] = [null] + _: + assert(false) + emit_changed() + + +func insert_slot(i: int) -> int: + assert(_mode == MODE_TEXTURES) + if i == -1: + i = get_texture_count() + for type in TYPE_COUNT: + _textures[type].insert(i, null) + emit_changed() + return i + + +func remove_slot(i: int): + assert(_mode == MODE_TEXTURES) + if i == -1: + i = get_slots_count() - 1 + for type in TYPE_COUNT: + _textures[type].remove(i) + emit_changed() + + +func has_any_textures() -> bool: + for type in len(_textures): + var texs = _textures[type] + for i in len(texs): + if texs[i] != null: + return true + return false + + +#func set_textures(textures: Array): +# _textures = textures + + +# Cannot type hint because it would cause circular dependency +#func migrate_from_1_4(terrain): +# var textures := [] +# for type in TYPE_COUNT: +# textures.append([]) +# +# if terrain.is_using_texture_array(): +# for type in TYPE_COUNT: +# var tex : TextureArray = terrain.get_ground_texture_array(type) +# textures[type] = [tex] +# _mode = MODE_TEXTURE_ARRAYS +# +# else: +# for index in terrain.get_max_ground_texture_slot_count(): +# for type in TYPE_COUNT: +# var tex : Texture = terrain.get_ground_texture(type, index) +# textures[type].append(tex) +# _mode = MODE_TEXTURES +# +# _textures = textures |