Beide Addons auf die EcoGame-Konventionen abgestimmt
Rock Generator 2.4.0: - Benennung Fels_<Form>_<Klasse> statt Rock_000 (Praefix/Form/Klasse im Panel, Klasse S/M/L/XL, optionale Durchnummerierung bei Batches) - Bake liefert jetzt <name>_albedo und <name>_normal. AO/Cavity wird per Option MULTIPLIKATIV ins Albedo gebacken (Staerke regelbar) - separate Roughness- und AO-Paesse sind Default aus, weil Roughness in EcoGame eine Zahl im Master- Material ist. Gemessen: Albedo-Mittelwert 0.549 -> 0.433 mit AO, Kontrast rauf. - UV1 Lightmap Default AUS (EcoGame beleuchtet dynamisch) Tree Generator 1.18.0: - Benennung <Art>_<Variante>_S<Stufe>, z.B. Birke_01_S1..S4 (statt stage0..3); Art-Feld und Varianten-Nummer im Panel, Art leer = Preset-Name - UV1 Lightmap Default AUS README: Konventionen dokumentiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,37 @@
|
||||
|
||||
---
|
||||
|
||||
## EcoGame-Konventionen (beide Addons)
|
||||
|
||||
Abgestimmt auf `A:\eco\EcoGame` (UE 5.8). Kurzfassung:
|
||||
|
||||
**Benennung**
|
||||
- Felsen: `Fels_<Form>_<Klasse>` — Form = Buchstabe (A, B, …), Klasse = `S/M/L/XL`.
|
||||
Die Klasse meint eine eigene **Silhouette**, nicht blosse Groesse: rein
|
||||
groesser/kleiner macht die Engine ueber ScaleMin/Max.
|
||||
- Baeume: `<Art>_<Variante>_S<Stufe>`, z. B. `Birke_01_S1` … `Birke_01_S4`.
|
||||
Zusatz-Ebenen haengen hinten an: `_Leaf`, `_Frucht`.
|
||||
- Texturen: `<name>_albedo` und `<name>_normal` — mehr nicht.
|
||||
|
||||
**Textur-Bake**
|
||||
- Nur **Albedo + Normal**. Roughness ist im Master-Material eine **Zahl**,
|
||||
keine Textur.
|
||||
- **AO/Cavity wird ins Albedo multipliziert** (Option „AO ins Albedo einrechnen",
|
||||
Staerke regelbar). Dunkle Ritzen und helle Platten stecken im Farbbild — das
|
||||
traegt den Stylized-Look. Separate Rough-/AO-Paesse sind Default **aus**.
|
||||
- 1024 px reicht fuer stylized Formen.
|
||||
- Tileable (4D-Torus) passt zum triplanar mappenden Master-Material.
|
||||
|
||||
**Mesh**
|
||||
- Echte Meter, Ursprung unten-mittig, FBX pro Asset bzw. LOD-Gruppe.
|
||||
- **UV1 Lightmap ist Default aus** — EcoGame beleuchtet dynamisch.
|
||||
- Meshes brauchen **keine eigenen Materialien**; in UE bekommt alles die
|
||||
Material-Instanz vom Master. Ein Platzhalter im FBX ist okay.
|
||||
- Scale-Randomisierung nur fuer die **Form** (nicht-uniform) nutzen, nicht fuer
|
||||
die Gesamtgroesse — sonst multipliziert sie sich mit ScaleMin/Max der Engine.
|
||||
|
||||
---
|
||||
|
||||
## Stylized Tree Generator
|
||||
|
||||
Parametrischer **Geaest**-Generator (Stamm + Aeste + Sub-Aeste) als Geometry-Nodes-
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
schema_version = "1.0.0"
|
||||
|
||||
id = "stylized_rock_generator"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
name = "Stylized Rock Generator"
|
||||
tagline = "Batch-Generator fuer stylized Rocks mit UE5-Export"
|
||||
maintainer = "D4rkst3r"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
schema_version = "1.0.0"
|
||||
|
||||
id = "stylized_tree_generator"
|
||||
version = "1.17.0"
|
||||
version = "1.18.0"
|
||||
name = "Stylized Tree Generator"
|
||||
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
|
||||
maintainer = "D4rkst3r"
|
||||
|
||||
Vendored
+8
-8
@@ -7,7 +7,7 @@
|
||||
"id": "stylized_rock_generator",
|
||||
"name": "Stylized Rock Generator",
|
||||
"tagline": "Batch-Generator fuer stylized Rocks mit UE5-Export",
|
||||
"version": "2.3.0",
|
||||
"version": "2.4.0",
|
||||
"type": "add-on",
|
||||
"maintainer": "D4rkst3r",
|
||||
"license": [
|
||||
@@ -23,16 +23,16 @@
|
||||
"Mesh",
|
||||
"Modeling"
|
||||
],
|
||||
"archive_url": "./stylized_rock_generator-2.3.0.zip",
|
||||
"archive_size": 14694,
|
||||
"archive_hash": "sha256:a6e15dd94c6b77dc1ef7c631d1d1dce275a8d3550d16369d90675a2f42fa6298"
|
||||
"archive_url": "./stylized_rock_generator-2.4.0.zip",
|
||||
"archive_size": 16036,
|
||||
"archive_hash": "sha256:e7163f6f0c53731f897b8a1ba63db1cdab94aa182dd720ca1a5653a2ca3df9ec"
|
||||
},
|
||||
{
|
||||
"schema_version": "1.0.0",
|
||||
"id": "stylized_tree_generator",
|
||||
"name": "Stylized Tree Generator",
|
||||
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
|
||||
"version": "1.17.0",
|
||||
"version": "1.18.0",
|
||||
"type": "add-on",
|
||||
"maintainer": "D4rkst3r",
|
||||
"license": [
|
||||
@@ -48,9 +48,9 @@
|
||||
"Mesh",
|
||||
"Modeling"
|
||||
],
|
||||
"archive_url": "./stylized_tree_generator-1.17.0.zip",
|
||||
"archive_size": 16523,
|
||||
"archive_hash": "sha256:49c3e777aa602ba3c63537aacd866bb5b11ac6484dbc0f91b28d26f497f98c00"
|
||||
"archive_url": "./stylized_tree_generator-1.18.0.zip",
|
||||
"archive_size": 16777,
|
||||
"archive_hash": "sha256:9ea5b7a9c01f3c1b382436d25539ab9ec41ffb8b051d26c17c82783c594680a0"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+113
-24
@@ -1,7 +1,7 @@
|
||||
bl_info = {
|
||||
"name": "Stylized Rock Generator",
|
||||
"author": "D4rkst3r",
|
||||
"version": (2, 3, 0),
|
||||
"version": (2, 4, 0),
|
||||
"blender": (4, 2, 0),
|
||||
"location": "View3D > Sidebar > Rock Gen",
|
||||
"description": (
|
||||
@@ -102,6 +102,16 @@ def _apply_modifier(context, obj, mod_name):
|
||||
raise RockGenError("Modifier '%s' Apply wurde abgebrochen." % mod_name)
|
||||
|
||||
|
||||
def _asset_name(settings, index, batch_count):
|
||||
"""EcoGame-Schema: Fels_<Form>_<Klasse>, bei Batches mit laufender Nummer."""
|
||||
base = "%s_%s_%s" % (settings.name_prefix.strip() or "Fels",
|
||||
(settings.name_form.strip() or "A").upper(),
|
||||
settings.name_class)
|
||||
if settings.name_numbered and batch_count > 1:
|
||||
return "%s_%02d" % (base, index + 1)
|
||||
return base
|
||||
|
||||
|
||||
def _face_count(obj):
|
||||
return len(obj.data.polygons)
|
||||
|
||||
@@ -279,7 +289,7 @@ def _make_lightmap_uv(context, obj):
|
||||
# Mesh-Aufbau
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _build_rock_mesh(context, settings, index, location, rng):
|
||||
def _build_rock_mesh(context, settings, index, location, rng, name=None):
|
||||
"""Baut das reine Rock-Mesh (ohne Transform/Material). Kann RockGenError werfen."""
|
||||
# 1. Basis-Mesh
|
||||
if settings.base_shape == 'CUBE':
|
||||
@@ -289,7 +299,7 @@ def _build_rock_mesh(context, settings, index, location, rng):
|
||||
subdivisions=1, radius=1.0, location=location
|
||||
)
|
||||
obj = context.active_object
|
||||
obj.name = "Rock_%03d" % index
|
||||
obj.name = name or ("Rock_%03d" % index)
|
||||
|
||||
# Effektive Form-Parameter (optional pro Rock variiert)
|
||||
eff_noise = settings.noise_scale
|
||||
@@ -504,10 +514,10 @@ def _parent_keep_transform(child, parent):
|
||||
child.matrix_parent_inverse = parent.matrix_world.inverted()
|
||||
|
||||
|
||||
def _build_lod_group(context, settings, index, location, rng):
|
||||
base_name = "Rock_%03d" % index
|
||||
def _build_lod_group(context, settings, index, location, rng, base_name=None):
|
||||
base_name = base_name or ("Rock_%03d" % index)
|
||||
|
||||
lod0 = _build_rock_mesh(context, settings, index, location, rng)
|
||||
lod0 = _build_rock_mesh(context, settings, index, location, rng, name=base_name)
|
||||
_apply_hardsurface(context, lod0, settings)
|
||||
_apply_random_transform(context, lod0, settings, rng)
|
||||
if settings.assign_material:
|
||||
@@ -556,15 +566,16 @@ def _build_lod_group(context, settings, index, location, rng):
|
||||
# Ein Rock (bzw. eine LOD-Gruppe) erzeugen
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def make_one_rock(context, settings, index):
|
||||
def make_one_rock(context, settings, index, batch_count=1):
|
||||
"""Erzeugt genau einen Rock / eine LOD-Gruppe. Liefert Liste der Objekte."""
|
||||
rng = random.Random(settings.seed + index * 9973)
|
||||
location = (index * settings.spacing, 0.0, 0.0)
|
||||
name = _asset_name(settings, index, batch_count)
|
||||
|
||||
if settings.generate_lods:
|
||||
return _build_lod_group(context, settings, index, location, rng)
|
||||
return _build_lod_group(context, settings, index, location, rng, base_name=name)
|
||||
|
||||
obj = _build_rock_mesh(context, settings, index, location, rng)
|
||||
obj = _build_rock_mesh(context, settings, index, location, rng, name=name)
|
||||
_apply_hardsurface(context, obj, settings)
|
||||
_apply_random_transform(context, obj, settings, rng)
|
||||
_apply_shading(context, obj, settings)
|
||||
@@ -645,8 +656,9 @@ class RockGenSettings(PropertyGroup):
|
||||
description="Fuer Material-Maker-Texturen (Albedo/Normal/Roughness/AO)",
|
||||
)
|
||||
generate_lightmap_uv: BoolProperty(
|
||||
name="UV1 Lightmap-UV", default=True,
|
||||
description="Separates, nicht ueberlappendes UV fuer Unreal Static-Mesh-Lightmaps",
|
||||
name="UV1 Lightmap-UV", default=False,
|
||||
description=("Separates, nicht ueberlappendes UV fuer Static-Mesh-Lightmaps. "
|
||||
"EcoGame beleuchtet dynamisch - dort nicht noetig"),
|
||||
)
|
||||
|
||||
# --- Hard-Surface (optional) ---
|
||||
@@ -736,19 +748,57 @@ class RockGenSettings(PropertyGroup):
|
||||
name="Bake-Ordner", default="", subtype='DIR_PATH',
|
||||
description="Zielordner fuer die gebackenen Textur-PNGs",
|
||||
)
|
||||
# --- Benennung (EcoGame-Schema: Fels_<Form>_<Klasse>) ---
|
||||
name_prefix: StringProperty(
|
||||
name="Praefix", default="Fels",
|
||||
description="Basisname, z.B. 'Fels' oder 'Felsblock'",
|
||||
)
|
||||
name_form: StringProperty(
|
||||
name="Form", default="A",
|
||||
description="Form-Variante als Buchstabe (A, B, C ...)",
|
||||
)
|
||||
name_class: EnumProperty(
|
||||
name="Groessen-Klasse",
|
||||
items=[('S', "S", "klein"), ('M', "M", "mittel"),
|
||||
('L', "L", "gross"), ('XL', "XL", "sehr gross")],
|
||||
default='M',
|
||||
description=("Groessen-KLASSE mit eigener Geometrie. Reines Groesser/Kleiner "
|
||||
"macht die Engine ueber ScaleMin/Max - eine eigene Klasse nur, "
|
||||
"wenn sich die Silhouette aendert"),
|
||||
)
|
||||
name_numbered: BoolProperty(
|
||||
name="Bei Batch durchnummerieren", default=True,
|
||||
description="Haengt bei mehreren Rocks _01, _02 ... an (sonst Blender-Suffix)",
|
||||
)
|
||||
|
||||
bake_prefix: StringProperty(
|
||||
name="Textur-Prefix", default="T_Rock_Stylized",
|
||||
description="Dateiname-Prefix (UE-Konvention T_)",
|
||||
name="Textur-Name", default="fels_a",
|
||||
description="Basisname; es entstehen <name>_albedo.png und <name>_normal.png",
|
||||
)
|
||||
bake_resolution: EnumProperty(
|
||||
name="Aufloesung",
|
||||
items=[('512', "512", ""), ('1024', "1024", ""), ('2048', "2048", "")],
|
||||
default='1024',
|
||||
default='1024', # reicht fuer stylized/flaechige Formen
|
||||
)
|
||||
bake_color: BoolProperty(name="BaseColor", default=True)
|
||||
bake_color: BoolProperty(name="Albedo", default=True)
|
||||
bake_normal: BoolProperty(name="Normal", default=True)
|
||||
bake_roughness: BoolProperty(name="Roughness", default=True)
|
||||
bake_ao: BoolProperty(name="AO / Cavity", default=True)
|
||||
bake_roughness: BoolProperty(
|
||||
name="Roughness", default=False,
|
||||
description="In EcoGame ist Roughness eine ZAHL im Master-Material, keine Textur",
|
||||
)
|
||||
bake_ao: BoolProperty(
|
||||
name="AO separat", default=False,
|
||||
description=("Eigene AO-Textur. In EcoGame nicht noetig - dort wird AO ins "
|
||||
"Albedo eingerechnet (siehe unten)"),
|
||||
)
|
||||
bake_ao_into_albedo: BoolProperty(
|
||||
name="AO ins Albedo einrechnen", default=True,
|
||||
description="Cavity/AO multiplikativ ins Farbbild backen (EcoGame-Konvention)",
|
||||
)
|
||||
bake_ao_strength: FloatProperty(
|
||||
name="AO-Staerke", default=1.0, min=0.0, max=1.0,
|
||||
description="0 = kein AO im Albedo, 1 = voll",
|
||||
)
|
||||
bake_base_color: FloatVectorProperty(
|
||||
name="Grundfarbe", subtype='COLOR', size=4,
|
||||
default=(0.52, 0.47, 0.40, 1.0), min=0.0, max=1.0,
|
||||
@@ -796,7 +846,7 @@ class OBJECT_OT_generate_rocks(Operator):
|
||||
for i in range(settings.batch_count):
|
||||
names_before = set(bpy.data.objects.keys())
|
||||
try:
|
||||
created.extend(make_one_rock(context, settings, i))
|
||||
created.extend(make_one_rock(context, settings, i, settings.batch_count))
|
||||
except Exception as exc: # noqa: BLE001 - bewusst breit, ein Rock darf nicht den Batch killen
|
||||
failed.append((i, str(exc)))
|
||||
print("[RockGen] Rock %d fehlgeschlagen: %s" % (i, exc))
|
||||
@@ -839,7 +889,7 @@ class OBJECT_OT_generate_rocks(Operator):
|
||||
|
||||
names_before = set(bpy.data.objects.keys())
|
||||
try:
|
||||
self._created.extend(make_one_rock(context, settings, self._index))
|
||||
self._created.extend(make_one_rock(context, settings, self._index, settings.batch_count))
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self._failed.append((self._index, str(exc)))
|
||||
print("[RockGen] Rock %d fehlgeschlagen: %s" % (self._index, exc))
|
||||
@@ -873,7 +923,9 @@ def _collect_export_targets(context, settings):
|
||||
tops = []
|
||||
for o in context.scene.objects:
|
||||
is_group = (o.type == 'EMPTY' and o.get("fbx_type") == "LodGroup")
|
||||
is_standalone = (o.type == 'MESH' and o.name.startswith("Rock_") and o.parent is None)
|
||||
is_standalone = (o.type == 'MESH' and o.parent is None
|
||||
and (o.name.startswith(settings.name_prefix.strip() or "Fels")
|
||||
or o.name.startswith("Rock_")))
|
||||
if is_group or is_standalone:
|
||||
tops.append(o)
|
||||
if settings.export_selected_only:
|
||||
@@ -1073,6 +1125,19 @@ def _build_bake_material(base_color=(0.52, 0.47, 0.40), cell_scale=2.5):
|
||||
bump.inputs["Distance"].default_value = 0.4
|
||||
links.new(cell_fac.outputs[0], bump.inputs["Height"])
|
||||
|
||||
# EcoGame-Konvention: AO/Cavity wird NICHT als eigene Textur exportiert,
|
||||
# sondern direkt ins Albedo multipliziert - dunkle Ritzen und helle Platten
|
||||
# sind im Farbbild eingebacken. Das traegt den Stylized-Look.
|
||||
ao_mix = nodes.new("ShaderNodeMixRGB")
|
||||
ao_mix.blend_type = 'MULTIPLY'
|
||||
ao_mix.inputs["Fac"].default_value = 1.0
|
||||
links.new(ramp.outputs["Color"], ao_mix.inputs["Color1"])
|
||||
ao_rgb = nodes.new("ShaderNodeCombineXYZ")
|
||||
links.new(ao.outputs[0], ao_rgb.inputs["X"])
|
||||
links.new(ao.outputs[0], ao_rgb.inputs["Y"])
|
||||
links.new(ao.outputs[0], ao_rgb.inputs["Z"])
|
||||
links.new(ao_rgb.outputs[0], ao_mix.inputs["Color2"])
|
||||
|
||||
links.new(ramp.outputs["Color"], bsdf.inputs["Base Color"])
|
||||
links.new(rough.outputs[0], bsdf.inputs["Roughness"])
|
||||
links.new(bump.outputs["Normal"], bsdf.inputs["Normal"])
|
||||
@@ -1081,6 +1146,8 @@ def _build_bake_material(base_color=(0.52, 0.47, 0.40), cell_scale=2.5):
|
||||
sockets = {
|
||||
"out": out, "bsdf": bsdf, "emit": emit,
|
||||
"color": ramp.outputs["Color"],
|
||||
"color_ao": ao_mix.outputs["Color"], # Albedo mit eingebackenem AO
|
||||
"ao_mix": ao_mix,
|
||||
"roughness": rough.outputs[0],
|
||||
"ao": ao.outputs[0],
|
||||
}
|
||||
@@ -1139,6 +1206,10 @@ class OBJECT_OT_bake_rock_textures(Operator):
|
||||
base_color=tuple(settings.bake_base_color),
|
||||
cell_scale=settings.bake_cell_scale,
|
||||
)
|
||||
# AO-Staerke ins Albedo (Fac 0 = aus, 1 = voll)
|
||||
sk["ao_mix"].inputs["Fac"].default_value = (
|
||||
settings.bake_ao_strength if settings.bake_ao_into_albedo else 0.0
|
||||
)
|
||||
plane.data.materials.clear()
|
||||
plane.data.materials.append(mat)
|
||||
|
||||
@@ -1157,7 +1228,7 @@ class OBJECT_OT_bake_rock_textures(Operator):
|
||||
|
||||
if settings.bake_normal:
|
||||
links.new(sk["bsdf"].outputs[0], sk["out"].inputs["Surface"])
|
||||
saved.append(_bake_one(context, mat, img_node, prefix + "_N",
|
||||
saved.append(_bake_one(context, mat, img_node, prefix + "_normal",
|
||||
folder, res, 'NORMAL', non_color=True))
|
||||
|
||||
def _emit_pass(source_socket, suffix, non_color):
|
||||
@@ -1167,11 +1238,14 @@ class OBJECT_OT_bake_rock_textures(Operator):
|
||||
folder, res, 'EMIT', non_color))
|
||||
|
||||
if settings.bake_color:
|
||||
_emit_pass(sk["color"], "_BC", non_color=False)
|
||||
# EcoGame braucht nur _albedo und _normal. Das AO steckt bereits
|
||||
# im Farbbild, sofern "AO ins Albedo einrechnen" aktiv ist.
|
||||
src = sk["color_ao"] if settings.bake_ao_into_albedo else sk["color"]
|
||||
_emit_pass(src, "_albedo", non_color=False)
|
||||
if settings.bake_roughness:
|
||||
_emit_pass(sk["roughness"], "_R", non_color=True)
|
||||
_emit_pass(sk["roughness"], "_roughness", non_color=True)
|
||||
if settings.bake_ao:
|
||||
_emit_pass(sk["ao"], "_AO", non_color=True)
|
||||
_emit_pass(sk["ao"], "_ao", non_color=True)
|
||||
|
||||
except Exception as exc: # noqa: BLE001
|
||||
print("[RockGen] Bake fehlgeschlagen: %s" % exc)
|
||||
@@ -1300,6 +1374,16 @@ class VIEW3D_PT_rock_generator(Panel):
|
||||
row.prop(settings, "new_preset_name", text="")
|
||||
row.operator("rockgen.preset_save", text="Speichern", icon='ADD')
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Benennung", icon='SORTALPHA')
|
||||
row = box.row(align=True)
|
||||
row.prop(settings, "name_prefix", text="")
|
||||
row.prop(settings, "name_form", text="")
|
||||
row.prop(settings, "name_class", text="")
|
||||
box.prop(settings, "name_numbered")
|
||||
box.label(text="Ergebnis: %s" % _asset_name(settings, 0, settings.batch_count),
|
||||
icon='INFO')
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Basis")
|
||||
box.prop(settings, "base_shape")
|
||||
@@ -1397,6 +1481,11 @@ class VIEW3D_PT_rock_generator(Panel):
|
||||
row = box.row(align=True)
|
||||
row.prop(settings, "bake_color", toggle=True)
|
||||
row.prop(settings, "bake_normal", toggle=True)
|
||||
box.prop(settings, "bake_ao_into_albedo")
|
||||
sub = box.row()
|
||||
sub.enabled = settings.bake_ao_into_albedo
|
||||
sub.prop(settings, "bake_ao_strength")
|
||||
row = box.row(align=True)
|
||||
row.prop(settings, "bake_roughness", toggle=True)
|
||||
row.prop(settings, "bake_ao", toggle=True)
|
||||
box.operator("object.bake_rock_textures", icon='TEXTURE')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
bl_info = {
|
||||
"name": "Stylized Tree Generator",
|
||||
"author": "D4rkst3r",
|
||||
"version": (1, 17, 0),
|
||||
"version": (1, 18, 0),
|
||||
"blender": (4, 2, 0),
|
||||
"location": "View3D > Sidebar > Tree Gen",
|
||||
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
|
||||
@@ -964,7 +964,8 @@ def make_object(ng, preset="baum", name=None, growth=None, seed=None):
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
from bpy.props import (
|
||||
IntProperty, FloatProperty, EnumProperty, BoolProperty, PointerProperty,
|
||||
IntProperty, FloatProperty, EnumProperty, BoolProperty, StringProperty,
|
||||
PointerProperty,
|
||||
)
|
||||
from bpy.types import Operator, Panel, PropertyGroup
|
||||
|
||||
@@ -981,18 +982,32 @@ class TreeGenSettings(PropertyGroup):
|
||||
description="Erzeugt mehrere Stufen (Setzling .. ausgewachsen) mit gleichem Seed",
|
||||
)
|
||||
stages: IntProperty(name="Anzahl Stufen", default=4, min=2, max=8)
|
||||
art_name: StringProperty(
|
||||
name="Art", default="",
|
||||
description=("Art-Name fuer den Export, z.B. 'Birke'. Leer = Preset-Name. "
|
||||
"Schema: <Art>_<Variante>_S<Stufe>"),
|
||||
)
|
||||
variant: IntProperty(
|
||||
name="Variante", default=1, min=1, max=99,
|
||||
description="Laufende Variante derselben Art (Birke_01, Birke_02 ...)",
|
||||
)
|
||||
spacing: FloatProperty(name="Abstand", default=4.0, min=0.0, max=20.0)
|
||||
apply_modifier: BoolProperty(
|
||||
name="Modifier anwenden", default=False,
|
||||
description="Ergebnis als normales Mesh einfrieren (fuer den Export)",
|
||||
)
|
||||
generate_lightmap_uv: BoolProperty(
|
||||
name="UV1 Lightmap-UV", default=True,
|
||||
description=("Zweiter, nicht ueberlappender UV-Kanal fuer Unreal-Lightmaps. "
|
||||
"Braucht 'Modifier anwenden' (nur echte Meshes lassen sich unwrappen)"),
|
||||
name="UV1 Lightmap-UV", default=False,
|
||||
description=("Zweiter, nicht ueberlappender UV-Kanal fuer Lightmaps. Braucht "
|
||||
"'Modifier anwenden'. EcoGame beleuchtet dynamisch -> nicht noetig"),
|
||||
)
|
||||
|
||||
|
||||
def _art(s):
|
||||
"""Art-Name fuer das EcoGame-Schema <Art>_<Variante>_S<Stufe>."""
|
||||
return (s.art_name.strip() or s.preset).capitalize()
|
||||
|
||||
|
||||
def _place(ob, x):
|
||||
ob.location.x = x
|
||||
|
||||
@@ -1049,12 +1064,12 @@ class TREEGEN_OT_create(Operator):
|
||||
for i in range(s.stages):
|
||||
t = i / float(s.stages - 1) if s.stages > 1 else 1.0
|
||||
ob = make_object(ng, preset=s.preset, growth=t, seed=s.seed,
|
||||
name="%s_%s_stage%d" % (OBJ_NAME, s.preset, i))
|
||||
name="%s_%02d_S%d" % (_art(s), s.variant, i + 1))
|
||||
_place(ob, x); x += s.spacing
|
||||
created.append(ob)
|
||||
else:
|
||||
ob = make_object(ng, preset=s.preset, seed=s.seed,
|
||||
name="%s_%s" % (OBJ_NAME, s.preset))
|
||||
name="%s_%02d" % (_art(s), s.variant))
|
||||
created.append(ob)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self.report({'ERROR'}, "Erzeugen fehlgeschlagen: %s" % exc)
|
||||
@@ -1099,6 +1114,12 @@ class VIEW3D_PT_tree_generator(Panel):
|
||||
box.label(text="Vorlage", icon='PRESET')
|
||||
box.prop(s, "preset", text="")
|
||||
box.prop(s, "seed")
|
||||
row = box.row(align=True)
|
||||
row.prop(s, "art_name", text="")
|
||||
row.prop(s, "variant")
|
||||
box.label(text="Name: %s_%02d%s" % (_art(s), s.variant,
|
||||
"_S1..S%d" % s.stages if s.use_growth else ""),
|
||||
icon='INFO')
|
||||
|
||||
box = layout.box()
|
||||
box.label(text="Wachstum")
|
||||
|
||||
Reference in New Issue
Block a user