extends RefCounted ## Materialien für den Low-Poly-Look: eine flache Farbe, matt, kein Muster, ## kein Relief. Was "Holz" von "Filz" unterscheidet, ist die Farbe und die ## Form - nicht eine Textur. Die Palette ist pastellig und satt, wie Knete. ## Kein class_name: den Klassencache baut nur der Editor, headless fehlt er. const FARBEN := { "filz": Color(0.33, 0.70, 0.42), "filz_dunkel": Color(0.26, 0.60, 0.36), "holz": Color(0.86, 0.68, 0.46), "holz_dunkel": Color(0.76, 0.42, 0.30), "holz_rand": Color(0.60, 0.40, 0.26), "messing": Color(0.96, 0.80, 0.36), "knochen": Color(0.99, 0.96, 0.90), "boden": Color(0.90, 0.84, 0.72), "glas": Color(1.0, 0.92, 0.55), } static var _fertig: Dictionary = {} ## Ein Stoff, eine Instanz: gleiche Farbe teilt das Material. static func mach(name: String) -> StandardMaterial3D: if _fertig.has(name): return _fertig[name] var m := StandardMaterial3D.new() m.albedo_color = FARBEN[name] m.roughness = 0.85 m.metallic = 0.0 # Fast kein Glanzpunkt: Knete glänzt nicht, sie leuchtet vom Licht her. m.metallic_specular = 0.15 _fertig[name] = m return m static func eigene(name: String) -> StandardMaterial3D: return mach(name).duplicate() static func filz() -> StandardMaterial3D: return mach("filz") static func filz_dunkel() -> StandardMaterial3D: return mach("filz_dunkel") static func holz() -> StandardMaterial3D: return mach("holz") static func holz_dunkel() -> StandardMaterial3D: return mach("holz_dunkel") static func boden() -> StandardMaterial3D: return mach("boden") static func messing(emission := 0.0) -> StandardMaterial3D: if emission <= 0.0: return mach("messing") var m := eigene("messing") m.emission_enabled = true m.emission = Color(1.0, 0.80, 0.35) m.emission_energy_multiplier = emission return m ## Würfel: Farbe kommt aus den Vertexfarben (Körper hell, Augen dunkel). static func knochen() -> StandardMaterial3D: if _fertig.has("knochen"): return _fertig["knochen"] var m := StandardMaterial3D.new() m.vertex_color_use_as_albedo = true m.roughness = 0.8 m.metallic_specular = 0.15 _fertig["knochen"] = m return m ## Zonenrand: dunkleres Holz als die Becher, damit sich beides trennt; kann ## leuchten, wenn der Platz dran ist. static func rand() -> StandardMaterial3D: var m := eigene("holz_rand") m.emission = Color(1.0, 0.78, 0.30) m.emission_enabled = false return m