diff --git a/korman/exporter/material.py b/korman/exporter/material.py index d189a5e..997bbc1 100644 --- a/korman/exporter/material.py +++ b/korman/exporter/material.py @@ -19,7 +19,7 @@ import math import mathutils from pathlib import Path from PyHSPlasma import * -from typing import Union +from typing import Sequence, Union import weakref from .explosions import * @@ -1183,7 +1183,7 @@ class MaterialConverter: data[i] = level_data return numLevels, eWidth, eHeight, [data,] - def get_materials(self, bo): + def get_materials(self, bo) -> Sequence[plKey]: return self._obj2mat.get(bo, []) def get_base_layer(self, hsgmat): diff --git a/korman/nodes/node_python.py b/korman/nodes/node_python.py index c758b3e..9ece289 100644 --- a/korman/nodes/node_python.py +++ b/korman/nodes/node_python.py @@ -283,7 +283,7 @@ class PlasmaPythonFileNode(PlasmaVersionedNode, bpy.types.Node): from_node = socket.links[0].from_node value = from_node.value if socket.is_simple_value else from_node.get_key(exporter, so) - if not isinstance(value, tuple): + if not isinstance(value, (tuple, list)): value = (value,) for i in value: param = plPythonParameter() @@ -723,7 +723,7 @@ class PlasmaAttribObjectNode(idprops.IDPropObjectMixin, PlasmaAttribNodeBase, bp bl_label = "Object Attribute" pl_attrib = ("ptAttribSceneobject", "ptAttribSceneobjectList", "ptAttribAnimation", - "ptAttribSwimCurrent", "ptAttribWaveSet") + "ptAttribSwimCurrent", "ptAttribWaveSet", "ptAttribGrassShader") target_object = PointerProperty(name="Object", description="Object containing the required data", @@ -765,6 +765,15 @@ class PlasmaAttribObjectNode(idprops.IDPropObjectMixin, PlasmaAttribNodeBase, bp if not waveset.enabled: self.raise_error("water modifier not enabled on '{}'".format(self.object_name)) return exporter.mgr.find_create_key(plWaveSet7, so=ref_so, bl=bo) + elif attrib == "ptAttribGrassShader": + grass_shader = bo.plasma_modifiers.grass_shader + if not grass_shader.enabled: + self.raise_error("grass shader modifier not enabled on '{}'".format(self.object_name)) + if exporter.mgr.getVer() <= pvPots: + return None + return [exporter.mgr.find_create_key(plGrassShaderMod, so=ref_so, name=i.name) + for i in exporter.mesh.material.get_materials(bo)] + @classmethod def _idprop_mapping(cls): diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index 3683039..1b7eea8 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -321,6 +321,75 @@ class PlasmaFollowMod(idprops.IDPropObjectMixin, PlasmaModifierProperties): return True +class PlasmaGrassWave(bpy.types.PropertyGroup): + distance = FloatVectorProperty(name="Distance", + size=3, + default=(0.2, 0.2, 0.1), + subtype="XYZ", + unit="LENGTH", + options=set()) + direction = FloatVectorProperty(name="Direction", + size=2, + default=(0.2, 0.05), + soft_min=0.0, soft_max=1.0, + unit="LENGTH", + subtype="XYZ", + options=set()) + speed = FloatProperty(name="Speed", + default=0.1, + unit="VELOCITY", + options=set()) + + +class PlasmaGrassShaderMod(PlasmaModifierProperties): + pl_id = "grass_shader" + + bl_category = "Render" + bl_label = "Grass Shader" + bl_description = "Applies waving grass effect at run-time" + + wave1 = PointerProperty(type=PlasmaGrassWave) + wave2 = PointerProperty(type=PlasmaGrassWave) + wave3 = PointerProperty(type=PlasmaGrassWave) + wave4 = PointerProperty(type=PlasmaGrassWave) + + # UI Accessor + wave_selector = EnumProperty(items=[("wave1", "Wave 1", ""), + ("wave2", "Wave 2", ""), + ("wave3", "Wave 3", ""), + ("wave4", "Wave 4", "")], + name="Waves", + options=set()) + + @property + def copy_material(self): + return True + + def export(self, exporter, bo, so): + if exporter.mgr.getVer() <= pvPots: + exporter.report.warning("Not supported on this version of Plasma", indent=3) + return + else: + exporter.report.port("This will only function on MOUL and EOA", indent=3) + + materials = exporter.mesh.material.get_materials(bo) + if not materials: + exporter.report.warning("No materials are associated with this object, no grass shader exported!", + indent=3) + return + elif len(materials) > 1: + exporter.report.warning("Ah, a multiple material grass shader, eh. You like living dangerously...", + indent=3) + + for material in materials: + mod = exporter.mgr.find_create_object(plGrassShaderMod, so=so, name=material.name) + mod.material = material + for mod_wave, settings in zip(mod.waves, (self.wave1, self.wave2, self.wave3, self.wave4)): + mod_wave.dist = hsVector3(*settings.distance) + mod_wave.dirX, mod_wave.dirY = settings.direction + mod_wave.speed = settings.speed + + class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties, PlasmaModifierUpgradable): pl_id = "lightmap" diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py index 7c6dfa6..6df9fe7 100644 --- a/korman/ui/modifiers/render.py +++ b/korman/ui/modifiers/render.py @@ -127,6 +127,21 @@ def followmod(modifier, layout, context): if modifier.leader_type == "kFollowObject": layout.prop(modifier, "leader", icon="OUTLINER_OB_MESH") +def grass_shader(modifier, layout, context): + layout.prop(modifier, "wave_selector", icon="SMOOTHCURVE") + layout.separator() + + wave = getattr(modifier, modifier.wave_selector) + box = layout.box() + split = box.split() + col = split.column() + col.label("Distortion:") + col.prop(wave, "distance", text="") + col = split.column() + col.label("Direction:") + col.prop(wave, "direction", text="") + box.prop(wave, "speed") + def lighting(modifier, layout, context): split = layout.split() col = split.column()