Skip to content

Commit cf2a1ea

Browse files
committed
Refactor MaterialManager to support more options (like e3d submodel selfillum)
1 parent 2d87b5d commit cf2a1ea

3 files changed

Lines changed: 42 additions & 36 deletions

File tree

addons/libmaszyna/e3d/e3d_instancer.gd

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ func _is_submodel_valid(target_node: E3DModelInstance, submodel: E3DSubModel) ->
4343

4444
func _get_material_override(target_node: E3DModelInstance, submodel: E3DSubModel) -> Material:
4545
var unprefixed_model_path: String = "/".join(target_node.data_path.split("/").slice(1))
46+
var options = MaterialManager.MaterialOptions.new()
47+
48+
# TODO: handle more material options here (selfillum, diffuse_color, etc)
49+
options.force_transparent = submodel.material_transparent
50+
4651
if submodel.dynamic_material:
4752
if target_node.skins.size() < submodel.dynamic_material_index + 1:
4853
push_warning(
@@ -57,7 +62,7 @@ func _get_material_override(target_node: E3DModelInstance, submodel: E3DSubModel
5762
else MaterialManager.Transparency.Disabled
5863
)
5964
var skin: Variant = target_node.skins[submodel.dynamic_material_index]
60-
return MaterialManager.get_material(unprefixed_model_path, skin, dynamic_transparency)
65+
return MaterialManager.get_material(unprefixed_model_path, skin, options)
6166

6267
if submodel.material_colored:
6368
return _colored_material
@@ -71,8 +76,7 @@ func _get_material_override(target_node: E3DModelInstance, submodel: E3DSubModel
7176
return MaterialManager.get_material(
7277
unprefixed_model_path,
7378
submodel.material_name,
74-
named_transparency,
75-
submodel.diffuse_color,
79+
options,
7680
)
7781

7882
return null

addons/libmaszyna/materials/material_factory.gd

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ func create(
8181
model_path: String = "",
8282
season: MaterialManager.Season = MaterialManager.Season.SEASON_SUMMER,
8383
weather: MaterialManager.Weather = MaterialManager.Weather.WEATHER_CLEAR,
84-
force_transparent: bool = false,
85-
diffuse_color: Color = Color.WHITE
84+
options: MaterialManager.MaterialOptions = MaterialManager.MaterialOptions.new(),
8685
) -> Material:
8786
var variant: MaszynaMaterial.MaszynaMaterialVariant = mmat.get_variant(season, weather)
8887
var shader_meta:MaszynaShaderMeta = _get_shader_meta(variant.shader)
@@ -94,8 +93,7 @@ func create(
9493
shader_meta,
9594
shader_meta.texture_map,
9695
model_path,
97-
force_transparent,
98-
diffuse_color,
96+
options,
9997
)
10098
return material
10199

@@ -106,8 +104,7 @@ func apply(
106104
model_path: String,
107105
season: MaterialManager.Season,
108106
weather: MaterialManager.Weather,
109-
force_transparent: bool,
110-
diffuse_color: Color = Color.WHITE
107+
options: MaterialManager.MaterialOptions = MaterialManager.MaterialOptions.new(),
111108
) -> void:
112109
var variant: MaszynaMaterial.MaszynaMaterialVariant = mmat.get_variant(season, weather)
113110
var shader_meta:MaszynaShaderMeta = _get_shader_meta(variant.shader)
@@ -118,8 +115,7 @@ func apply(
118115
shader_meta,
119116
shader_meta.texture_map,
120117
model_path,
121-
force_transparent,
122-
diffuse_color
118+
options,
123119
)
124120

125121

@@ -138,8 +134,7 @@ func _apply(
138134
shader_meta: MaszynaShaderMeta,
139135
texture_map: TextureMap,
140136
model_path: String,
141-
force_transparent: bool,
142-
diffuse_color: Color,
137+
options: MaterialManager.MaterialOptions,
143138
) -> void:
144139

145140
if not material is ShaderMaterial or not shader_meta.base_material is ShaderMaterial:
@@ -151,9 +146,9 @@ func _apply(
151146
if property_name == "shader" or property_name == "render_priority" or property_name.begins_with("shader_parameter/"):
152147
target_shader_material.set(property_name, source_shader_material.get(property_name))
153148

154-
shader_meta.factory.call(mmat, variant, material, texture_map, model_path, diffuse_color)
149+
shader_meta.factory.call(mmat, variant, material, texture_map, model_path, options.diffuse_color)
155150
var transparency: MaterialManager.Transparency = MaterialManager.Transparency.Disabled
156-
if mmat.transparent or force_transparent:
151+
if mmat.transparent or options.force_transparent:
157152
transparency = MaterialManager.Transparency.AlphaScissor
158153
target_shader_material.set_shader_parameter("transparency", transparency)
159154
target_shader_material.set_shader_parameter("alpha_scissor_threshold", 0.5)

addons/libmaszyna/materials/material_manager.gd

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ var _managed_materials: Dictionary = {}
1212

1313
enum Transparency { Disabled, Alpha, AlphaScissor }
1414

15-
const _transparency_codes = {
16-
Transparency.Disabled: "0",
17-
Transparency.Alpha: "a",
18-
Transparency.AlphaScissor: "s",
19-
}
15+
16+
class MaterialOptions:
17+
var diffuse_color: Color = Color.WHITE
18+
var selfillum_color: Color = Color.WHITE
19+
var selfillum_energy: float = 1.0
20+
var selfillum_enabled: bool = false
21+
var force_transparent: bool = false # TODO: AphaCut/Alpha modes support
22+
var alpha_scissor_threshold: float = 0.5
23+
2024

2125
@export var season: Season = Season.SEASON_SUMMER:
2226
set(x):
@@ -41,31 +45,29 @@ func load_material(model_path:String, material_name:String) -> MaszynaMaterial:
4145
func get_material(
4246
model_path:String,
4347
material_path:String,
44-
transparent:Transparency = Transparency.Disabled,
45-
diffuse_color: Color = Color(1.0, 1.0, 1.0)
48+
options: MaterialOptions = MaterialOptions.new(),
4649
) -> Material:
47-
var cache_hash: String = _compute_cache_hash(model_path, material_path, transparent, diffuse_color)
50+
var cache_hash: String = _compute_cache_hash(model_path, material_path, options)
4851
var managed_material: Dictionary = _managed_materials.get(cache_hash, {})
4952
if managed_material:
5053
var material_ref: WeakRef = managed_material.get("material_ref") as WeakRef
5154
var material: ShaderMaterial = material_ref.get_ref() as ShaderMaterial if material_ref else null
5255
if material:
5356
return material
5457
_managed_materials.erase(cache_hash)
55-
var force_transparent := not transparent == Transparency.Disabled # TODO: ALPHA
58+
var force_transparent = options.force_transparent # TODO: ALPHA
5659
var output: ShaderMaterial = _materials_cache.get(cache_hash) as ShaderMaterial
5760
if not output:
5861
var mmat: MaszynaMaterial = load_material(model_path, material_path)
59-
output = MaterialFactory.create(mmat, model_path, season, weather, force_transparent, diffuse_color)
62+
output = MaterialFactory.create(mmat, model_path, season, weather, options)
6063
else:
6164
var mmat: MaszynaMaterial = load_material(model_path, material_path)
62-
MaterialFactory.apply(output, mmat, model_path, season, weather, force_transparent, diffuse_color)
65+
MaterialFactory.apply(output, mmat, model_path, season, weather, options)
6366
_managed_materials[cache_hash] = {
6467
"material_ref": weakref(output),
6568
"model_path": model_path,
6669
"material_path": material_path,
67-
"force_transparent": force_transparent,
68-
"diffuse_color": diffuse_color,
70+
"options": options,
6971
}
7072
_materials_cache.set(cache_hash, output)
7173
return output
@@ -107,14 +109,18 @@ func load_texture(model_path:String, material_name:String, normal:bool = false)
107109
func _compute_cache_hash(
108110
model_path: String,
109111
material_path: String,
110-
transparent: Transparency,
111-
diffuse_color: Color,
112+
options: MaterialOptions,
112113
) -> String:
113-
return model_path.path_join(("%s_t%s_%s.res" % [
114-
material_path,
115-
_transparency_codes[transparent],
116-
"%x%x%x" % [diffuse_color.r8, diffuse_color.g8, diffuse_color.b8],
117-
]))
114+
var options_hash = ":".join([
115+
options.force_transparent,
116+
options.diffuse_color.to_html(true),
117+
options.alpha_scissor_threshold,
118+
options.selfillum_enabled,
119+
options.selfillum_color.to_html(true),
120+
options.selfillum_energy,
121+
].map(str)).md5_text()
122+
return model_path.path_join("%s_%s.res" % [material_path, options_hash])
123+
118124

119125
func _refresh_managed_materials() -> void:
120126
var cache_hashes: Array = _managed_materials.keys()
@@ -134,7 +140,8 @@ func _refresh_managed_material(cache_hash: String) -> void:
134140
var material_path: String = managed_material.get("material_path", "")
135141
var force_transparent: Transparency = managed_material.get("force_transparent", false)
136142
var diffuse_color: Color = managed_material.get("diffuse_color", Color.WHITE)
143+
var options:MaterialOptions = managed_material.get("options")
137144
var mmat: MaszynaMaterial = load_material(model_path, material_path)
138145
mmat.transparent = mmat.transparent or force_transparent
139-
MaterialFactory.apply(material, mmat, model_path, season, weather, force_transparent, diffuse_color)
146+
MaterialFactory.apply(material, mmat, model_path, season, weather, options)
140147
_materials_cache.set(cache_hash, material)

0 commit comments

Comments
 (0)