ModelTranslator: dedupe sanitized material names, set alphaIsTransparency for alpha-test textures

This commit is contained in:
ud18010
2026-07-15 12:00:50 +08:00
parent 073ae48a61
commit 0b068dbaa0
4 changed files with 29 additions and 10 deletions
+15 -5
View File
@@ -132,7 +132,7 @@ def _channel(pixels, ch):
return pixels[..., ch if ch is not None else 0]
def _save_png(path, rgba, srgb_view=False):
def _save_png(path, rgba):
"""float32 (h,w,4) -> PNG。写原始值(Non-Color,避免色彩管理改写数据)。"""
import bpy
h, w = rgba.shape[:2]
@@ -146,7 +146,7 @@ def _save_png(path, rgba, srgb_view=False):
bpy.data.images.remove(img)
def _convert_material(mat, model_name, outdir, max_size):
def _convert_material(mat, model_name, outdir, max_size, used_snames):
warnings = []
maps, consts = _material_maps(mat, warnings)
tw, th = _target_size(maps, max_size)
@@ -192,7 +192,15 @@ def _convert_material(mat, model_name, outdir, max_size):
else:
mix[..., 3] = consts["roughness"]
sname = safe_name(mat.name)
# 中文等非 ASCII 材质名会同样退化(如都变 "mat"),加序号防止互相覆盖
sname = base_sname = safe_name(mat.name)
n = 1
while sname in used_snames:
n += 1
sname = "%s_%d" % (base_sname, n)
used_snames.add(sname)
if sname != base_sname:
warnings.append("材质名 %s 清洗后与其它材质重名,输出改用 %s" % (mat.name, sname))
base_png = os.path.abspath(os.path.join(outdir, "%s_%s_base.png" % (model_name, sname)))
mix_png = os.path.abspath(os.path.join(outdir, "%s_%s_mix.png" % (model_name, sname)))
_save_png(base_png, base)
@@ -242,7 +250,9 @@ def main():
if slot.material and slot.material not in used_mats:
used_mats.append(slot.material)
results = [_convert_material(m, model_name, outdir, max_size) for m in used_mats]
used_snames = set()
results = [_convert_material(m, model_name, outdir, max_size, used_snames)
for m in used_mats]
_strip_textures()
fbx_out = os.path.join(outdir, model_name + ".fbx")
@@ -253,5 +263,5 @@ def main():
ensure_ascii=False))
if __name__ == "__main__" and "--" in __import__("sys").argv:
if __name__ == "__main__" and "--" in sys.argv:
main()
+3 -2
View File
@@ -44,15 +44,16 @@ def write_unity_assets(outdir, summary, max_size):
mix_png = os.path.join(outdir, m["mix_png"])
base_guid = ua.guid_for(base_png)
mix_guid = ua.guid_for(mix_png)
alpha_test = m["alpha_mode"] == "transparency"
with open(base_png + ".meta", "w", encoding="utf-8", newline="\n") as f:
f.write(ua.texture_meta(base_guid, srgb=True, max_size=max_size))
f.write(ua.texture_meta(base_guid, srgb=True, max_size=max_size,
alpha_is_transparency=alpha_test))
with open(mix_png + ".meta", "w", encoding="utf-8", newline="\n") as f:
f.write(ua.texture_meta(mix_guid, srgb=False, max_size=max_size))
mat_name = "%s_%s" % (summary["model"], m["safe_name"])
mat_path = os.path.join(outdir, mat_name + ".mat")
mat_guid = ua.guid_for(mat_path)
alpha_test = m["alpha_mode"] == "transparency"
with open(mat_path, "w", encoding="utf-8", newline="\n") as f:
f.write(ua.material_yaml(mat_name, ua.XPBR_SHADER_GUID,
base_guid, mix_guid, alpha_test))
@@ -35,6 +35,13 @@ class TestTemplates(unittest.TestCase):
self.assertIn("maxTextureSize: 2048", on)
self.assertIn("guid: " + "a" * 32, on)
def test_texture_meta_alpha_is_transparency(self):
default = ua.texture_meta("a" * 32, srgb=True, max_size=2048)
ait = ua.texture_meta("a" * 32, srgb=True, max_size=2048,
alpha_is_transparency=True)
self.assertIn("alphaIsTransparency: 0", default)
self.assertIn("alphaIsTransparency: 1", ait)
def test_material_yaml_refs_and_keyword(self):
y = ua.material_yaml("tong_wood", "s" * 32, "c" * 32, "d" * 32, alpha_test=True)
self.assertIn("m_Name: tong_wood", y)
+4 -3
View File
@@ -33,7 +33,7 @@ def safe_name(name):
return re.sub(r"[^0-9A-Za-z_\-]", "_", name).strip("_") or "mat"
def texture_meta(guid, srgb, max_size):
def texture_meta(guid, srgb, max_size, alpha_is_transparency=False):
return """fileFormatVersion: 2
guid: {guid}
TextureImporter:
@@ -88,7 +88,7 @@ TextureImporter:
spriteBorder: {{x: 0, y: 0, z: 0, w: 0}}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
alphaIsTransparency: {ait}
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
@@ -135,7 +135,8 @@ TextureImporter:
userData:
assetBundleName:
assetBundleVariant:
""".format(guid=guid, srgb=1 if srgb else 0, max_size=max_size)
""".format(guid=guid, srgb=1 if srgb else 0, max_size=max_size,
ait=1 if alpha_is_transparency else 0)
def material_yaml(name, shader_guid, base_tex_guid, mix_tex_guid, alpha_test):