diff --git a/Tools/ModelTranslator/rizom_unwrap.py b/Tools/ModelTranslator/rizom_unwrap.py index 09e8d44a..5326851e 100644 --- a/Tools/ModelTranslator/rizom_unwrap.py +++ b/Tools/ModelTranslator/rizom_unwrap.py @@ -91,16 +91,32 @@ def _call(label, fn, params, timeout=TIMEOUT_S): return res +RETRY = 1 # 实例级重试次数:RizomUV IPC 有 2000ms 内部响应窗,偶发 not responding + + def rizom_unwrap(fbx_path, exe, map_res=MAP_RES, padding_px=PADDING_PX): - """AutoSeam 全自动切缝 -> Unfold -> Pack -> 覆盖保存 fbx_path。失败抛 RizomError。""" + """AutoSeam 全自动切缝 -> Unfold -> Pack -> 覆盖保存 fbx_path。失败抛 RizomError。 + 间歇性 IPC 失败自动换新实例重试一次。""" mod = _import_link(exe) + fbx_abs = os.path.abspath(fbx_path) + pad_uv = float(padding_px) / map_res + last = None + for attempt in range(1 + RETRY): + if attempt: + print("[警告] RizomUV 第 %d 次失败(%s),换新实例重试" % (attempt, last)) + try: + return _unwrap_once(mod, exe, fbx_abs, map_res, pad_uv) + except RizomError as e: + last = e + raise RizomError("重试后仍失败:%s" % last) + + +def _unwrap_once(mod, exe, fbx_abs, map_res, pad_uv): link = mod.CRizomUVLink() try: _call("RunRizomUV", lambda _p: link.RunRizomUV(exePath=exe), None, timeout=60) except RizomError as e: raise RizomError("RizomUV 启动失败(license/环境):%s" % e) - fbx_abs = os.path.abspath(fbx_path) - pad_uv = float(padding_px) / map_res try: _call("Load", link.Load, {"File.Path": fbx_abs, "File.XYZ": True}) # AutoSeam:MOSAIC(QuasiDevelopable) + 切柄/连洞 + 防重叠后处理 diff --git a/Tools/ModelTranslator/tests/test_rizom_unwrap.py b/Tools/ModelTranslator/tests/test_rizom_unwrap.py index 59908c5b..a8443965 100644 --- a/Tools/ModelTranslator/tests/test_rizom_unwrap.py +++ b/Tools/ModelTranslator/tests/test_rizom_unwrap.py @@ -50,5 +50,27 @@ class TestCall(unittest.TestCase): self.assertEqual(ru._call("Ok", lambda p: {"Data": 1}, {}), {"Data": 1}) +class TestRetry(unittest.TestCase): + def test_second_attempt_succeeds(self): + calls = [] + + def fake_once(*a, **kw): + calls.append(1) + if len(calls) == 1: + raise ru.RizomError("IPC 抖动") + + with mock.patch.object(ru, "_import_link"), \ + mock.patch.object(ru, "_unwrap_once", side_effect=fake_once): + ru.rizom_unwrap("x.fbx", "rizomuv.exe") + self.assertEqual(len(calls), 2) + + def test_both_attempts_fail_raises(self): + with mock.patch.object(ru, "_import_link"), \ + mock.patch.object(ru, "_unwrap_once", + side_effect=ru.RizomError("持续失败")), \ + self.assertRaises(ru.RizomError): + ru.rizom_unwrap("x.fbx", "rizomuv.exe") + + if __name__ == "__main__": unittest.main()