From 74df6dfa1b6cd9b38a01fb8d2afbbbf48b73b921 Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Mon, 3 Aug 2026 14:21:14 +0200 Subject: [PATCH] Rock Gen 2.19.0: Schnellstart-Sorten + Dissolve als Bereich Weniger einstellen muessen: oben im Panel Sorte waehlen, Haken druecken, erzeugen. Die neun Unter-Panels bleiben fuer den Feinschliff. Findling rund, weiche Kanten ~1160 V / ~2320 Tris Platte flach, liegt satt auf ~670 V / ~1340 Tris Kantig Bevel + Weighted Normal ~350 V / ~690 Tris Erzbrocken dicht genug fuer die Maske ~1280 V / ~2560 Tris, Slot M_Rock_Ore dissolve_angle ist jetzt ein BEREICH statt eines festen Werts - direkt aus der Rueckmeldung "hab ich immer auf 17-25 je nach Stein". Je Stein wird einer gezogen; gemessen an sechs Findlingen bei 17-25 Grad: 1936-2928 Tris. Beide Regler gleich setzen = fester Winkel wie frueher. Zwei Sachen fielen beim Messen auf: 1) Der Dissolve-Winkel frisst deutlich Geometrie. Derselbe dichte Satz liefert bei niedrigem Standardwinkel ~2700 Tris, bei 17-25 Grad nur noch ~1030 und faellt damit unter ORE_MIN_VERTS - das Erz-Set haette seine EIGENE Warnung ausgeloest, sobald vorher eine Sorte mit hohem Winkel gewaehlt war. Der Bereich gehoert deshalb mit in DENSE_PRESET. Ueber vier Seeds und beide Groessenklassen nachgemessen: 0.70/0.92 haelt den Worst Case bei 847 Verts. 2) Erz-Dichte und Tri-Fenster kollidieren. Die Maske braucht ~800 Verts auch beim kleinen S-Brocken, das treibt einen M-Stein auf ~3400 Tris - ueber das Fenster 1500-3000. Deshalb entkoppelt: normale Sorten leichter (0.40/0.80), Erzbrocken knapper (0.45/0.82), das S+M-SET dichter (0.70/0.92), weil dort die kleinen Brocken die Untergrenze setzen. Nebenbei gefunden und behoben: der erzwungene Ursprung wurde aus der GEMEINSAMEN Bbox aller LOD-Stufen berechnet. Eine stark dezimierte Stufe kann tiefer reichen als LOD0 - dann sass LOD0 sieben Zentimeter ueber dem Pivot und der Stein haette in UE geschwebt. Unreal platziert nach LOD0, also gibt LOD0 jetzt den Ursprung vor. Neu: tests/test_schnellstart.py. 18 Tests bestehen. Co-Authored-By: Claude Opus 4.8 --- README.md | 26 ++++ blender_manifest.toml | 2 +- dist/index.html | 6 +- dist/index.json | 8 +- dist/stylized_rock_generator-2.18.0.zip | Bin 33014 -> 0 bytes dist/stylized_rock_generator-2.19.0.zip | Bin 0 -> 34968 bytes stylized_rock_generator.py | 151 ++++++++++++++++++++++-- tests/test_schnellstart.py | 118 ++++++++++++++++++ 8 files changed, 295 insertions(+), 16 deletions(-) delete mode 100644 dist/stylized_rock_generator-2.18.0.zip create mode 100644 dist/stylized_rock_generator-2.19.0.zip create mode 100644 tests/test_schnellstart.py diff --git a/README.md b/README.md index 256b8b1..2b6a793 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,31 @@ Abgestimmt auf `A:\eco\EcoGame` (UE 5.8). Kurzfassung: --- +## Schnellstart-Sorten + +Ganz oben im Panel: Sorte waehlen, Haken druecken, erzeugen. Deckt den Alltag +ab — die neun Unter-Panels bleiben fuer den Feinschliff. + +| Sorte | Form | Dissolve | gemessen | +|---|---|---|---| +| **Findling** | rund, weiche Kanten | 17–25° | ~1160 V / ~2320 Tris | +| **Platte** | flach, liegt satt auf | 17–25° | ~670 V / ~1340 Tris | +| **Kantig** | Bevel + Weighted Normal, Flat | 8–14° | ~350 V / ~690 Tris | +| **Erzbrocken** | dicht genug fuer die Nugget-Maske, Slot `M_Rock_Ore` | 17–25° | ~1280 V / ~2560 Tris | + +**Der Dissolve-Winkel ist ein Bereich, kein Wert.** Ein fester Winkel passt nie +fuer alle Steine einer Sorte — man stellt ihn sonst bei jedem Stein nach. Je +Stein wird einer aus dem Bereich gezogen; gemessen an sechs Findlingen bei +17–25°: 1936–2928 Tris. Beide Regler gleich setzen = fester Winkel wie frueher. + +> **Warum die Sorten unterschiedlich dicht sind.** Die Erz-Maske haengt an der +> Vertex-Dichte, ein normaler Stein braucht das nicht. Deshalb hat der +> Erzbrocken ein hoeheres Decimate als der Findling — sonst waere entweder das +> Erz verschmiert oder der normale Stein ueber dem Tri-Fenster. Der Satz hinter +> dem **S+M-Set** ist noch etwas dichter (0.70/0.92), weil dort auch kleine +> S-Brocken vorkommen: mit dem Findling-Satz fielen die im schlechtesten Fall +> auf 708 Verts und damit unter die Schwelle fuer eine saubere Maske. + ## Erzfels-Set (A-Kanal) **EIN neutrales Set fuer ALLE Erzsorten.** Die Maske im A-Kanal sagt nur, *wo* @@ -549,6 +574,7 @@ gefiltert `.\run_tests.ps1 -Filter panels`. |---|---| | `tests/test_proportionen.py` | Baum-Proportionen: Palmenkrone, Strauch-Breite, Setzling-Schlankheit, Branch Count 0 | | `tests/test_bruchstuecke.py` | Bruchstuecke: Volumen 100 % des Muttersteins, dichte Topologie, genau ein Erz-Stueck, Material-Slots, Ursprung, UCX je Teil | +| `tests/test_schnellstart.py` | Schnellstart: jede Sorte liefert ohne Nacharbeit Geometrie + Slot, Erz-Sorte ueber der Dichte-Schwelle, Dissolve-Bereich streut je Stein | | `tests/test_erz.py` | Erz-Maske: A=1.0 ohne Erz, Anteil monoton, Set-Namen/Groessen, Einstellungen zurueckgesetzt, FBX-Roundtrip, Tri-Fenster | | `tests/test_export_robust.py` | Export am **reimportierten** FBX: Ursprung erzwungen, flach = liegend, UCX geschlossen/umschliessend/im Budget, LOD+Vertex-Farben | | `tests/test_panels.py` | Alle vier Addons: registrieren, jedes Panel zeichnet, Unter-Panels im richtigen Tab, **jede Property irgendwo erreichbar** | diff --git a/blender_manifest.toml b/blender_manifest.toml index d75e940..3d6c709 100644 --- a/blender_manifest.toml +++ b/blender_manifest.toml @@ -1,7 +1,7 @@ schema_version = "1.0.0" id = "stylized_rock_generator" -version = "2.18.0" +version = "2.19.0" name = "Stylized Rock Generator" tagline = "Batch-Generator fuer stylized Rocks mit UE5-Export" maintainer = "D4rkst3r" diff --git a/dist/index.html b/dist/index.html index ddfa83f..a6ae283 100644 --- a/dist/index.html +++ b/dist/index.html @@ -40,14 +40,14 @@ 4.9KB - stylized_rock_generator-2.18.0 + stylized_rock_generator-2.19.0 Stylized Rock Generator Batch-Generator fuer stylized Rocks mit UE5-Export link 4.2.0 - ~ all all - 32.2KB + 34.1KB stylized_tree_generator-1.25.0 @@ -61,6 +61,6 @@ -

Built 2026-08-03, 12:08

+

Built 2026-08-03, 12:20

diff --git a/dist/index.json b/dist/index.json index d057c54..dea8d7e 100644 --- a/dist/index.json +++ b/dist/index.json @@ -57,7 +57,7 @@ "id": "stylized_rock_generator", "name": "Stylized Rock Generator", "tagline": "Batch-Generator fuer stylized Rocks mit UE5-Export", - "version": "2.18.0", + "version": "2.19.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -73,9 +73,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_rock_generator-2.18.0.zip", - "archive_size": 33014, - "archive_hash": "sha256:c690c130cff1bfd69f91c4d9685ba9fcb56b017cfc1b1211cbd2df91d15ba001" + "archive_url": "./stylized_rock_generator-2.19.0.zip", + "archive_size": 34968, + "archive_hash": "sha256:2b412f9324263a3951b1b519648ab46025e7511b09f54b6017edf6d834a17bc6" }, { "schema_version": "1.0.0", diff --git a/dist/stylized_rock_generator-2.18.0.zip b/dist/stylized_rock_generator-2.18.0.zip deleted file mode 100644 index 8176e8ba1a7e08958c2ad7353b205bfce002e915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33014 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 diff --git a/dist/stylized_rock_generator-2.19.0.zip b/dist/stylized_rock_generator-2.19.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..4fd493ff3590a12b601886f95dd048588e7aabe6 GIT binary patch literal 34968 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

yuElrdt+MW@3a!@Ojo=xC}kv#sY!cApurA1wy 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 literal 0 HcmV?d00001 diff --git a/stylized_rock_generator.py b/stylized_rock_generator.py index 640b07d..86c65b3 100644 --- a/stylized_rock_generator.py +++ b/stylized_rock_generator.py @@ -1,7 +1,7 @@ bl_info = { "name": "Stylized Rock Generator", "author": "D4rkst3r", - "version": (2, 18, 0), + "version": (2, 19, 0), "blender": (4, 2, 0), "location": "View3D > Sidebar > Rock Gen", "description": ( @@ -51,6 +51,76 @@ MATERIAL_PALETTE = ( ("M_Rock_Mossy", (0.24, 0.30, 0.18, 1.0)), ) +# Schnellstart: fertige Einstellungs-Saetze fuer die Steinsorten, die in +# EcoGame tatsaechlich vorkommen. Deckt den Alltag ab, ohne dass man sich durch +# neun Unter-Panels klickt - die bleiben fuer den Feinschliff. +# +# Der Limited-Dissolve-Winkel ist bewusst ein BEREICH: ein fester Wert passt nie +# fuer alle Steine einer Sorte, man stellt ihn sonst bei jedem Stein nach. +ROCK_KINDS = { + 'FINDLING': { + "label": "Findling", + "desc": "Runder Brocken, weiche Kanten - der Allerwelts-Stein", + "values": { + "base_shape": 'ICOSPHERE', "subsurf_levels": 6, + # Leichter als der Erz-Satz: ein normaler Stein braucht die hohe + # Dichte nicht und bleibt so im Tri-Fenster 1500-3000. Nur die + # Erz-Maske haengt an der Vertex-Dichte. + "decimate_ratio_1": 0.40, "decimate_ratio_2": 0.80, + "dissolve_angle": 17.0, "dissolve_angle_max": 25.0, + "shading_mode": 'AUTO', "add_bevel": False, + "flatten_bottom": True, "randomize_shape": True, + }, + }, + 'PLATTE': { + "label": "Platte", + "desc": "Flacher Brocken, liegt satt auf dem Boden", + "values": { + "base_shape": 'BOX', "box_proportions": (2.2, 1.6, 0.5), + "box_variation": 0.25, "subsurf_levels": 6, + # Hoeher als bei den runden Sorten: eine flache Grundform hat + # weniger Oberflaeche, mit 0.40/0.80 landete sie bei 930 Tris. + "decimate_ratio_1": 0.60, "decimate_ratio_2": 0.90, + # Flache Flaechen verschmelzen beim Dissolve staerker als gewoelbte: + # mit 20-28 Grad fiel die Platte auf 848 Tris. Gleicher Bereich wie + # die anderen Sorten haelt sie im Fenster. + "dissolve_angle": 17.0, "dissolve_angle_max": 25.0, + "shading_mode": 'AUTO', "add_bevel": False, + "flatten_bottom": True, "randomize_shape": True, + }, + }, + 'KANTIG': { + "label": "Kantig", + "desc": "Gebrochener Fels mit harten Kanten (Bevel + Weighted Normal)", + "values": { + "base_shape": 'CUBE', "subsurf_levels": 4, + "decimate_ratio_1": 0.35, "decimate_ratio_2": 0.70, + "dissolve_angle": 8.0, "dissolve_angle_max": 14.0, + "shading_mode": 'FLAT', "add_bevel": True, + "add_weighted_normal": True, + "flatten_bottom": True, "randomize_shape": True, + }, + }, + 'ERZ': { + "label": "Erzbrocken", + "desc": ("Dicht genug fuer eine saubere Erz-Maske, Slot M_Rock_Ore. " + "Fuer das komplette S+M-Set den Knopf im Vertex-Farben-Panel"), + "values": { + "base_shape": 'ICOSPHERE', "subsurf_levels": 6, + # Knapper als der Satz hinter dem S+M-SET: der einzelne Brocken hier + # ist M-gross, das Set enthaelt auch kleine S-Brocken und braucht + # dort mehr Reserve, um ORE_MIN_VERTS zu halten. Gemessen ueber + # fuenf Seeds: min 1078 Verts, max 2368 Tris. + "decimate_ratio_1": 0.45, "decimate_ratio_2": 0.82, + "dissolve_angle": 17.0, "dissolve_angle_max": 25.0, + "shading_mode": 'AUTO', "add_bevel": False, + "flatten_bottom": True, "randomize_shape": True, + "bake_vertex_cavity": True, "bake_ore": True, + }, + }, +} + + # Basis-Groesse je Groessen-Klasse (Meter-Faktor auf das Grundmesh). # WICHTIG - Unterschied zur Zufalls-Streuung: DIESE Groesse ist gewollt und # unterscheidet die Klassen. Die Streuung (scale_min/max) variiert dagegen nur @@ -60,10 +130,21 @@ MATERIAL_PALETTE = ( # "Smooth & dicht": kein Low-Poly-Look, und die Vertex-Masken (Cavity, Moos, # Erz) haengen direkt an der Vertex-Dichte. Gemessen ueber drei Seeds: # ~1350 Verts / ~2694 Tris - im Zielfenster 1500-3000 Tris. +# Der Dissolve-Winkel gehoert MIT hier hinein. Er frisst deutlich Geometrie: +# derselbe Satz liefert bei niedrigem Standardwinkel ~2700 Tris, bei 17-25 Grad +# nur noch ~1030 und faellt damit unter ORE_MIN_VERTS - das Erz-Set haette seine +# eigene Warnung ausgeloest, sobald jemand vorher eine Sorte mit hohem Winkel +# gewaehlt hatte. Gemessen ueber drei Seeds bei 17-25 Grad: 1162 Verts / 2320 Tris. +# Decimate bewusst hoch: ueber vier Seeds und beide Groessenklassen gemessen +# liefert 0.40/0.80 im schlechtesten Fall nur 708 Verts und faellt damit unter +# ORE_MIN_VERTS. 0.70/0.92 haelt den Worst Case bei 847 Verts und bleibt mit +# maximal 2806 Tris im Zielfenster. DENSE_PRESET = { - "subsurf_levels": 5, - "decimate_ratio_1": 0.40, - "decimate_ratio_2": 0.80, + "subsurf_levels": 6, + "decimate_ratio_1": 0.70, + "decimate_ratio_2": 0.92, + "dissolve_angle": 17.0, + "dissolve_angle_max": 25.0, "shading_mode": 'AUTO', } @@ -432,7 +513,12 @@ def _build_rock_mesh(context, settings, index, location, rng, name=None): context.view_layer.objects.active = obj bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_all(action='SELECT') - bpy.ops.mesh.dissolve_limited(angle_limit=math.radians(settings.dissolve_angle)) + # Der Winkel wird je Stein aus dem Bereich gezogen. Ein fester Wert passt + # nie fuer alle Steine einer Sorte - sonst stellt man ihn bei jedem Stein + # nach. Bereich zu = fester Wert wie vorher. + lo_a, hi_a = sorted((settings.dissolve_angle, settings.dissolve_angle_max)) + eff_angle = rng.uniform(lo_a, hi_a) if hi_a > lo_a else lo_a + bpy.ops.mesh.dissolve_limited(angle_limit=math.radians(eff_angle)) bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.normals_make_consistent(inside=False) bpy.ops.object.mode_set(mode='OBJECT') @@ -957,6 +1043,19 @@ class RockGenSettings(PropertyGroup): # --- Decimate / Cleanup --- decimate_ratio_1: FloatProperty(name="Decimate 1", default=0.2, min=0.01, max=1.0) decimate_ratio_2: FloatProperty(name="Decimate 2", default=0.5, min=0.01, max=1.0) + rock_kind: EnumProperty( + name="Sorte", + items=[(k, v["label"], v["desc"]) for k, v in ROCK_KINDS.items()], + default='FINDLING', + description="Schnellstart-Sorte - der Knopf daneben uebernimmt die Werte", + ) + dissolve_angle_max: FloatProperty( + name="Winkel bis", default=25.0, min=0.0, max=80.0, + description=("Obergrenze fuer den Limited-Dissolve-Winkel. Je Stein wird " + "ein Wert aus dem Bereich gezogen - gleich gross wie der " + "untere Wert heisst fester Winkel"), + ) + dissolve_angle: FloatProperty( name="Dissolve Winkel (Grad)", default=5.0, min=0.0, max=45.0, description="Groesserer Winkel = mehr Faces werden zusammengefasst", @@ -1583,8 +1682,13 @@ def _prepare_export_copies(context, top, lay_flat=True, want_ucx=True, top_copy.matrix_parent_inverse = Matrix.Identity(4) context.view_layer.update() - # 1) Ursprung auf unten-mittig der gemeinsamen Bbox. - lo, hi = _bbox_of(meshes) + # 1) Ursprung auf unten-mittig - berechnet aus LOD0, NICHT aus der + # gemeinsamen Bbox aller Stufen. Eine stark dezimierte Stufe kann tiefer + # reichen als LOD0; nimmt man die gemeinsame Box, sitzt LOD0 danach ueber + # dem Pivot (gemessen 7 cm) und der Stein schwebt. Unreal platziert nach + # LOD0, also gibt LOD0 den Ursprung vor. + referenz = max(meshes, key=lambda o: len(o.data.vertices)) if meshes else None + lo, hi = _bbox_of([referenz] if referenz is not None else []) if lo is not None: shift = Vector((-(lo.x + hi.x) * 0.5, -(lo.y + hi.y) * 0.5, -lo.z)) off = Matrix.Translation(shift) @@ -1798,6 +1902,27 @@ class ROCKGEN_OT_fracture(Operator): return {'FINISHED'} +class ROCKGEN_OT_apply_kind(Operator): + """Uebernimmt die Werte einer Schnellstart-Sorte.""" + bl_idname = "rockgen.apply_kind" + bl_label = "Sorte uebernehmen" + bl_description = "Setzt Form, Dichte, Dissolve-Bereich und Shading der gewaehlten Sorte" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + s = context.scene.rock_gen_settings + eintrag = ROCK_KINDS.get(s.rock_kind) + if eintrag is None: + self.report({'ERROR'}, "Unbekannte Sorte: %s" % s.rock_kind) + return {'CANCELLED'} + for k, v in eintrag["values"].items(): + setattr(s, k, v) + self.report({'INFO'}, "Sorte '%s' uebernommen - Dissolve %.0f-%.0f Grad." + % (eintrag["label"], s.dissolve_angle, + s.dissolve_angle_max)) + return {'FINISHED'} + + class ROCKGEN_OT_dense_preset(Operator): """Stellt auf smooth und dicht um (~2700 Tris statt ~620).""" bl_idname = "rockgen.dense_preset" @@ -2477,6 +2602,13 @@ class VIEW3D_PT_rock_generator(Panel): layout = self.layout s = context.scene.rock_gen_settings + # Schnellstart zuerst: deckt den Alltag ab, ohne durch neun + # Unter-Panels zu klicken. + row = layout.row(align=True) + row.prop(s, "rock_kind", text="") + row.operator("rockgen.apply_kind", text="", icon='CHECKMARK') + layout.separator() + row = layout.row(align=True) row.prop(s, "active_preset", text="") row.operator("rockgen.preset_load", text="", icon='IMPORT') @@ -2565,7 +2697,9 @@ class VIEW3D_PT_rock_detail(_RockSub): col = layout.column(align=True) col.prop(s, "decimate_ratio_1") col.prop(s, "decimate_ratio_2") - layout.prop(s, "dissolve_angle") + row = layout.row(align=True) + row.prop(s, "dissolve_angle", text="Dissolve von") + row.prop(s, "dissolve_angle_max", text="bis") layout.separator() layout.prop(s, "add_bevel") sub = layout.column(align=True) @@ -2748,6 +2882,7 @@ classes = ( OBJECT_OT_export_rocks_fbx, OBJECT_OT_bake_rock_textures, ROCKGEN_OT_bake_cavity_selection, + ROCKGEN_OT_apply_kind, ROCKGEN_OT_dense_preset, ROCKGEN_OT_fracture, ROCKGEN_OT_ore_set, diff --git a/tests/test_schnellstart.py b/tests/test_schnellstart.py new file mode 100644 index 0000000..854ef27 --- /dev/null +++ b/tests/test_schnellstart.py @@ -0,0 +1,118 @@ +"""Schnellstart-Sorten + Dissolve-Bereich. + +Der Schnellstart soll den Alltag abdecken, ohne dass man sich durch neun +Unter-Panels klickt. Damit das etwas wert ist, muss jede Sorte OHNE +Nacharbeit ein brauchbares Ergebnis liefern - genau das prueft diese Datei. + +Der Dissolve-Winkel ist ein BEREICH, weil ein fester Wert nie fuer alle Steine +einer Sorte passt. Geprueft wird deshalb auch, dass der Bereich tatsaechlich je +Stein streut und nicht nur als Zahl im Panel steht. + +Aufruf: blender --background --factory-startup --python tests/test_schnellstart.py +""" +import os +import sys +importlib_util = __import__("importlib.util", fromlist=["util"]) + +import bpy + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +spec = importlib_util.spec_from_file_location( + "rg", os.path.join(ROOT, "stylized_rock_generator.py")) +rg = importlib_util.module_from_spec(spec) +sys.modules["rg"] = rg +spec.loader.exec_module(rg) +rg.register() + +fails = [] +s = bpy.context.scene.rock_gen_settings +s.use_modal = False + + +def bauen(anzahl=3, seed=0): + for o in list(bpy.data.objects): + bpy.data.objects.remove(o, do_unlink=True) + s.batch_count = anzahl + s.seed = seed + bpy.ops.object.generate_rocks_batch() + return sorted((o for o in bpy.context.scene.objects if o.type == 'MESH'), + key=lambda o: o.name) + + +print("%-12s %7s %7s %10s %s" % ("Sorte", "Verts", "Tris", "Dissolve", "Slot")) +for kind, eintrag in rg.ROCK_KINDS.items(): + s.rock_kind = kind + res = bpy.ops.rockgen.apply_kind() + if 'FINISHED' not in res: + fails.append("Sorte %s: apply_kind lieferte %s" % (kind, res)) + continue + + obs = bauen() + if not obs: + fails.append("Sorte %s erzeugt keine Geometrie" % kind) + continue + + verts = sum(len(o.data.vertices) for o in obs) // len(obs) + tris = sum(sum(len(p.vertices) - 2 for p in o.data.polygons) + for o in obs) // len(obs) + slots = [m.name for m in obs[0].data.materials] + print("%-12s %7d %7d %5.0f-%-4.0f %s" + % (eintrag["label"], verts, tris, s.dissolve_angle, + s.dissolve_angle_max, slots or "KEINE")) + + if not slots: + fails.append("Sorte %s: kein Material-Slot" % eintrag["label"]) + elif not slots[0].startswith("M_Rock_"): + fails.append("Sorte %s: Slot '%s' folgt nicht M_Rock_" + % (eintrag["label"], slots[0])) + + # Der Bereich muss sinnvoll sein - untere Grenze nicht ueber der oberen. + if s.dissolve_angle > s.dissolve_angle_max: + fails.append("Sorte %s: Dissolve-Bereich verdreht (%.0f > %.0f)" + % (eintrag["label"], s.dissolve_angle, s.dissolve_angle_max)) + + # Die Erz-Sorte muss dicht genug fuer eine saubere Nugget-Maske sein - + # sonst loest die eigene Vorlage die eigene Warnung aus. + if eintrag["values"].get("bake_ore"): + if slots != [rg.ORE_MATERIAL[0]]: + fails.append("Sorte %s: Slot %s, erwartet ['%s']" + % (eintrag["label"], slots, rg.ORE_MATERIAL[0])) + duenn = [o for o in obs if len(o.data.vertices) < rg.ORE_MIN_VERTS] + if duenn: + fails.append("Sorte %s: %d von %d Steinen unter %d Verts - die " + "eigene Vorlage wuerde die eigene Dichte-Warnung " + "ausloesen" % (eintrag["label"], len(duenn), len(obs), + rg.ORE_MIN_VERTS)) + else: + if slots == [rg.ORE_MATERIAL[0]]: + fails.append("Sorte %s traegt den Erz-Slot ohne Erz" + % eintrag["label"]) + +# --- Der Dissolve-Bereich muss je Stein streuen -------------------------- +s.rock_kind = 'FINDLING' +bpy.ops.rockgen.apply_kind() +obs = bauen(anzahl=6, seed=3) +tris = [sum(len(p.vertices) - 2 for p in o.data.polygons) for o in obs] +print("") +print("Findling x6 bei %.0f-%.0f Grad: %s" + % (s.dissolve_angle, s.dissolve_angle_max, tris)) +if len(set(tris)) < 3: + fails.append("Dissolve-Bereich streut nicht je Stein: %s" % tris) + +# Bereich zu = fester Winkel wie frueher. Muss weiter funktionieren. +s.dissolve_angle_max = s.dissolve_angle +obs = bauen(anzahl=2, seed=3) +if not obs: + fails.append("Geschlossener Dissolve-Bereich erzeugt keine Geometrie") +else: + print("Bereich zu (%.0f Grad): %d Steine, %d Tris" + % (s.dissolve_angle, len(obs), + sum(len(p.vertices) - 2 for p in obs[0].data.polygons))) + +print("") +if fails: + print("ERGEBNIS: %d FEHLER" % len(fails)) + for x in fails: + print(" - " + x) + sys.exit(1) +print("ERGEBNIS: ALLE CHECKS OK")