Thanks Olm-Z. That sounds like what I’m aiming for at the moment. It would be good to see your code from 2.49.
Here’s what I’ve created so far:
import bpy
import liblo
class OBJECT_PT_SkelMap(bpy.types.Panel):
bl_label = "Skeleton mapping"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw(self, context):
main_list = bpy.types.Scene.skelmap_main_list
main_vals = bpy.types.Scene.skelmap_main_vals
limb_list = bpy.types.Scene.skelmap_limb_list
limb_vals = bpy.types.Scene.skelmap_limb_vals
layout = self.layout
scn = context.scene
for m in main_list:
row = layout.row()
col = row.column()
col.prop_search( scn, "skelmap_"+m, context.scene, "objects" )
row = layout.row()
for k in ['Left', 'Right']:
col = row.column()
col.label(k)
for l in limb_list:
row = layout.row()
for k in [ 'l', 'r' ]:
col = row.column()
col.prop_search( scn, "skelmap_"+k+"_"+l, context.scene, "objects" )
class DumpOSC:
def callback(self, path, args, types, src):
try:
self.options[path]
except :
i = 0
else :
self.options[path](path, args, types, src)
def new_user_handler(self, path, args, types, src):
print("---")
print("FOUND USER " + str(args[0]))
print("Now perform the Psi pose.")
def new_skeleton_handler(self, path, args, types, src):
print("---")
print("SUCCESS USER " + str(args[0]))
print("You are now being tracked!")
def lost_user_handler(self, path, args, types, src):
print("---")
print("LOST USER " + str(args[0]))
print("where are you?")
def joint_handler(self, path, args, types, src):
sides = ["l", "r"]
jointId = args[0]
userId = str(args[1])
jointLoc = args[2:]
try:
i = bpy.types.Scene.skelmap_main_list.index(jointId)
iList = "main"
except ValueError:
try:
i = bpy.types.Scene.skelmap_limb_list.index(jointId[2:])
iList = "limb"
except ValueError:
pass
vals = getattr(bpy.types.Scene, "skelmap_"+iList+"_vals")
if iList == "limb":
vals[sides.index(jointId[0:1])][i] = jointLoc
else:
vals[i] = jointLoc
try:
setattr(bpy.types.Scene, "skelmap_"+iList+"_vals", vals)
except:
pass
try:
objName = getattr(bpy.context.scene, "skelmap_"+jointId)
obj = bge.logic.getCurrentScene().objects[objName]
obj.worldPosition = jointLoc
except:
pass
def create_server(self, port = None):
liblo.Server(port).free()
self.server = liblo.Server(port)
# register callback function for all messages
self.server.add_method(None, None, self.callback)
print("listening on URL: " + self.server.get_url())
def __init__(self, port = None):
self.options = { '/new_user' : self.new_user_handler,
'/lost_user' : self.lost_user_handler,
'/new_skeleton' : self.new_skeleton_handler,
'/joint' : self.joint_handler }
# create server object
try:
self.create_server(port)
except:
pass
def run(self):
self.server.recv(33)
if __name__ == '__main__':
try:
bpy.types.Scene.skelmap_app
except:
# Create OSC listener
bpy.types.Scene.skelmap_app = DumpOSC(7110)
try:
bpy.types.Scene.skelmap_app.run()
except:
del bpy.types.Scene.skelmap_app
pass
# Create joint lists and value dicts
# Main joints first
main_list = [ "head", "neck", "torso" ]
main_vals = {}
# Followed by joint pairs
limb_list = [ "shoulder", "elbow", "hand", "hip", "knee", "ankle", "foot" ]
limb_vals = [ {}, {} ]
# Save lists to scene
bpy.types.Scene.skelmap_main_list = main_list
bpy.types.Scene.skelmap_main_vals = main_vals
bpy.types.Scene.skelmap_limb_list = limb_list
bpy.types.Scene.skelmap_limb_vals = limb_vals
# Create UI fields for each joint: eg. skelmap_l_shoulder
for m in main_list:
setattr(bpy.types.Scene, "skelmap_"+m, bpy.props.StringProperty( name = m.title(), description = "Send location value to object" ))
for l in limb_list:
for k in [ 'l', 'r' ]:
setattr(bpy.types.Scene, "skelmap_"+k+"_"+l, bpy.props.StringProperty( name = l.title(), description = "Send location value to object" ))
# Create UI fields for other options
Here’s what happens at the moment:
- The script creates a panel with fields for the user to link an object with an OSC joint type.
- When DumpOSC.run()s, it receives an OSC message and runs the callback function related to the message type (joint_handler if a ‘/joint’ message is received).
- The joint_handler puts the joint vector into a global array AND
- The joint_handler updates the linked object’s world position.
At the moment, the global value arrays are being updated with each run(), but I’m getting no changes of position for any of the objects in the game engine.
Maybe this script could be added to an Empty in the scene as a single-run controller script, then another controller script could repeatedly run the run() function (which I think is probably what you suggested)?
This is only my second Python project, so I’m still finding my feet with this fantastic language (and the Blender 2.5 python API), so changes/streamlining/suggestions etc, are greatly appreciated. 