Browse Source

Update Avatar Modifiers and Condition Nodes

pull/56/head
Adam Johnson 7 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):
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)
def find_modifier(bo, modid):
"""Given a Blender Object, finds a given modifier and returns it or 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)

68
korman/nodes/node_conditions.py

@ -21,8 +21,9 @@ from PyHSPlasma import *
from .node_core import *
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_idname = "PlasmaClickableNode"
bl_label = "Clickable"
@ -31,8 +32,10 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node):
# These are the Python attributes we can fill in
pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"}
clickable = StringProperty(name="Clickable",
description="Mesh that is clickable")
clickable_object = PointerProperty(name="Clickable",
description="Mesh object that is clickable",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds",
description="Clickable's bounds (NOTE: only used if your clickable is not a collider)",
items=bounds_types,
@ -63,7 +66,7 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node):
])
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")
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.
# 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)
if self.clickable:
clickable_bo = bpy.data.objects.get(self.clickable, None)
if clickable_bo is None:
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)
if self.clickable_object:
clickable_so = exporter.mgr.find_create_object(plSceneObject, bl=self.clickable_object)
return (self.clickable_object, clickable_so)
else:
return (None, parent_so)
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_idname = "PlasmaClickableRegionNode"
bl_label = "Clickable Region Settings"
bl_width_default = 200
region = StringProperty(name="Region",
description="Object that defines the region mesh")
region_object = PointerProperty(name="Region",
description="Object that defines the region mesh",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds",
description="Physical object's bounds (NOTE: only used if your clickable is not a collider)",
items=bounds_types,
@ -161,14 +168,14 @@ class PlasmaClickableRegionNode(PlasmaNodeBase, bpy.types.Node):
])
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")
def convert_subcondition(self, exporter, parent_bo, parent_so, logicmod):
# 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:
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
# 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
logicmod.addCondition(objinbox_key)
@classmethod
def _idprop_mapping(cls):
return {"region_object": "region"}
class PlasmaClickableRegionSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket):
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="")
class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
class PlasmaVolumeSensorNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node):
bl_category = "CONDITIONS"
bl_idname = "PlasmaVolumeSensorNode"
bl_label = "Region Sensor"
@ -320,8 +331,10 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
pl_attrib = {"ptAttribActivator", "ptAttribActivatorList", "ptAttribNamedActivator"}
# Region Mesh
region = StringProperty(name="Region",
description="Object that defines the region mesh")
region_object = PointerProperty(name="Region",
description="Object that defines the region mesh",
type=bpy.types.Object,
poll=idprops.poll_mesh_objects)
bounds = EnumProperty(name="Bounds",
description="Physical object's bounds",
items=bounds_types)
@ -364,11 +377,13 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
layout.prop(self, "report_on")
# 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")
def get_key(self, exporter, parent_so):
bo = self.region_object
if bo is None:
self.raise_error("Region cannot be empty")
so = exporter.mgr.find_create_object(plSceneObject, bl=bo)
rgn_enter, rgn_exit = None, None
@ -393,6 +408,8 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node):
def export(self, exporter, bo, parent_so):
# We need to ensure we export to the correct SO
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)
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)
return logicKey
@property
def region_object(self):
phys_bo = bpy.data.objects.get(self.region, None)
if phys_bo is None:
self.raise_error("invalid Region object: '{}'".format(self.region))
return phys_bo
@classmethod
def _idprop_mapping(cls):
return {"region_object": "region"}
@property
def report_enters(self):

33
korman/properties/modifiers/avatar.py

@ -20,13 +20,14 @@ from PyHSPlasma import *
from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz
from ...exporter.explosions import ExportError
from ...helpers import find_modifier
from ... import idprops
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):
class PlasmaSittingBehavior(idprops.IDPropObjectMixin, PlasmaModifierProperties, PlasmaModifierLogicWiz):
pl_id = "sittingmod"
bl_category = "Avatar"
@ -39,10 +40,14 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
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")
clickable_object = PointerProperty(name="Clickable",
description="Object that defines the clickable area",
type=bpy.types.Object,
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",
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):
# 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:
if self.clickable_object is None:
raise ExportError("'{}': Sitting Behavior's clickable object is invalid".format(self.key_name))
# Generate the logic nodes now
@ -65,7 +69,7 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
def harvest_actors(self):
if self.facing_enabled:
return (self.clickable_obj,)
return (self.clickable_object.name,)
return ()
def logicwiz(self, bo):
@ -81,16 +85,16 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# Clickable
clickable = nodes.new("PlasmaClickableNode")
clickable.link_output(sittingmod, "satisfies", "condition")
clickable.clickable = self.clickable_obj
clickable.bounds = find_modifier(self.clickable_obj, "collision").bounds
clickable.clickable_object = self.clickable_object
clickable.bounds = find_modifier(self.clickable_object, "collision").bounds
# 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:
region = nodes.new("PlasmaClickableRegionNode")
region.link_output(clickable, "satisfies", "region")
region.name = "ClickableAvRegion"
region.region = self.region_obj
region.region_object = self.region_object
region.bounds = region_phys.bounds
# Facing Target (optional)
@ -105,6 +109,11 @@ class PlasmaSittingBehavior(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# facing target conditional for us. isn't that nice?
clickable.find_input_socket("facing").allow_simple = False
@classmethod
def _idprop_mapping(cls):
return {"clickable_object": "clickable_obj",
"region_object": "region_obj"}
@property
def key_name(self):
return "{}_SitBeh".format(self.id_data.name)

2
korman/properties/modifiers/region.py

@ -88,7 +88,7 @@ class PlasmaFootstepRegion(PlasmaModifierProperties, PlasmaModifierLogicWiz):
# Region Sensor
volsens = nodes.new("PlasmaVolumeSensorNode")
volsens.name = "RegionSensor"
volsens.region = bo.name
volsens.region_object = bo
volsens.bounds = self.bounds
volsens.find_input_socket("enter").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")
col = layout.column()
col.prop_search(modifier, "clickable_obj", bpy.data, "objects", icon="MESH_DATA")
clickable = find_modifier(modifier.clickable_obj, "collision")
col.prop(modifier, "clickable_object", icon="MESH_DATA")
clickable = find_modifier(modifier.clickable_object, "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")
col.prop(modifier, "region_object", icon="MESH_DATA")
region = find_modifier(modifier.region_object, "collision")
if region is not None:
col.prop(region, "bounds")

Loading…
Cancel
Save