active bone shape
|
@ -53,6 +53,7 @@ def register():
|
||||||
#bpy.types.Scene.bone_widget = bpy.props.PointerProperty(type=BoneWidgetSettings)
|
#bpy.types.Scene.bone_widget = bpy.props.PointerProperty(type=BoneWidgetSettings)
|
||||||
#get_widgets(DefaultFolder, DefaultShapes)
|
#get_widgets(DefaultFolder, DefaultShapes)
|
||||||
#get_widgets(CustomFolder, CustomShapes)
|
#get_widgets(CustomFolder, CustomShapes)
|
||||||
|
sys.modules.update({"bone_widget.ctx": context.BW_context()})
|
||||||
from bone_widget import ctx
|
from bone_widget import ctx
|
||||||
|
|
||||||
for f in ctx.folders:
|
for f in ctx.folders:
|
||||||
|
|
11
context.py
|
@ -153,12 +153,15 @@ class BW_context:
|
||||||
|
|
||||||
ob = bpy.context.object
|
ob = bpy.context.object
|
||||||
if ob.type == 'ARMATURE':
|
if ob.type == 'ARMATURE':
|
||||||
bones = ob.pose.bones
|
return bpy.context.selected_pose_bones
|
||||||
return [b for b in bones if b.bone.select]
|
#bones = ob.pose.bones
|
||||||
else:
|
#return [b for b in bones if b.bone.select]
|
||||||
|
elif self.rig:
|
||||||
widgets = self.selected_widgets
|
widgets = self.selected_widgets
|
||||||
return [b for b in self.rig.pose.bones if b.custom_shape in widgets]
|
return [b for b in self.rig.pose.bones if b.custom_shape in widgets]
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def widget(self):
|
def widget(self):
|
||||||
if not self.poll():
|
if not self.poll():
|
||||||
|
@ -253,7 +256,7 @@ class BW_context:
|
||||||
return False
|
return False
|
||||||
if ob.type == 'ARMATURE' and ob.mode == 'POSE':
|
if ob.type == 'ARMATURE' and ob.mode == 'POSE':
|
||||||
return True
|
return True
|
||||||
if ob.type in ('MESH','CURVE'):
|
if ob.type in ('MESH', 'CURVE'):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
35
operators.py
|
@ -420,7 +420,7 @@ class BW_OT_create_widget(Operator):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return ctx.bone and ctx.active_widget
|
return ctx.selected_bones and ctx.active_widget
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
folder = ctx.active_folder
|
folder = ctx.active_folder
|
||||||
|
@ -633,23 +633,33 @@ class BW_OT_add_widget(Operator):
|
||||||
bl_label = "Add Widget"
|
bl_label = "Add Widget"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
replace: BoolProperty(default=False, name='Replace')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return ctx.widget
|
return ctx.widget
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
if event.ctrl:
|
||||||
|
self.replace = True
|
||||||
|
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
folder = ctx.active_folder
|
||||||
shape = ctx.widget
|
shape = ctx.widget
|
||||||
bone = ctx.bone
|
bone = ctx.bone
|
||||||
|
|
||||||
if bone:
|
if self.replace and ctx.active_widget:
|
||||||
name = bone.name
|
name = ctx.active_widget.name
|
||||||
else:
|
else: #Find a unique name
|
||||||
name = shape.name
|
name = folder.get_widget_display_name(bone.name if bone else shape.name)
|
||||||
|
|
||||||
#name = name.split('-', 1)[-1]
|
i = 0
|
||||||
#name = re.sub('.\d{3}', '', name)
|
org_name = name
|
||||||
folder = ctx.active_folder
|
while name in folder.widgets:
|
||||||
name = folder.get_widget_clean_name(name)
|
name = f'{org_name} {i:02d}'
|
||||||
|
i += 1
|
||||||
|
|
||||||
widget_path = folder.get_widget_path(name)
|
widget_path = folder.get_widget_path(name)
|
||||||
icon_path = folder.get_icon_path(name)
|
icon_path = folder.get_icon_path(name)
|
||||||
|
@ -661,10 +671,11 @@ class BW_OT_add_widget(Operator):
|
||||||
shape_copy = shape.copy()
|
shape_copy = shape.copy()
|
||||||
shape_copy.data = shape_copy.data.copy()
|
shape_copy.data = shape_copy.data.copy()
|
||||||
|
|
||||||
shape_copy.matrix_world = get_bone_matrix(bone)
|
if bone:
|
||||||
|
shape_copy.matrix_world = get_bone_matrix(bone)
|
||||||
|
|
||||||
mat = custom_shape_matrix(bone)
|
mat = custom_shape_matrix(bone)
|
||||||
shape_copy.data.transform(mat)
|
shape_copy.data.transform(mat)
|
||||||
|
|
||||||
render_widget(shape_copy, icon_path)
|
render_widget(shape_copy, icon_path)
|
||||||
folder.add_widget(name)
|
folder.add_widget(name)
|
||||||
|
|
|
@ -70,12 +70,17 @@ def refresh(self, context):
|
||||||
bpy.ops.bonewidget.refresh_folders()
|
bpy.ops.bonewidget.refresh_folders()
|
||||||
|
|
||||||
class BW_PG_folder(PropertyGroup):
|
class BW_PG_folder(PropertyGroup):
|
||||||
icons = bpy.utils.previews.new()
|
#icons = bpy.utils.previews.new()
|
||||||
path: StringProperty(subtype='FILE_PATH', default='Default', update=refresh)
|
path: StringProperty(subtype='FILE_PATH', default='Default', update=refresh)
|
||||||
expand: BoolProperty()
|
expand: BoolProperty()
|
||||||
widgets: CollectionProperty(type=BW_PG_widget)
|
widgets: CollectionProperty(type=BW_PG_widget)
|
||||||
widget_index: IntProperty()
|
widget_index: IntProperty()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icons(self):
|
||||||
|
prefs = ctx.prefs
|
||||||
|
return prefs.get_folder_previews(self.as_pointer())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def abspath(self):
|
def abspath(self):
|
||||||
return ctx.abspath(self.path)
|
return ctx.abspath(self.path)
|
||||||
|
@ -202,6 +207,8 @@ class BW_PG_bone_color(PropertyGroup):
|
||||||
class BW_prefs(AddonPreferences):
|
class BW_prefs(AddonPreferences):
|
||||||
bl_idname = __package__
|
bl_idname = __package__
|
||||||
|
|
||||||
|
previews = {}
|
||||||
|
|
||||||
default_folder: PointerProperty(type=BW_PG_folder)
|
default_folder: PointerProperty(type=BW_PG_folder)
|
||||||
folders: CollectionProperty(type=BW_PG_folder)
|
folders: CollectionProperty(type=BW_PG_folder)
|
||||||
folder_index: IntProperty()
|
folder_index: IntProperty()
|
||||||
|
@ -225,6 +232,12 @@ class BW_prefs(AddonPreferences):
|
||||||
|
|
||||||
#use_custom_colors: BoolProperty(name='Custom Colors', default=False, update=set_default_colors)
|
#use_custom_colors: BoolProperty(name='Custom Colors', default=False, update=set_default_colors)
|
||||||
|
|
||||||
|
def get_folder_previews(self, adress):
|
||||||
|
if adress not in self.previews:
|
||||||
|
self.previews[adress] = bpy.utils.previews.new()
|
||||||
|
|
||||||
|
return self.previews[adress]
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
draw_prefs(self.layout)
|
draw_prefs(self.layout)
|
||||||
|
|
||||||
|
|
8
ui.py
|
@ -249,6 +249,14 @@ class BW_PT_main(Panel):
|
||||||
edit_row.operator('bonewidget.create_widget', text='Create')
|
edit_row.operator('bonewidget.create_widget', text='Create')
|
||||||
edit_row.operator('bonewidget.edit_widget', text='Edit')
|
edit_row.operator('bonewidget.edit_widget', text='Edit')
|
||||||
|
|
||||||
|
# Draw Active Bone Shape
|
||||||
|
if context.active_pose_bone:
|
||||||
|
widget_col.separator()
|
||||||
|
col = widget_col.column(align=False)
|
||||||
|
col.use_property_split = True
|
||||||
|
col.prop(context.active_pose_bone, 'name', text='Bone Name')
|
||||||
|
col.prop(context.active_pose_bone, 'custom_shape', text='Widget')
|
||||||
|
|
||||||
if ctx.prefs.use_custom_collection and ctx.rig:
|
if ctx.prefs.use_custom_collection and ctx.rig:
|
||||||
widget_col.separator()
|
widget_col.separator()
|
||||||
row = widget_col.row()
|
row = widget_col.row()
|
||||||
|
|
Before Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 888 B |
Before Width: | Height: | Size: 624 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 809 B After Width: | Height: | Size: 809 B |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 1.7 KiB |