diff --git a/korman/helpers.py b/korman/helpers.py
index a36d138..faaffea 100644
--- a/korman/helpers.py
+++ b/korman/helpers.py
@@ -62,6 +62,14 @@ def ensure_object_can_bake(bo, toggle):
def ensure_power_of_two(value):
return pow(2, math.floor(math.log(value, 2)))
+def find_modifier(boname, modid):
+ """Given a Blender Object name, finds a given modifier and returns it or None"""
+ bo = bpy.data.objects.get(boname, None)
+ if bo is not None:
+ # if they give us the wrong modid, it is a bug and an AttributeError
+ return getattr(bo.plasma_modifiers, modid)
+ return None
+
def make_active_selection(bo):
"""Selects a single Blender Object and makes it active"""
for i in bpy.data.objects:
diff --git a/korman/nodes/node_avatar.py b/korman/nodes/node_avatar.py
index a04c45e..69a552b 100644
--- a/korman/nodes/node_avatar.py
+++ b/korman/nodes/node_avatar.py
@@ -18,6 +18,7 @@ from bpy.props import *
from PyHSPlasma import *
from .node_core import PlasmaNodeBase, PlasmaNodeSocketBase
+from ..properties.modifiers.avatar import sitting_approach_flags
class PlasmaSittingBehaviorNode(PlasmaNodeBase, bpy.types.Node):
bl_category = "AVATAR"
@@ -27,10 +28,7 @@ class PlasmaSittingBehaviorNode(PlasmaNodeBase, bpy.types.Node):
approach = EnumProperty(name="Approach",
description="Directions an avatar can approach the seat from",
- items=[("kApproachFront", "Front", "Approach from the font"),
- ("kApproachLeft", "Left", "Approach from the left"),
- ("kApproachRight", "Right", "Approach from the right"),
- ("kApproachRear", "Rear", "Approach from the rear guard")],
+ items=sitting_approach_flags,
default={"kApproachFront", "kApproachLeft", "kApproachRight"},
options={"ENUM_FLAG"})
diff --git a/korman/properties/modifiers/__init__.py b/korman/properties/modifiers/__init__.py
index 2a1394b..25897be 100644
--- a/korman/properties/modifiers/__init__.py
+++ b/korman/properties/modifiers/__init__.py
@@ -17,6 +17,7 @@ import bpy
import inspect
from .base import PlasmaModifierProperties
+from .avatar import *
from .logic import *
from .physics import *
from .region import *
diff --git a/korman/properties/modifiers/avatar.py b/korman/properties/modifiers/avatar.py
new file mode 100644
index 0000000..a35185d
--- /dev/null
+++ b/korman/properties/modifiers/avatar.py
@@ -0,0 +1,104 @@
+# This file is part of Korman.
+#
+# Korman is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Korman is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Korman. If not, see .
+
+import bpy
+from bpy.props import *
+from PyHSPlasma import *
+
+from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz
+from ...exporter.explosions import ExportError
+from ...helpers import find_modifier
+
+sitting_approach_flags = [("kApproachFront", "Front", "Approach from the font"),
+ ("kApproachLeft", "Left", "Approach from the left"),
+ ("kApproachRight", "Right", "Approach from the right"),
+ ("kApproachRear", "Rear", "Approach from the rear guard")]
+
+class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
+ pl_id = "sittingmod"
+
+ bl_category = "Avatar"
+ bl_label = "Sitting Behavior"
+ bl_description = "Avatar sitting position"
+
+ approach = EnumProperty(name="Approach",
+ description="Directions an avatar can approach the seat from",
+ items=sitting_approach_flags,
+ default={"kApproachFront", "kApproachLeft", "kApproachRight"},
+ options={"ENUM_FLAG"})
+
+ clickable_obj = StringProperty(name="Clickable",
+ description="Object that defines the clickable area")
+ region_obj = StringProperty(name="Region",
+ description="Object that defines the region mesh")
+
+ facing_enabled = BoolProperty(name="Avatar Facing",
+ description="The avatar must be facing the clickable's Y-axis",
+ default=True)
+ facing_degrees = IntProperty(name="Tolerance",
+ description="How far away we will tolerate the avatar facing the clickable",
+ min=-180, max=180, default=45)
+
+ def created(self, obj):
+ self.display_name = "{}_SitBeh".format(obj.name)
+
+ def export(self, exporter, bo, so):
+ # The user absolutely MUST specify a clickable or this won't export worth crap.
+ clickable_obj = bpy.data.objects.get(self.clickable_obj, None)
+ if clickable_obj is None:
+ raise ExportError("'{}': Sitting Behavior's clickable object is invalid")
+
+ # Generate the logic nodes now
+ self.logicwiz(bo)
+
+ # Now, export the node tree
+ self.node_tree.export(exporter, bo, so)
+
+ def logicwiz(self, bo):
+ tree = self.node_tree
+ nodes = tree.nodes
+ nodes.clear()
+
+ # Sitting Modifier
+ sittingmod = nodes.new("PlasmaSittingBehaviorNode")
+ sittingmod.approach = self.approach
+ sittingmod.name = "SittingBeh"
+
+ # Clickable
+ clickable = nodes.new("PlasmaClickableNode")
+ clickable.link_output(tree, sittingmod, "satisfies", "condition")
+ clickable.clickable = self.clickable_obj
+ clickable.bounds = find_modifier(self.clickable_obj, "collision").bounds
+
+ # Avatar Region (optional)
+ region_phys = find_modifier(self.region_obj, "collision")
+ if region_phys is not None:
+ region = nodes.new("PlasmaClickableRegionNode")
+ region.link_output(tree, clickable, "satisfies", "region")
+ region.name = "ClickableAvRegion"
+ region.region = self.region_obj
+ region.bounds = region_phys.bounds
+
+ # Facing Target (optional)
+ if self.facing_enabled:
+ facing = nodes.new("PlasmaFacingTargetNode")
+ facing.link_output(tree, clickable, "satisfies", "facing")
+ facing.name = "FacingClickable"
+ facing.directional = True
+ facing.tolerance = self.facing_degrees
+ else:
+ # this socket must be explicitly disabled, otherwise it automatically generates a default
+ # facing target conditional for us. isn't that nice?
+ clickable.find_input_socket("facing").allow_simple = False
diff --git a/korman/ui/modifiers/__init__.py b/korman/ui/modifiers/__init__.py
index 06220b9..7dcf614 100644
--- a/korman/ui/modifiers/__init__.py
+++ b/korman/ui/modifiers/__init__.py
@@ -13,6 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see .
+from .avatar import *
from .logic import *
from .physics import *
from .region import *
diff --git a/korman/ui/modifiers/avatar.py b/korman/ui/modifiers/avatar.py
new file mode 100644
index 0000000..5e8d010
--- /dev/null
+++ b/korman/ui/modifiers/avatar.py
@@ -0,0 +1,39 @@
+# This file is part of Korman.
+#
+# Korman is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Korman is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Korman. If not, see .
+
+import bpy
+
+from ...helpers import find_modifier
+
+def sittingmod(modifier, layout, context):
+ layout.row().prop(modifier, "approach")
+
+ col = layout.column()
+ col.prop_search(modifier, "clickable_obj", bpy.data, "objects", icon="MESH_DATA")
+ clickable = find_modifier(modifier.clickable_obj, "collision")
+ if clickable is not None:
+ col.prop(clickable, "bounds")
+
+ col = layout.column()
+ col.prop_search(modifier, "region_obj", bpy.data, "objects", icon="MESH_DATA")
+ region = find_modifier(modifier.region_obj, "collision")
+ if region is not None:
+ col.prop(region, "bounds")
+
+ split = layout.split()
+ split.column().prop(modifier, "facing_enabled")
+ col = split.column()
+ col.enabled = modifier.facing_enabled
+ col.prop(modifier, "facing_degrees")