project_teddy/addons/zylann.hterrain/hterrain_texture_set.gd

253 lines
5.6 KiB
GDScript

@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