Commit 3f310a7b authored by Bruno Laurencich's avatar Bruno Laurencich

send root Z

parent 5142ad33
......@@ -45,6 +45,27 @@ class Error(Exception):
def __init__(self, msg):
self.msg = msg
def find_root_bone(bones):
root = None
for b in bones:
if not b.parent:
if root:
raise Error("more than one Root bone found.")
root = b
if root:
return root
raise Error("No Root bone found.")
def find_lowest_bone(bones):
lowest = 0
for b in bones:
lowest = min(lowest, b.matrix_local.to_translation().z)
return lowest
class Armature_Handler:
#TODO: create a global control for the visualization handling (hiding helpers or mesh)
def __init__(self, armature_object, helpers):
......@@ -58,7 +79,16 @@ class Armature_Handler:
self.pose = self.object.pose.bones
self.bones = self.object.data.bones
self.arm_repr = {}
#Find the data.(root_bone), and extract the starting local location
self.root_bone = find_root_bone(self.bones)
self.root_starting_loc = self.root_bone.matrix_local.to_translation()
#Find the lowest starting bone, and the relative height of the root at startup
self.lowest_starting_z = find_lowest_bone(self.bones)
self.relative_root_height = self.root_starting_loc.z - self.lowest_starting_z
#Keep the pose.(root_bone) for later use
self.root_bone = self.pose[self.root_bone.name]
print("Root bone: {} | starting location: {}".format(self.root_bone.name, self.root_starting_loc))
print("Bones found in armature")
for b in self.bones:
if not b.capture_bone:
......@@ -85,6 +115,8 @@ class Armature_Handler:
self.message = " Chordata operator | Calibrating... Press ENTER to start posing "
def __del__(self):
for m in self.meshes: m.hide = False
......
......@@ -152,7 +152,7 @@ class Chord_Receive_OSC(bpy.types.Operator):
if event.type == 'TIMER':
osc_process()
self.set_keyframe()
send.send_Armature(self.armature.object, self.chord_global.send)
send.send_Armature(self.armature, self.chord_global.send)
return {'PASS_THROUGH'}
......@@ -195,6 +195,7 @@ class Chord_Receive_OSC(bpy.types.Operator):
chord_scene = context.scene.chordata
self.armature = arm.Armature_Handler(chord_scene.target, chord_scene.helpers)
self.prepare_armature()
self.chord_global = context.user_preferences.addons[__package__].preferences
......
......@@ -189,7 +189,7 @@ def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i + n]
def send_Armature(arm, options):
def send_Armature(arm_m, options):
#TODO: this works, but the implementation could be much more elegant.. (and performative)
global INIT
if not INIT: return
......@@ -197,7 +197,21 @@ def send_Armature(arm, options):
msgs = []
chord_scene = bpy.context.scene.chordata
try:
arm = arm_m.object
root_bone = arm_m.root_bone
root_starting_loc = arm_m.root_starting_loc
relative_root_height = arm_m.relative_root_height
except AttributeError as e:
arm = arm_m
root_bone = False
lowest_bone_z = 0
for b in arm.pose.bones:
if options.send_root_z and root_bone:
lowest_bone_z = min(b.tail.z, lowest_bone_z)
if not b.transmit_bone: continue
if options.send_rot:
......@@ -239,6 +253,9 @@ def send_Armature(arm, options):
msgs.append(oscbuildparse.OSCMessage("/Chordata/dist_3/"+b.name,
None, [dist.length]))
if options.send_root_z and root_bone:
root_normalized_z = (root_starting_loc.z - lowest_bone_z) / relative_root_height
msgs.append(oscbuildparse.OSCMessage("/Chordata/root_z", None, [root_normalized_z]))
if not msgs: return
......
Timer unit: 1e-06 s
Total time: 0.094833 s
File: /home/daylan/.local/bin/blender-2.79-linux-glibc219-x86_64/2.79/scripts/addons_contrib/chordata_addon/osc4py3_original/osc4py3/osctoolspools.py
Function: wait_for_job at line 180
Line # Hits Time Per Hit % Time Line Contents
==============================================================
180 @profile
181 def wait_for_job(self, timeout=None):
182 """Called by a working thread to get next job.
183
184 If working thread get a LAST_JOB job, then they must exit.
185
186 :param timeout: maximum seconds to wait for a job, None for infinite,
187 0 for just polling.
188 Default to None (infinite wait).
189 :type timeout: float or None
190 :return: informations needed by worker thread(s) to do the job, or
191 None if if exited with a timeout, or LAST_JOB it the workqueue
192 is terminating.
193 :rtype: WorkJob
194 """
195 4883 75192.0 15.4 79.3 if not self.sem.acquire(timeout): # Wait for an available job.
196 258 384.0 1.5 0.4 return None
197 4625 8594.0 1.9 9.1 job = self.jobs.popleft()
198 4625 5842.0 1.3 6.2 if job is LAST_JOB:
199 # In case there is another thread waiting for a job
200 self.send_terminate()
201 4625 4821.0 1.0 5.1 return job
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment