"""Prueft das gebaute Tree-Addon: registrieren, Operator ausfuehren, Ergebnis messen.""" import bpy, sys, zipfile, os, tempfile, importlib.util, traceback ZIP = r"A:\eco\stylized_rock_generator\dist\stylized_tree_generator-1.19.0.zip" fails = [] tmp = tempfile.mkdtemp() with zipfile.ZipFile(ZIP) as z: z.extractall(tmp) init = None for root, _, files in os.walk(tmp): if "__init__.py" in files: init = os.path.join(root, "__init__.py"); break if not init: print("FAIL: __init__.py nicht im Zip"); sys.exit(1) print("Zip-Inhalt ok:", os.path.relpath(init, tmp)) spec = importlib.util.spec_from_file_location("stylized_tree_generator", init) m = importlib.util.module_from_spec(spec) sys.modules["stylized_tree_generator"] = m try: spec.loader.exec_module(m) m.register() print("registriert ok") except Exception: traceback.print_exc(); print("FAIL: register"); sys.exit(1) s = bpy.context.scene.tree_gen_settings # 1) einzelner Baum je Preset for p in ("baum", "palme", "busch", "kaktus"): for o in list(bpy.data.objects): bpy.data.objects.remove(o, do_unlink=True) s.preset = p; s.use_growth = False; s.seed = 3 r = bpy.ops.object.treegen_create() obs = [o for o in bpy.data.objects if o.type == 'MESH'] bpy.context.view_layer.update() dg = bpy.context.evaluated_depsgraph_get() v = len(obs[0].evaluated_get(dg).data.vertices) if obs else 0 ok = ('FINISHED' in r) and v > 0 print("preset %-7s -> %s verts=%d" % (p, "ok" if ok else "FAIL", v)) if not ok: fails.append(p) # 2) Wachstums-Stufen for o in list(bpy.data.objects): bpy.data.objects.remove(o, do_unlink=True) s.preset = "baum"; s.use_growth = True; s.stages = 4 r = bpy.ops.object.treegen_create() obs = sorted([o for o in bpy.data.objects if o.type == 'MESH'], key=lambda o: o.name) bpy.context.view_layer.update() dg = bpy.context.evaluated_depsgraph_get() counts = [len(o.evaluated_get(dg).data.vertices) for o in obs] growing = all(counts[i] < counts[i+1] for i in range(len(counts)-1)) print("stufen: %d Objekte verts=%s aufsteigend=%s" % (len(obs), counts, growing)) if len(obs) != 4 or not growing: fails.append("stages") # 3) Modifier anwenden (Export-Pfad) for o in list(bpy.data.objects): bpy.data.objects.remove(o, do_unlink=True) s.use_growth = False; s.apply_modifier = True s.generate_lightmap_uv = True # Default ist AUS (EcoGame: dynamisches Licht) bpy.ops.object.treegen_create() obs = [o for o in bpy.data.objects if o.type == 'MESH'] real = len(obs[0].data.vertices) if obs else 0 # echte Mesh-Daten, nicht evaluated uvs = [l.name for l in obs[0].data.uv_layers] if obs else [] print("apply_modifier -> echte Verts=%d mods=%d uvs=%s" % (real, len(obs[0].modifiers) if obs else -1, uvs)) if real == 0: fails.append("apply") if "UVMap" not in uvs: fails.append("uv0") if "Lightmap" not in uvs: fails.append("uv1") # UV muss world-space sein: V-Bereich ~ Baumhoehe if obs and obs[0].data.uv_layers.get("UVMap"): d = obs[0].data.uv_layers["UVMap"].data vs = [x.uv[1] for x in d] h = max(v.co.z for v in obs[0].data.vertices) print("UV world-space check: V-max=%.2f Baumhoehe=%.2f" % (max(vs), h)) if max(vs) < h * 0.5: fails.append("uv_scale") m.unregister() print("ERGEBNIS:", "ALLE TESTS BESTANDEN" if not fails else ("FEHLER: " + ", ".join(fails))) sys.exit(1 if fails else 0)