def tool_down(self, event): self._handle = -1 self._moved = False self._bones = self.get_current_bones() for i in range(len(self._bones)): bone = self._bones[i] pos, axis = self.get_world_bone_axis(bone) pos += axis * self._frac scale = Vector.magnitude(axis) / 10.0 eventpos = Vector(event.posRaw[0], event.posRaw[1], event.posRaw[2]) eventaxis = Vector(event.axis[0], event.axis[1], event.axis[2]) # te.axis is normalized # d = |(x2-x1) x (x1-x0)| / |x2-x1| # x2 = eventpos, x1 = eventpos + axis, x0 = pos # (x2-x1) = -axis # (x1-x0) = eventpos+axis - pos # |(x2-x1)| = 1 # (-axis) x (eventpos-pos+axis) d = Vector.magnitude(Vector.cross(-eventaxis, eventpos - pos + eventaxis)) if d <= scale: self._handle = i return 1 return 0
def tool_move(self, event): if self._handle < 0: return # Nearest point on line A to line B: # N = (Da x Db) x Db # t = ((Pb - Pa) . N) / (Da . N) # A == bone # B == event # event axis (Db) is normalized, so t in units of |Da| pos, axis = self.get_world_bone_axis(self._bones[self._handle]) eventpos = Vector(event.posRaw[0], event.posRaw[1], event.posRaw[2]) eventaxis = Vector(event.axis[0], event.axis[1], event.axis[2]) N = Vector.cross(Vector.cross(axis, eventaxis), eventaxis) DaN = Vector.dot(axis, N) Pba = eventpos - pos self._frac = Vector.dot(Pba, N) / DaN if self._frac < 0: self._frac = 0 if self._frac > 1: self._frac = 1 self._dirty = True self._moved = True
def tool_draw(self, ca): self._bones = self.get_current_bones() cur_time = lwsdk.LWInterfaceInfo().curTime for bone in self._bones: if bone.type == lwsdk.LWBONETYPE_ZAXIS: len = bone.restlength; dir = Vector(0,0,1) ca.setCSysItem(ca.dispData, bone.id); else: pos = self._item_info.param(bone.id, lwsdk.LWIP_POSITION, cur_time) len = Vector.magnitude(pos) dir = pos / len; ca.setCSysItem(ca.dispData, bone.parent); ca.setDrawMode(ca.dispData, 8 + 4) q1 = Vector(-0.1,-0.1,0) q2 = Vector( 0.1,-0.1,0) q3 = Vector( 0.1, 0.1,0) q4 = Vector(-0.1, 0.1,0) q1 += dir * self._frac q1 *= len q2 += dir * self._frac q2 *= len q3 += dir * self._frac q3 *= len q4 += dir * self._frac q4 *= len # color can be a lwsdk.Vector, lwsdk.Color or a Python sequence ca.setColor(ca.dispData, [1.0, 0.3, 0.1, 1.0]) ca.line(ca.dispData, q1, q2, lwsdk.LWCSYS_OBJECT) ca.line(ca.dispData, q2, q3, lwsdk.LWCSYS_OBJECT) ca.line(ca.dispData, q3, q4, lwsdk.LWCSYS_OBJECT) ca.line(ca.dispData, q4, q1, lwsdk.LWCSYS_OBJECT) ca.line(ca.dispData, q1, q3, lwsdk.LWCSYS_OBJECT) ca.line(ca.dispData, q2, q4, lwsdk.LWCSYS_OBJECT) ca.setColor(ca.dispData, [1.0, 0.3, 0.1, 0.2]) ca.quad(ca.dispData, q1, q2, q3, q4, lwsdk.LWCSYS_OBJECT)
def split_bone(self, bone, split): cur_time = lwsdk.LWTimeInfo().time; pos = self._item_info.param(bone.id, lwsdk.LWIP_W_POSITION, cur_time) rest_pos = Vector(self._bone_info.restParam(bone.id, lwsdk.LWIP_POSITION)) rest_rot = Vector(self._bone_info.restParam(bone.id, lwsdk.LWIP_ROTATION)) rest_rot *= math.pi / 180.0 rest_len = bone.restlength # Clone the existing bone # Make the new bone the parent, existing bone the child lwsdk.command("SelectItem %s" % lwsdk.itemid_to_str(bone.id)) lwsdk.command("Clone 1") selected_items = lwsdk.LWInterfaceInfo().selected_items() new_bone = PyBone(selected_items[0], self._item_info.parent(selected_items[0]), self._bone_info.type(selected_items[0]), self._bone_info.restLength(selected_items[0])) # Make new bone child of original parent lwsdk.command("ParentItem %s" % lwsdk.itemid_to_str(bone.parent)) # Motion options corrections: # - Don't copy over the goal lwsdk.command("GoalItem 0") if new_bone.type == lwsdk.LWBONETYPE_ZAXIS: temp_vector = Vector(0,0,1) split_pos = temp_vector * (rest_len * split) # Make new bone shorter to the split lwsdk.command("BoneRestLength %g" % (rest_len * split)) # Make corrections to existing bone # - Parent it to the new bone # - Place at the split position # - Shorten it to the remainder of original length # - Reset scale and rotation (as those are now done by new bone) lwsdk.command("SelectItem %s" % lwsdk.itemid_to_str(bone.id)) lwsdk.command("ParentItem %s" % lwsdk.itemid_to_str(new_bone.id)) # Set positions self.set_vec_chan_to_value(bone.id, 0, split_pos) lwsdk.command("PivotPosition 0 0 0") lwsdk.command("BoneRestPosition %s" % str(split_pos)) lwsdk.command("BoneRestLength %g" % (rest_len * (1-split))) # Set rotations self.set_vec_chan_to_value(bone.id, 3, Vector(0,0,0)) lwsdk.command("PivotRotation 0 0 0") lwsdk.command("BoneRestRotation 0 0 0") # Set scales self.set_vec_chan_to_value(bone.id, 6, Vector(1,1,1)); lwsdk.command("DirtyMotion") lwsdk.command("UpdateMotion") # Move children to take into account shortened bone child_id = self._item_info.firstChild(bone.id) while child_id: lwsdk.command("SelectItem %s" % lwsdk.itemid_to_str(child_id)) self.add_value_to_vec_chan(child_id, 0, -split_pos); if self._item_info.type(child_id) == lwsdk.LWI_BONE: child_pos = Vector(self._bone_info.restParam(child_id, lwsdk.LWIP_POSITION)) child_pos -= split_pos; lwsdk.command("BoneRestPosition %s" % str(child_pos)) lwsdk.command("DirtyMotion") lwsdk.command("UpdateMotion") child_id = self._item_info.nextChild(bone.id, child_id) else: axispos, axis = self.get_world_bone_axis(bone) # Move new bone to split position new_rest_pos = rest_pos * split lwsdk.command("BoneRestPosition %s" % str(new_rest_pos)) # newPos = split * pos self.mul_value_to_vec_chan(new_bone.id, 0, split) lwsdk.command("BoneRestRotation 0 0 0") self.set_vec_chan_to_value(new_bone.id, 3, Vector(0,0,0)) self.set_vec_chan_to_value(new_bone.id, 6, Vector(1,1,1)) lwsdk.command("DirtyMotion") lwsdk.command("UpdateMotion") # Make corrections to existing bone # - Parent it to the new bone lwsdk.command("SelectItem %s" % lwsdk.itemid_to_str(bone.id)) lwsdk.command("ParentItem %s" % lwsdk.itemid_to_str(new_bone.id)) # - Correct place to account for new bone parent # New bone parent has no rotation and unit scale, # so only difference is a position offset new_rest_pos = rest_pos * (1.0 - split) lwsdk.command("BoneRestPosition %s" % str(new_rest_pos)) # newPos = (1.0 - split) * pos self.mul_value_to_vec_chan(bone.id, 0, 1.0 - split) lwsdk.command("DirtyMotion") lwsdk.command("UpdateMotion") return new_bone
def process(self, ga): item_info = lwsdk.LWItemInfo() object_info = lwsdk.LWObjectInfo() instancer_funcs = lwsdk.LWItemInstancerFuncs() instance_info = lwsdk.LWItemInstanceInfo() interface_info = lwsdk.LWInterfaceInfo() current_time = interface_info.curTime autokey_is_on = ((interface_info.generalFlags & lwsdk.LWGENF_AUTOKEY) != 0) selected_item = interface_info.selected_items()[0] selected_item_id = lwsdk.itemid_to_str(selected_item) # find the Instancer that owns the selected object found_instancer = None obj = item_info.first(lwsdk.LWI_OBJECT, None) while obj and (not found_instancer): instancer = object_info.instancer(obj) if instancer: instance = instancer_funcs.first(instancer) while instance and (not found_instancer): if instance_info.item(instance) == selected_item: # found it! found_instancer = instancer break instance = instancer_funcs.next(instancer, instance) obj = item_info.next(obj) if not found_instancer: print >>sys.stderr, 'Object "%s" is NOT instanced!' % item_info.name(selected_item) return lwsdk.AFUNC_OK instances = [] instance = instancer_funcs.first(found_instancer) while instance: if instance_info.item(instance) == selected_item: instances.append(instance) instance = instancer_funcs.next(found_instancer, instance) # values used for progress current_index = 1.0 target_index = len(instances) * 1.0 for instance in instances: pos = instance_info.pos(instance, 0) # Note: InstanceInfo.rotation() returns radians! rot = instance_info.rotation(instance, 0) scl = instance_info.scale(instance, 0) lwsdk.command("SelectItem %s" % selected_item_id) lwsdk.command("Clone 1") lwsdk.command("Position %s" % str(pos)) # Note: Rotation expects degrees! lwsdk.command("Rotation %s" % str(Vector.to_degrees(rot))) lwsdk.command("Scale %s" % str(scl)) if not autokey_is_on: lwsdk.command("CreateKey %f" % current_time) lwsdk.command("StatusMsg {%f}Baking instances..." % (current_index / target_index)) current_index += 1.0 lwsdk.command("SelectItem %s" % selected_item_id) lwsdk.command("StatusMsg Baking complete.") return lwsdk.AFUNC_OK
def process(self, ga): item_info = lwsdk.LWItemInfo() object_info = lwsdk.LWObjectInfo() instancer_funcs = lwsdk.LWItemInstancerFuncs() instance_info = lwsdk.LWItemInstanceInfo() interface_info = lwsdk.LWInterfaceInfo() current_time = interface_info.curTime autokey_is_on = ((interface_info.generalFlags & lwsdk.LWGENF_AUTOKEY) != 0) selected_item = interface_info.selected_items()[0] selected_item_id = lwsdk.itemid_to_str(selected_item) # find the Instancer that owns the selected object found_instancer = None obj = item_info.first(lwsdk.LWI_OBJECT, None) while obj and (not found_instancer): instancer = object_info.instancer(obj) if instancer: instance = instancer_funcs.first(instancer) while instance and (not found_instancer): if instance_info.item(instance) == selected_item: # found it! found_instancer = instancer break instance = instancer_funcs.next(instancer, instance) obj = item_info.next(obj) if not found_instancer: print >> sys.stderr, 'Object "%s" is NOT instanced!' % item_info.name( selected_item) return lwsdk.AFUNC_OK instances = [] instance = instancer_funcs.first(found_instancer) while instance: if instance_info.item(instance) == selected_item: instances.append(instance) instance = instancer_funcs.next(found_instancer, instance) # values used for progress current_index = 1.0 target_index = len(instances) * 1.0 for instance in instances: pos = instance_info.pos(instance, 0) # Note: InstanceInfo.rotation() returns radians! rot = instance_info.rotation(instance, 0) scl = instance_info.scale(instance, 0) lwsdk.command("SelectItem %s" % selected_item_id) lwsdk.command("Clone 1") lwsdk.command("Position %s" % str(pos)) # Note: Rotation expects degrees! lwsdk.command("Rotation %s" % str(Vector.to_degrees(rot))) lwsdk.command("Scale %s" % str(scl)) if not autokey_is_on: lwsdk.command("CreateKey %f" % current_time) lwsdk.command("StatusMsg {%f}Baking instances..." % (current_index / target_index)) current_index += 1.0 lwsdk.command("SelectItem %s" % selected_item_id) lwsdk.command("StatusMsg Baking complete.") return lwsdk.AFUNC_OK