From 788dc2fe9c151838903b767002d9a6f97dbb4d7b Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Fri, 19 Jun 2015 00:14:09 -0700 Subject: [PATCH] Add ViewFaceMods. The ViewFaceMod is presented as a Swivel component, with artist-ready presets for the typical Sprite and Billboard, as well as an advanced 'Custom' option which exposes additional features. --- korman/properties/modifiers/render.py | 87 +++++++++++++++++++++++++++ korman/ui/modifiers/render.py | 23 +++++++ 2 files changed, 110 insertions(+) diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index 0da8adc..b6922d1 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -19,6 +19,8 @@ from bpy.props import * from PyHSPlasma import * from .base import PlasmaModifierProperties +from ...exporter import utils +from ...exporter.explosions import ExportError class PlasmaLightMapGen(PlasmaModifierProperties): pl_id = "lightmap" @@ -86,3 +88,88 @@ class PlasmaLightMapGen(PlasmaModifierProperties): @property def resolution(self): return int(self.quality) + +class PlasmaViewFaceMod(PlasmaModifierProperties): + pl_id = "viewfacemod" + + bl_category = "Render" + bl_label = "Swivel" + bl_description = "Swivel object to face the camera, player, or another object" + + preset_options = EnumProperty(name="Type", + description="Type of Facing", + items=[ + ("Billboard", "Billboard", "Face the camera (Y Axis only)"), + ("Sprite", "Sprite", "Face the camera (All Axis)"), + ("Custom", "Custom", "Custom Swivel"), + ]) + + follow_mode = EnumProperty(name="Target Type", + description="Target of the swivel", + items=[ + ("kFaceCam", "Camera", "Face the camera"), + ("kFaceList", "Listener", "Face listeners"), + ("kFacePlay", "Player", "Face the local player"), + ("kFaceObj", "Object", "Face an object"), + ]) + target_object = StringProperty(name="Target Object", + description="Object to face") + + pivot_on_y = BoolProperty(name="Pivot on local Y", + description="Swivel only around the local Y axis", + default=False) + + offset = BoolProperty(name="Offset", description="Use offset vector", default=False) + offset_local = BoolProperty(name="Local", description="Use local coordinates", default=False) + offset_coord = FloatVectorProperty(name="", subtype="XYZ") + + def created(self, obj): + self.display_name = obj.name + + def export(self, exporter, bo, so): + vfm = exporter.mgr.find_create_object(plViewFaceModifier, so=so, name=self.display_name) + + # Set a default scaling (libHSPlasma will set this to 0 otherwise). + vfm.scale = hsVector3(1,1,1) + l2p = utils.matrix44(bo.matrix_local) + vfm.localToParent = l2p + vfm.parentToLocal = l2p.inverse() + + # Cyan has these as separate components, but they're really just preset + # options for common swivels. We've consolidated them both here, along + # with the fully-customizable swivel as a third option. + if self.preset_options == "Billboard": + vfm.setFlag(plViewFaceModifier.kFaceCam, True) + vfm.setFlag(plViewFaceModifier.kPivotY, True) + elif self.preset_options == "Sprite": + vfm.setFlag(plViewFaceModifier.kFaceCam, True) + vfm.setFlag(plViewFaceModifier.kPivotFace, True) + elif self.preset_options == "Custom": + # For the discerning artist, full control over their swivel options! + vfm.setFlag(getattr(plViewFaceModifier, self.follow_mode), True) + + if self.follow_mode == "kFaceObj": + # If this swivel is following an object, make sure that the + # target has been selected and is a valid SO. + if self.target_object: + target_obj = bpy.data.objects.get(self.target_object, None) + if target_obj is None: + raise ExportError("'{}': Swivel's target object is invalid".format(self.display_name)) + else: + vfm.faceObj = exporter.mgr.find_create_key(plSceneObject, bl=target_obj) + else: + raise ExportError("'{}': Swivel's target object must be selected".format(self.display_name)) + + if self.pivot_on_y: + vfm.setFlag(plViewFaceModifier.kPivotY, True) + else: + vfm.setFlag(plViewFaceModifier.kPivotFace, True) + + if self.offset: + vfm.offset = hsVector3(*self.offset_coord) + if self.offset_local: + vfm.setFlag(plViewFaceModifier.kOffsetLocal, True) + + @property + def requires_actor(self): + return True diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py index 79d53f0..dea3265 100644 --- a/korman/ui/modifiers/render.py +++ b/korman/ui/modifiers/render.py @@ -32,3 +32,26 @@ def lightmap(modifier, layout, context): im_name = "{}_LIGHTMAPGEN.png".format(context.active_object.name) if tex.image.name == im_name: layout.template_preview(tex, show_buttons=False) + +def viewfacemod(modifier, layout, context): + layout.prop(modifier, "preset_options") + + if modifier.preset_options == "Custom": + layout.row().prop(modifier, "follow_mode") + if modifier.follow_mode == "kFaceObj": + layout.prop_search(modifier, "target_object", bpy.data, "objects", icon="OUTLINER_OB_MESH") + layout.separator() + + layout.prop(modifier, "pivot_on_y") + layout.separator() + + split = layout.split() + col = split.column() + col.prop(modifier, "offset") + row = col.row() + row.enabled = modifier.offset + row.prop(modifier, "offset_local") + + col = split.column() + col.enabled = modifier.offset + col.prop(modifier, "offset_coord")