From 3a06eb6890b5b53e170cfbb57b5c34749c9da229 Mon Sep 17 00:00:00 2001 From: Christophe SEUX Date: Fri, 31 Mar 2023 14:53:41 +0200 Subject: [PATCH] Assign bones --- area.py | 3 ++ func_shape.py | 5 +-- op_picker.py | 7 +++- op_shape.py | 2 +- panels.py | 3 +- picker.py | 94 +++++++++++++++++++++++++++++++++++++++++---------- properties.py | 5 +-- utils.py | 20 +++++------ 8 files changed, 103 insertions(+), 36 deletions(-) diff --git a/area.py b/area.py index 0e06cdd..b3e5dd3 100644 --- a/area.py +++ b/area.py @@ -36,6 +36,9 @@ def draw_header(self, context): #layout.separator_spacer() layout.operator('rigpicker.reload_picker', icon='FILE_REFRESH', text='') + + #layout.prop('rigpicker.reload_picker', icon='FILE_REFRESH', text='') + layout.separator_spacer() else: diff --git a/func_shape.py b/func_shape.py index dd0dd39..1cf39a1 100644 --- a/func_shape.py +++ b/func_shape.py @@ -20,7 +20,7 @@ def get_picker_datas(objects, canvas, rig): canvas_y = [p[1] for p in canvas_coords] canvas_center = sum(canvas_coords, Vector()) / len(canvas_coords) - canvas_scale_fac = 1024 / (max(canvas_y) - min(canvas_y))# Reference height for the canvas + canvas_scale_fac = 4096 / (max(canvas_y) - min(canvas_y))# Reference height for the canvas objects.append(canvas) @@ -74,6 +74,7 @@ def get_picker_datas(objects, canvas, rig): color = [0.5, 0.5, 0.5] shape = { + 'source_name': ob.name, 'tooltip': ob.rig_picker.name, 'points': points, 'polygons': polygons, @@ -96,7 +97,7 @@ def get_picker_datas(objects, canvas, rig): picker_datas.append(shape) - print(picker_datas) + #print(picker_datas) return picker_datas #rig.data.rig_picker['shapes'] = picker_datas diff --git a/op_picker.py b/op_picker.py index cb45942..26dd584 100644 --- a/op_picker.py +++ b/op_picker.py @@ -171,7 +171,12 @@ class RP_OT_box_select(bpy.types.Operator): return {'RUNNING_MODAL'} def release_event(self): - if (self.start_mouse[0] != self.mouse[0] and self.start_mouse[1] != self.mouse[1]): + scn = bpy.context.scene + + if scn.rig_picker.use_pick_bone: + self.picker.assign_bone_event() + + elif (self.start_mouse[0] != self.mouse[0] and self.start_mouse[1] != self.mouse[1]): self.picker.border_select(self.border, self.mode) else: self.picker.move_event(self.mouse) diff --git a/op_shape.py b/op_shape.py index 67c3fe5..3a4d548 100644 --- a/op_shape.py +++ b/op_shape.py @@ -183,7 +183,7 @@ class RP_OT_save_picker(bpy.types.Operator): def execute(self, context): scn = context.scene - canvas= scn.rig_picker.canvas + canvas = scn.rig_picker.canvas rig = scn.rig_picker.rig shapes = [o for o in scn.objects if o != canvas and is_shape(o)] diff --git a/panels.py b/panels.py index 130f588..e4b10bb 100644 --- a/panels.py +++ b/panels.py @@ -25,7 +25,7 @@ class RP_PT_picker_maker_panel(bpy.types.Panel): layout = self.layout col = layout.column(align=False) col.prop_search(scn.rig_picker, 'rig', scn, 'objects', text='Rig ') - col.prop_search(scn.rig_picker, 'canvas', scn, 'objects', text='canvas ') + col.prop_search(scn.rig_picker, 'canvas', scn, 'objects', text='Canvas ') col.prop_search(scn.rig_picker, 'symmetry', scn, 'objects', text='Symmetry ') if ob.type == 'ARMATURE': @@ -42,6 +42,7 @@ class RP_PT_picker_maker_panel(bpy.types.Panel): row.operator('rigpicker.create_shape', icon='MESH_DATA', text='Create shape') row.operator('rigpicker.mirror_shape', icon='ARROW_LEFTRIGHT', text='Mirror shape') col.operator('rigpicker.name_from_bone', icon='SORTALPHA' , text='Name from bones') + col.prop(scn.rig_picker, 'use_pick_bone', icon='EYEDROPPER', text='Auto bone assign') if ob.type !='ARMATURE': diff --git a/picker.py b/picker.py index fcef07c..e6898e4 100644 --- a/picker.py +++ b/picker.py @@ -18,11 +18,12 @@ import threading class Shape: - def __init__(self, picker, points, polygons=None, edges=None, tooltip='', color=None): + def __init__(self, picker, points, polygons=None, edges=None, tooltip='', color=None, source_name=''): self.type = 'display' self.picker = picker self.rig = picker.rig + self.source_name = source_name self.hover = False self.press = False @@ -116,9 +117,9 @@ class Shape: class BoneShape(Shape): - def __init__(self, picker, points, polygons, edges, bone, tooltip='', color=None): + def __init__(self, picker, points, polygons, edges, bone, tooltip='', color=None, source_name=''): super().__init__(picker, points=points, polygons=polygons, edges=edges, - tooltip=tooltip, color=color) + tooltip=tooltip, color=color, source_name=source_name) self.type = 'bone' self.bone = bone @@ -141,24 +142,35 @@ class BoneShape(Shape): 'hide': [0.85, 0.85, 0.85, 0.2], } - if bone.bone_group: + if bone and bone.bone_group: normal_color = bone.bone_group.colors.normal.copy() normal_color.s *= 0.75 self.bone_colors['normal'] = [*normal_color, 1] self.bone_colors['select'] = [*bone.bone_group.colors.select, 1] self.bone_colors['active'] = [*bone.bone_group.colors.active, 1] self.bone_colors['hide'] = [*normal_color, 0.1] + + #self.color = [i for i in self.color] @property def select(self): + if not self.bone: + return False + return self.bone in (bpy.context.selected_pose_bones or []) #self.bone.bone.select @property def active(self): + if not self.bone: + return False + return self.bone == bpy.context.active_pose_bone #self.rig.data.bones.active == self.bone.bone @property def hide(self): + if not self.bone: + return False + #return self.bone not in (bpy.context.visible_pose_bones or []) bl = [i for i, l in enumerate(self.bone.bone.layers) if l] rl = [i for i, l in enumerate(self.rig.data.layers) if l] @@ -166,6 +178,9 @@ class BoneShape(Shape): @property def bone_color(self): + if not self.bone: + return [0, 0, 0, 1] + bone = self.bone.bone bl = bone.layers @@ -192,6 +207,10 @@ class BoneShape(Shape): else: super().draw() + # Overlay the fill slightly with the bone color + #self.shader.uniform_float("color", (*self.bone_color[:3], 0.1)) + #self.p_batch.draw(self.shader) + if self.select: color = self.hover_color @@ -204,6 +223,10 @@ class BoneShape(Shape): self.shader.uniform_float("color", color) self.p_batch.draw(self.shader) + #Overlay the fill slightly with the bone color + self.shader.uniform_float("color", (*self.bone_colors['normal'][:3], 0.1)) + self.p_batch.draw(self.shader) + #self.contour_shader.bind() @@ -217,24 +240,40 @@ class BoneShape(Shape): bgl.glLineWidth(1) bgl.glDisable(bgl.GL_BLEND) + + def assign_bone_event(self): + + #print('assign_bone_event', self) + scn = bpy.context.scene + rig = scn.rig_picker.rig + source_object = scn.objects.get(self.source_name) + if not source_object: + print(f'Source object {self.source_name} not found') + return + active_bone = rig.data.bones.active + if not active_bone: + print('You need to have an active bone') + return + + source_object.rig_picker.name = rig.data.bones.active.name + def release_event(self, mode='SET'): super().release_event(mode) - if self.hide: + if self.hide or not self.bone: return select = True if mode == 'SUBSTRACT': select = False + self.bone.bone.select = select if self.hover: - self.bone.bone.select = select if mode != 'SUBSTRACT': self.rig.data.bones.active = self.bone.bone - else: - self.bone.bone.select = select + def border_select(self, border, mode='SET'): ''' @@ -242,6 +281,8 @@ class BoneShape(Shape): not any(intersect_point_quad_2d(b, *border) for b in self.bound) ): return ''' + if not self.bone: + return if self.hide: self.bone.bone.select = False @@ -287,8 +328,9 @@ class BoneShape(Shape): ''' class OperatorShape(Shape): - def __init__(self, picker, points, polygons, operator, tooltip='', color=None): - super().__init__(picker, points=points, polygons=polygons, tooltip=tooltip, color=color) + def __init__(self, picker, points, polygons, operator, tooltip='', color=None, source_name=''): + super().__init__(picker, points=points, polygons=polygons, tooltip=tooltip, + color=color, source_name=source_name) self.type = 'operator' self.active_color = [1, 1, 1, 0.15] @@ -367,7 +409,7 @@ class Picker: if s['type'] in ('CANVAS', 'DISPLAY'): shape = Shape( - self, + self, points=s['points'], polygons=s['polygons'], edges=s['edges'], @@ -376,11 +418,13 @@ class Picker: elif s['type'] == 'BONE': bone = rig.pose.bones.get(s['bone']) - if not bone: - print(f'Bone {s["bone"]} not exist') - continue + #if not bone: + # print(f'Bone {s["bone"]} not exist') + # continue + shape = BoneShape( - self, + self, + source_name=s['source_name'], points=s['points'], polygons=s['polygons'], edges=s['edges'], @@ -390,7 +434,8 @@ class Picker: elif s['type'] == 'OPERATOR': shape = OperatorShape( - self, + self, + source_name=s['source_name'], points=s['points'], polygons=s['polygons'], operator=s['operator'], @@ -400,6 +445,13 @@ class Picker: self.shapes.append(shape) + def assign_bone_event(self): + for s in self.shapes: + if s.type=='bone' and s.hover: + s.assign_bone_event() + + bpy.ops.rigpicker.save_picker() + def press_event(self, mode='SET'): for s in self.shapes: if s.hover: @@ -427,6 +479,8 @@ class Picker: def tooltip_event(self): #print('Tooltip Event', self) + #print(self.hover_shape, self.hover_shape.type) + if self.hover_shape and self.hover_shape.type != 'display': if self.hover_shape.type == 'bone': self.tooltip = self.hover_shape.bone.name @@ -441,6 +495,8 @@ class Picker: self.timer.cancel() + #print(self.tooltip) + self.region.tag_redraw() ''' @@ -567,6 +623,8 @@ def draw_callback_px(): text = picker.tooltip + #print('Draw text', text) + font_id = 0 #blf.dimensions(font_id, text) blf.enable(font_id, blf.SHADOW) @@ -575,11 +633,11 @@ def draw_callback_px(): # BLF drawing routine blf.position(font_id, picker.tooltip_mouse[0]-5, picker.tooltip_mouse[1]+5, 0) - blf.size(font_id, 14, 0) + blf.size(font_id, 14) blf.color(font_id, 1, 1, 1, 1) blf.shadow(font_id , 5, 0.0, 0.0, 0.0, 1) - blf.shadow_offset(font_id, 1, -1) + blf.shadow_offset(font_id, 2, -2) blf.draw(font_id, text) diff --git a/properties.py b/properties.py index b0d1dd1..21efaf5 100644 --- a/properties.py +++ b/properties.py @@ -1,5 +1,5 @@ import bpy -from bpy.props import EnumProperty, StringProperty, PointerProperty +from bpy.props import EnumProperty, StringProperty, PointerProperty, BoolProperty import inspect ''' @@ -42,7 +42,8 @@ class RP_PG_scene_ui_settings(bpy.types.PropertyGroup): symmetry: PointerProperty(type=bpy.types.Object) #idname: EnumProperty(items=[]) destination: StringProperty(subtype='FILE_PATH') - #bone_list: bpy.props.EnumProperty(items = bones_item) + #bone_list: bpy.props.EnumProperty(items = bones_item + use_pick_bone : BoolProperty(default=False) class RP_OT_operator_selector(bpy.types.Operator): diff --git a/utils.py b/utils.py index b266d85..c430216 100644 --- a/utils.py +++ b/utils.py @@ -184,20 +184,18 @@ def find_mirror(name): else: return None - def is_shape(ob): - shape = False + scn = bpy.context.scene + canvas = scn.rig_picker.canvas + if not canvas or ob.hide_render: + return False + + shapes = {ob for col in canvas.users_collection for ob in col.all_objects} - if ob.hide_render: - return shape + if ob.type in ('MESH', 'CURVE', 'FONT') and ob in shapes: + return True - if ob.type in ('MESH', 'CURVE', 'FONT'): - if ob.rig_picker.shape_type == 'BONE': - if ob.rig_picker.name: - shape = True - else: - shape = True - return shape + return False def is_over_region(self,context,event): inside = 2 < event.mouse_region_x < context.region.width -2 and \