Browse Source

Update Avatar Modifiers and Condition Nodes

pull/56/head
Adam Johnson 8 years ago
parent
commit
1fe8ecc02d
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 6
      korman/helpers.py
  2. 68
      korman/nodes/node_conditions.py
  3. 33
      korman/properties/modifiers/avatar.py
  4. 2
      korman/properties/modifiers/region.py
  5. 8
      korman/ui/modifiers/avatar.py

6
korman/helpers.py

@ -51,9 +51,9 @@ class TemporaryObject:
def ensure_power_of_two(value): def ensure_power_of_two(value):
return pow(2, math.floor(math.log(value, 2))) 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""" def find_modifier(bo, modid):
bo = bpy.data.objects.get(boname, None) """Given a Blender Object, finds a given modifier and returns it or None"""
if bo is not None: if bo is not None:
# if they give us the wrong modid, it is a bug and an AttributeError # if they give us the wrong modid, it is a bug and an AttributeError
return getattr(bo.plasma_modifiers, modid) return getattr(bo.plasma_modifiers, modid)

68
korman/nodes/node_conditions.py

@ -21,8 +21,9 @@ from PyHSPlasma import *
from .node_core import * from .node_core import *
from ..properties.modifiers.physics import bounds_types from ..properties.modifiers.physics import bounds_types
from .. import idprops
class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node): class PlasmaClickableNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node):
bl_category = "CONDITIONS" bl_category = "CONDITIONS"
bl_idname = "PlasmaClickableNode" bl_idname = "PlasmaClickableNode"
bl_label = "Clickable" bl_label = "Clickable"
@ -31,8 +32,10 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node):
# These are the Python attributes we can fill in # These are the Python attributes we can fill in
pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"} pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"}
clickable = StringProperty(name="Clickable", clickable_object = PointerProperty(name="Clickable",
description="Mesh that is clickable") description="Mesh object that is clickable",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds", bounds = EnumProperty(name="Bounds",
description="Clickable's bounds (NOTE: only used if your clickable is not a collider)", description="Clickable's bounds (NOTE: only used if your clickable is not a collider)",
items=bounds_types, items=bounds_types,
@ -63,7 +66,7 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node):
]) ])
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.prop_search(self, "clickable", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "clickable_object", icon="MESH_DATA")
layout.prop(self, "bounds") layout.prop(self, "bounds")
def export(self, exporter, parent_bo, parent_so): def export(self, exporter, parent_bo, parent_so):
@ -127,27 +130,31 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node):
# First: look up the clickable mesh. if it is not specified, then it's this BO. # First: look up the clickable mesh. if it is not specified, then it's this BO.
# We do this because we might be exporting from a BO that is not actually the clickable object. # We do this because we might be exporting from a BO that is not actually the clickable object.
# Case: sitting modifier (exports from sit position empty) # Case: sitting modifier (exports from sit position empty)
if self.clickable: if self.clickable_object:
clickable_bo = bpy.data.objects.get(self.clickable, None) clickable_so = exporter.mgr.find_create_object(plSceneObject, bl=self.clickable_object)
if clickable_bo is None: return (self.clickable_object, clickable_so)
self.raise_error("invalid Clickable object: '{}'".format(self.clickable))
clickable_so = exporter.mgr.find_create_object(plSceneObject, bl=clickable_bo)
return (clickable_bo, clickable_so)
else: else:
return (None, parent_so) return (None, parent_so)
def harvest_actors(self): def harvest_actors(self):
return (self.clickable,) if self.clickable_object:
return (self.clickable_object.name,)
@classmethod
def _idprop_mapping(cls):
return {"clickable_object": "clickable"}
class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node):
class PlasmaClickableRegionNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node):
bl_category = "CONDITIONS" bl_category = "CONDITIONS"
bl_idname = "PlasmaClickableRegionNode" bl_idname = "PlasmaClickableRegionNode"
bl_label = "Clickable Region Settings" bl_label = "Clickable Region Settings"
bl_width_default = 200 bl_width_default = 200
region = StringProperty(name="Region", region_object = PointerProperty(name="Region",
description="Object that defines the region mesh") description="Object that defines the region mesh",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds", bounds = EnumProperty(name="Bounds",
description="Physical object's bounds (NOTE: only used if your clickable is not a collider)", description="Physical object's bounds (NOTE: only used if your clickable is not a collider)",
items=bounds_types, items=bounds_types,
@ -161,14 +168,14 @@ class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node):
]) ])
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.prop_search(self, "region", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "region_object", icon="MESH_DATA")
layout.prop(self, "bounds") layout.prop(self, "bounds")
def convert_subcondition(self, exporter, parent_bo, parent_so, logicmod): def convert_subcondition(self, exporter, parent_bo, parent_so, logicmod):
# REMEMBER: parent_so doesn't have to be the actual region scene object... # REMEMBER: parent_so doesn't have to be the actual region scene object...
region_bo = bpy.data.objects.get(self.region, None) region_bo = self.region_object
if region_bo is None: if region_bo is None:
self.raise_error("invalid Region object: '{}'".format(self.region)) self.raise_error("invalid Region")
region_so = exporter.mgr.find_create_key(plSceneObject, bl=region_bo).object region_so = exporter.mgr.find_create_key(plSceneObject, bl=region_bo).object
# Try to figure out the appropriate bounds type for the region.... # Try to figure out the appropriate bounds type for the region....
@ -198,6 +205,10 @@ class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node):
objinbox_key.object.satisfied = True objinbox_key.object.satisfied = True
logicmod.addCondition(objinbox_key) logicmod.addCondition(objinbox_key)
@classmethod
def _idprop_mapping(cls):
return {"region_object": "region"}
class PlasmaClickableRegionSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket): class PlasmaClickableRegionSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket):
bl_color = (0.412, 0.0, 0.055, 1.0) bl_color = (0.412, 0.0, 0.055, 1.0)
@ -310,7 +321,7 @@ class PlasmaVolumeReportNode(PlasmaNodeBase, bpy.types.Node):
row.prop(self, "threshold", text="") row.prop(self, "threshold", text="")
class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node): class PlasmaVolumeSensorNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node):
bl_category = "CONDITIONS" bl_category = "CONDITIONS"
bl_idname = "PlasmaVolumeSensorNode" bl_idname = "PlasmaVolumeSensorNode"
bl_label = "Region Sensor" bl_label = "Region Sensor"
@ -320,8 +331,10 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"} pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"}
# Region Mesh # Region Mesh
region = StringProperty(name="Region", region_object = PointerProperty(name="Region",
description="Object that defines the region mesh") description="Object that defines the region mesh",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds", bounds = EnumProperty(name="Bounds",
description="Physical object's bounds", description="Physical object's bounds",
items=bounds_types) items=bounds_types)
@ -364,11 +377,13 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
layout.prop(self, "report_on") layout.prop(self, "report_on")
# Okay, if they changed the name of the ObData, that's THEIR problem... # Okay, if they changed the name of the ObData, that's THEIR problem...
layout.prop_search(self, "region", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "region_object", icon="MESH_DATA")
layout.prop(self, "bounds") layout.prop(self, "bounds")
def get_key(self, exporter, parent_so): def get_key(self, exporter, parent_so):
bo = self.region_object bo = self.region_object
if bo is None:
self.raise_error("Region cannot be empty")
so = exporter.mgr.find_create_object(plSceneObject, bl=bo) so = exporter.mgr.find_create_object(plSceneObject, bl=bo)
rgn_enter, rgn_exit = None, None rgn_enter, rgn_exit = None, None
@ -393,6 +408,8 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
def export(self, exporter, bo, parent_so): def export(self, exporter, bo, parent_so):
# We need to ensure we export to the correct SO # We need to ensure we export to the correct SO
region_bo = self.region_object region_bo = self.region_object
if region_bo is None:
self.raise_error("Region cannot be empty")
region_so = exporter.mgr.find_create_object(plSceneObject, bl=region_bo) region_so = exporter.mgr.find_create_object(plSceneObject, bl=region_bo)
interface = exporter.mgr.find_create_object(plInterfaceInfoModifier, name=self.key_name, so=region_so) interface = exporter.mgr.find_create_object(plInterfaceInfoModifier, name=self.key_name, so=region_so)
@ -457,12 +474,9 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
logicmod.addCondition(volKey) logicmod.addCondition(volKey)
return logicKey return logicKey
@property @classmethod
def region_object(self): def _idprop_mapping(cls):
phys_bo = bpy.data.objects.get(self.region, None) return {"region_object": "region"}
if phys_bo is None:
self.raise_error("invalid Region object: '{}'".format(self.region))
return phys_bo
@property @property
def report_enters(self): def report_enters(self):

33
korman/properties/modifiers/avatar.py

@ -20,13 +20,14 @@ from PyHSPlasma import *
from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz
from ...exporter.explosions import ExportError from ...exporter.explosions import ExportError
from ...helpers import find_modifier from ...helpers import find_modifier
from ... import idprops
sitting_approach_flags = [("kApproachFront", "Front", "Approach from the font"), sitting_approach_flags = [("kApproachFront", "Front", "Approach from the font"),
("kApproachLeft", "Left", "Approach from the left"), ("kApproachLeft", "Left", "Approach from the left"),
("kApproachRight", "Right", "Approach from the right"), ("kApproachRight", "Right", "Approach from the right"),
("kApproachRear", "Rear", "Approach from the rear guard")] ("kApproachRear", "Rear", "Approach from the rear guard")]
class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz): class PlasmaSittingBehavior(idprops.IDPropObjectMixin, PlasmaModifierProperties, PlasmaModifierLogicWiz):
pl_id = "sittingmod" pl_id = "sittingmod"
bl_category = "Avatar" bl_category = "Avatar"
@ -39,10 +40,14 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
default={"kApproachFront", "kApproachLeft", "kApproachRight"}, default={"kApproachFront", "kApproachLeft", "kApproachRight"},
options={"ENUM_FLAG"}) options={"ENUM_FLAG"})
clickable_obj = StringProperty(name="Clickable", clickable_object = PointerProperty(name="Clickable",
description="Object that defines the clickable area") description="Object that defines the clickable area",
region_obj = StringProperty(name="Region", type=bpy.types.Object,
description="Object that defines the region mesh") poll=idprops.poll_mesh_objects)
region_object = PointerProperty(name="Region",
description="Object that defines the region mesh",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
facing_enabled = BoolProperty(name="Avatar Facing", facing_enabled = BoolProperty(name="Avatar Facing",
description="The avatar must be facing the clickable's Y-axis", description="The avatar must be facing the clickable's Y-axis",
@ -53,8 +58,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
def export(self, exporter, bo, so): def export(self, exporter, bo, so):
# The user absolutely MUST specify a clickable or this won't export worth crap. # 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 self.clickable_object is None:
if clickable_obj is None:
raise ExportError("'{}': Sitting Behavior's clickable object is invalid".format(self.key_name)) raise ExportError("'{}': Sitting Behavior's clickable object is invalid".format(self.key_name))
# Generate the logic nodes now # Generate the logic nodes now
@ -65,7 +69,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
def harvest_actors(self): def harvest_actors(self):
if self.facing_enabled: if self.facing_enabled:
return (self.clickable_obj,) return (self.clickable_object.name,)
return () return ()
def logicwiz(self, bo): def logicwiz(self, bo):
@ -81,16 +85,16 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# Clickable # Clickable
clickable = nodes.new("PlasmaClickableNode") clickable = nodes.new("PlasmaClickableNode")
clickable.link_output(sittingmod, "satisfies", "condition") clickable.link_output(sittingmod, "satisfies", "condition")
clickable.clickable = self.clickable_obj clickable.clickable_object = self.clickable_object
clickable.bounds = find_modifier(self.clickable_obj, "collision").bounds clickable.bounds = find_modifier(self.clickable_object, "collision").bounds
# Avatar Region (optional) # Avatar Region (optional)
region_phys = find_modifier(self.region_obj, "collision") region_phys = find_modifier(self.region_object, "collision")
if region_phys is not None: if region_phys is not None:
region = nodes.new("PlasmaClickableRegionNode") region = nodes.new("PlasmaClickableRegionNode")
region.link_output(clickable, "satisfies", "region") region.link_output(clickable, "satisfies", "region")
region.name = "ClickableAvRegion" region.name = "ClickableAvRegion"
region.region = self.region_obj region.region_object = self.region_object
region.bounds = region_phys.bounds region.bounds = region_phys.bounds
# Facing Target (optional) # Facing Target (optional)
@ -105,6 +109,11 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# facing target conditional for us. isn't that nice? # facing target conditional for us. isn't that nice?
clickable.find_input_socket("facing").allow_simple = False clickable.find_input_socket("facing").allow_simple = False
@classmethod
def _idprop_mapping(cls):
return {"clickable_object": "clickable_obj",
"region_object": "region_obj"}
@property @property
def key_name(self): def key_name(self):
return "{}_SitBeh".format(self.id_data.name) return "{}_SitBeh".format(self.id_data.name)

2
korman/properties/modifiers/region.py

@ -88,7 +88,7 @@ class PlasmaFootstepRegion(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# Region Sensor # Region Sensor
volsens = nodes.new("PlasmaVolumeSensorNode") volsens = nodes.new("PlasmaVolumeSensorNode")
volsens.name = "RegionSensor" volsens.name = "RegionSensor"
volsens.region = bo.name volsens.region_object = bo
volsens.bounds = self.bounds volsens.bounds = self.bounds
volsens.find_input_socket("enter").allow = True volsens.find_input_socket("enter").allow = True
volsens.find_input_socket("exit").allow = True volsens.find_input_socket("exit").allow = True

8
korman/ui/modifiers/avatar.py

@ -21,14 +21,14 @@ def sittingmod(modifier, layout, context):
layout.row().prop(modifier, "approach") layout.row().prop(modifier, "approach")
col = layout.column() col = layout.column()
col.prop_search(modifier, "clickable_obj", bpy.data, "objects", icon="MESH_DATA") col.prop(modifier, "clickable_object", icon="MESH_DATA")
clickable = find_modifier(modifier.clickable_obj, "collision") clickable = find_modifier(modifier.clickable_object, "collision")
if clickable is not None: if clickable is not None:
col.prop(clickable, "bounds") col.prop(clickable, "bounds")
col = layout.column() col = layout.column()
col.prop_search(modifier, "region_obj", bpy.data, "objects", icon="MESH_DATA") col.prop(modifier, "region_object", icon="MESH_DATA")
region = find_modifier(modifier.region_obj, "collision") region = find_modifier(modifier.region_object, "collision")
if region is not None: if region is not None:
col.prop(region, "bounds") col.prop(region, "bounds")

Loading…
Cancel
Save