fixing bugs
23
__init__.py
|
@ -1,8 +1,8 @@
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Bone Widget",
|
"name": "Bone Widget",
|
||||||
"author": "Christophe SEUX",
|
"author": "Christophe SEUX",
|
||||||
"version": (2, 0, 0),
|
"version": (2, 0, 1),
|
||||||
"blender": (2, 92, 0),
|
"blender": (3, 4, 1),
|
||||||
"description": "Create custom shapes for bone controller",
|
"description": "Create custom shapes for bone controller",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
"wiki_url": "",
|
"wiki_url": "",
|
||||||
|
@ -12,22 +12,37 @@ bl_info = {
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if "bpy" in locals():
|
if "bpy" in locals():
|
||||||
import importlib as imp
|
import importlib as imp
|
||||||
imp.reload(context)
|
imp.reload(context)
|
||||||
|
sys.modules.update({"bone_widget.ctx": context.BW_context()})
|
||||||
|
|
||||||
|
imp.reload(shape_utils)
|
||||||
|
imp.reload(transform_utils)
|
||||||
|
imp.reload(icon_utils)
|
||||||
|
|
||||||
imp.reload(properties)
|
imp.reload(properties)
|
||||||
imp.reload(operators)
|
imp.reload(operators)
|
||||||
imp.reload(ui)
|
imp.reload(ui)
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
from . import context
|
from . import context
|
||||||
|
sys.modules.update({"bone_widget.ctx": context.BW_context()})
|
||||||
|
|
||||||
from . import operators
|
from . import operators
|
||||||
from . import ui
|
from . import ui
|
||||||
from . import properties
|
from . import properties
|
||||||
|
from . import shape_utils
|
||||||
|
from . import transform_utils
|
||||||
|
from . import icon_utils
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
import sys
|
||||||
|
|
||||||
#sys.modules.update({"bone_widget.ctx": context.BW_ctx()})
|
#sys.modules.update({"bone_widget.ctx": context.BW_ctx()})
|
||||||
from bone_widget import ctx
|
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
@ -38,6 +53,8 @@ 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)
|
||||||
|
from bone_widget import ctx
|
||||||
|
|
||||||
for f in ctx.folders:
|
for f in ctx.folders:
|
||||||
f.load_widgets()
|
f.load_widgets()
|
||||||
|
|
||||||
|
|
17
context.py
|
@ -6,7 +6,7 @@ import os
|
||||||
from bone_widget.shape_utils import get_bone
|
from bone_widget.shape_utils import get_bone
|
||||||
|
|
||||||
|
|
||||||
class BW_ctx:
|
class BW_context:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.module_dir = Path(__file__).parent
|
self.module_dir = Path(__file__).parent
|
||||||
|
@ -48,11 +48,15 @@ class BW_ctx:
|
||||||
@property
|
@property
|
||||||
def show_prefs_op(self):
|
def show_prefs_op(self):
|
||||||
ops = bpy.context.window_manager.operators
|
ops = bpy.context.window_manager.operators
|
||||||
op_idname = self.get_op_id('show_preferences')
|
id_names = [
|
||||||
|
self.get_op_id('show_preferences'),
|
||||||
|
self.get_op_id('add_folder'),
|
||||||
|
self.get_op_id('remove_folder')
|
||||||
|
]
|
||||||
|
|
||||||
#transforms = self.prefs.transforms
|
#transforms = self.prefs.transforms
|
||||||
if ops and ops[-1].bl_idname == op_idname:
|
if ops and ops[-1].bl_idname in id_names:
|
||||||
return ops[-1]
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def category(self):
|
def category(self):
|
||||||
|
@ -70,6 +74,9 @@ class BW_ctx:
|
||||||
@property
|
@property
|
||||||
def widget_col(self):
|
def widget_col(self):
|
||||||
col_name = self.prefs.collection
|
col_name = self.prefs.collection
|
||||||
|
|
||||||
|
col_name = col_name.format(ob=bpy.context.object)
|
||||||
|
|
||||||
col = bpy.data.collections.get(col_name)
|
col = bpy.data.collections.get(col_name)
|
||||||
if not col:
|
if not col:
|
||||||
col = bpy.data.collections.new(col_name)
|
col = bpy.data.collections.new(col_name)
|
||||||
|
@ -278,6 +285,6 @@ class BW_ctx:
|
||||||
# ops_data = getattr(bpy.ops, ctx.id_name)
|
# ops_data = getattr(bpy.ops, ctx.id_name)
|
||||||
# getattr(ops_data, op)()
|
# getattr(ops_data, op)()
|
||||||
|
|
||||||
sys.modules.update({"bone_widget.ctx": BW_ctx()})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ def bounds_2d_co(coords, width, height):
|
||||||
|
|
||||||
co_2d = [space_2d(region, rv3d, co) for co in coords]
|
co_2d = [space_2d(region, rv3d, co) for co in coords]
|
||||||
|
|
||||||
|
print("co_2d", co_2d)
|
||||||
|
|
||||||
x_value = sorted(co_2d, key=lambda x:x[0])
|
x_value = sorted(co_2d, key=lambda x:x[0])
|
||||||
y_value = sorted(co_2d, key=lambda x:x[1])
|
y_value = sorted(co_2d, key=lambda x:x[1])
|
||||||
|
|
||||||
|
@ -54,6 +56,9 @@ def render_widget(shape, filepath, width=32, height=32) :
|
||||||
bm = bmesh.new()
|
bm = bmesh.new()
|
||||||
bm.from_object(shape, dg)
|
bm.from_object(shape, dg)
|
||||||
|
|
||||||
|
width *= 2
|
||||||
|
height *= 2
|
||||||
|
|
||||||
coords = [shape.matrix_world @ v.co for v in bm.verts]
|
coords = [shape.matrix_world @ v.co for v in bm.verts]
|
||||||
coords = bounds_2d_co(coords, width, height)
|
coords = bounds_2d_co(coords, width, height)
|
||||||
|
|
||||||
|
@ -66,45 +71,53 @@ def render_widget(shape, filepath, width=32, height=32) :
|
||||||
batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
|
batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
|
||||||
|
|
||||||
with offscreen.bind():
|
with offscreen.bind():
|
||||||
bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
|
fb = gpu.state.active_framebuffer_get()
|
||||||
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
|
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||||
with gpu.matrix.push_pop():
|
with gpu.matrix.push_pop():
|
||||||
# reset matrices -> use normalized device coordinates [-1, 1]
|
# reset matrices -> use normalized device coordinates [-1, 1]
|
||||||
gpu.matrix.load_matrix(Matrix.Identity(4))
|
gpu.matrix.load_matrix(Matrix.Identity(4))
|
||||||
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
|
||||||
|
|
||||||
bgl.glLineWidth(4)
|
|
||||||
bgl.glEnable( bgl.GL_LINE_SMOOTH )
|
|
||||||
bgl.glEnable(bgl.GL_BLEND)
|
|
||||||
|
|
||||||
shader.bind()
|
shader.bind()
|
||||||
shader.uniform_float("color", (0, 0, 0, 0.1))
|
gpu.state.line_width_set(4*2)
|
||||||
|
#bgl.glEnable(bgl.GL_BLEND)
|
||||||
|
#bgl.glEnable( bgl.GL_LINE_SMOOTH )
|
||||||
|
shader.uniform_float("color", (0, 0, 0, 0.2))
|
||||||
batch.draw(shader)
|
batch.draw(shader)
|
||||||
|
|
||||||
bgl.glLineWidth(2)
|
gpu.state.line_width_set(2*2)
|
||||||
shader.uniform_float("color", (0.85, 0.85, 0.85, 1))
|
shader.uniform_float("color", (0.85, 0.85, 0.85, 1))
|
||||||
batch.draw(shader)
|
batch.draw(shader)
|
||||||
|
|
||||||
buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4)
|
buffer = fb.read_color(0, 0, width, height, 4, 0, 'FLOAT')
|
||||||
bgl.glReadBuffer(bgl.GL_BACK)
|
buffer.dimensions = width * height * 4
|
||||||
bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
|
#buffer = bgl.Buffer(bgl.GL_BYTE, width * height * 4)
|
||||||
|
#bgl.glReadBuffer(bgl.GL_BACK)
|
||||||
|
#bgl.glReadPixels(0, 0, width, height, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
|
||||||
|
|
||||||
offscreen.free()
|
offscreen.free()
|
||||||
|
|
||||||
#icon_name = '.' + shape.name + '_icon.png'
|
#icon_name = '.' + shape.name + '_icon.png'
|
||||||
icon_name = shape.name + '_icon.png'
|
icon_name = f'.{shape.name}_icon.png'
|
||||||
image = bpy.data.images.get(icon_name)
|
image = bpy.data.images.get(icon_name)
|
||||||
|
|
||||||
if image:
|
if image:
|
||||||
bpy.data.images.remove(image)
|
bpy.data.images.remove(image)
|
||||||
|
|
||||||
image = bpy.data.images.new(icon_name, width, height)
|
image = bpy.data.images.new(icon_name, width, height, alpha=True, float_buffer=True)
|
||||||
|
|
||||||
#image_data = np.asarray(buffer, dtype=np.uint8)
|
#image_data = np.asarray(buffer, dtype=np.uint8)
|
||||||
#image.pixels.foreach_set(image_data.flatten()/255)
|
#image.pixels.foreach_set(image_data.flatten()/255)
|
||||||
|
|
||||||
#image_data = np.asarray(buffer, dtype=np.uint8)
|
#image_data = np.asarray(buffer, dtype=np.uint8)
|
||||||
image.pixels = [v / 255 for v in buffer]
|
image.pixels.foreach_set(buffer)
|
||||||
|
|
||||||
image.save_render(str(filepath))
|
image.scale(int(width/2), int(height/2))
|
||||||
|
|
||||||
|
image.filepath_raw = str(filepath)
|
||||||
|
|
||||||
|
image.save()
|
||||||
|
|
||||||
|
bpy.data.images.remove(image)
|
||||||
|
|
||||||
|
|
107
operators.py
|
@ -8,7 +8,7 @@ from bone_widget import ctx
|
||||||
from .transform_utils import transform_matrix, apply_mat_to_verts, get_bone_size_factor, \
|
from .transform_utils import transform_matrix, apply_mat_to_verts, get_bone_size_factor, \
|
||||||
get_bone_matrix
|
get_bone_matrix
|
||||||
from .icon_utils import render_widget
|
from .icon_utils import render_widget
|
||||||
from .shape_utils import get_clean_shape, symmetrize_bone_shape, link_to_col, get_bone
|
from .shape_utils import get_clean_shape, symmetrize_bone_shape, link_to_col, get_bone, custom_shape_matrix
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -18,7 +18,7 @@ from mathutils import Matrix
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_copy_widgets(Operator) :
|
class BW_OT_copy_widgets(Operator):
|
||||||
bl_idname = 'bonewidget.copy_widgets'
|
bl_idname = 'bonewidget.copy_widgets'
|
||||||
bl_label = "Copy Widgets"
|
bl_label = "Copy Widgets"
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ class BW_OT_copy_widgets(Operator) :
|
||||||
else:
|
else:
|
||||||
bones = ctx.bones
|
bones = ctx.bones
|
||||||
|
|
||||||
|
|
||||||
for b in bones:
|
for b in bones:
|
||||||
if b.custom_shape:
|
if b.custom_shape:
|
||||||
s = b.custom_shape.copy()
|
s = b.custom_shape.copy()
|
||||||
|
@ -90,7 +89,7 @@ class BW_OT_copy_widgets(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_paste_widgets(Operator) :
|
class BW_OT_paste_widgets(Operator):
|
||||||
bl_idname = 'bonewidget.paste_widgets'
|
bl_idname = 'bonewidget.paste_widgets'
|
||||||
bl_label = "Paste Widgets"
|
bl_label = "Paste Widgets"
|
||||||
|
|
||||||
|
@ -174,7 +173,7 @@ class BW_OT_paste_widgets(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_remove_unused_shape(Operator) :
|
class BW_OT_remove_unused_shape(Operator):
|
||||||
bl_idname = 'bonewidget.remove_unused_shape'
|
bl_idname = 'bonewidget.remove_unused_shape'
|
||||||
bl_label = "Remove Unused Shape"
|
bl_label = "Remove Unused Shape"
|
||||||
|
|
||||||
|
@ -187,7 +186,7 @@ class BW_OT_remove_unused_shape(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_auto_color(Operator) :
|
class BW_OT_auto_color(Operator):
|
||||||
bl_idname = 'bonewidget.auto_color'
|
bl_idname = 'bonewidget.auto_color'
|
||||||
bl_label = "Auto Color"
|
bl_label = "Auto Color"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
@ -210,26 +209,26 @@ class BW_OT_auto_color(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_load_default_color(Operator) :
|
class BW_OT_load_default_color(Operator):
|
||||||
bl_idname = 'bonewidget.load_default_color'
|
bl_idname = 'bonewidget.load_default_color'
|
||||||
bl_label = "Load Default Color"
|
bl_label = "Load Default Color"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
select_color : FloatVectorProperty(name='Color', subtype='COLOR', default=[0.0, 1.0, 1.0])
|
select_color: FloatVectorProperty(name='Color', subtype='COLOR', default=[0.0, 1.0, 1.0])
|
||||||
active_color : FloatVectorProperty(name='Color', subtype='COLOR', default=[1.0, 1.0, 1.0])
|
active_color: FloatVectorProperty(name='Color', subtype='COLOR', default=[1.0, 1.0, 1.0])
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
ob = context.object
|
ob = context.object
|
||||||
|
|
||||||
colors = {
|
colors = {
|
||||||
'root': [0, 0, 0],
|
'Black': [0, 0, 0],
|
||||||
'spine chest hips': [1, 1, 0],
|
'Yellow': [1, 1, 0],
|
||||||
'.R': [0, 0.035, 0.95],
|
'Red': [0, 0.035, 0.95],
|
||||||
'.L': [1, 0, 0],
|
'Blue': [1, 0, 0],
|
||||||
'ik.R': [1, 0.1, 0.85],
|
'Pink': [1, 0.1, 0.85],
|
||||||
'ik.L': [0.67, 0, 0.87],
|
'Purple': [0.67, 0, 0.87],
|
||||||
'tweak.L': [0.75, 0.65, 0],
|
'Brown': [0.75, 0.65, 0],
|
||||||
'tweak.R': [1, 0.6, 0],
|
'Orange': [1, 0.6, 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v in colors.items():
|
for k, v in colors.items():
|
||||||
|
@ -244,10 +243,10 @@ class BW_OT_load_default_color(Operator) :
|
||||||
bone_group.colors.select = self.select_color
|
bone_group.colors.select = self.select_color
|
||||||
bone_group.colors.active = self.active_color
|
bone_group.colors.active = self.active_color
|
||||||
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class BW_OT_copy_bone_groups(Operator) :
|
|
||||||
|
class BW_OT_copy_bone_groups(Operator):
|
||||||
bl_idname = 'bonewidget.copy_bone_groups'
|
bl_idname = 'bonewidget.copy_bone_groups'
|
||||||
bl_label = "Copy Bone Groups"
|
bl_label = "Copy Bone Groups"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
@ -265,23 +264,22 @@ class BW_OT_copy_bone_groups(Operator) :
|
||||||
for bg in ob.pose.bone_groups:
|
for bg in ob.pose.bone_groups:
|
||||||
bone_groups[bg.name] = {
|
bone_groups[bg.name] = {
|
||||||
'colors': [bg.colors.normal[:], bg.colors.select[:], bg.colors.active[:]],
|
'colors': [bg.colors.normal[:], bg.colors.select[:], bg.colors.active[:]],
|
||||||
'bones' : [b.name for b in ob.pose.bones if b.bone_group == bg]
|
'bones': [b.name for b in ob.pose.bones if b.bone_group == bg]
|
||||||
}
|
}
|
||||||
|
|
||||||
blend_file = Path(gettempdir()) / 'bw_copy_bone_groups.json'
|
blend_file = Path(gettempdir()) / 'bw_copy_bone_groups.json'
|
||||||
|
|
||||||
blend_file.write_text(json.dumps(bone_groups))
|
blend_file.write_text(json.dumps(bone_groups))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class BW_OT_paste_bone_groups(Operator) :
|
|
||||||
|
class BW_OT_paste_bone_groups(Operator):
|
||||||
bl_idname = 'bonewidget.paste_bone_groups'
|
bl_idname = 'bonewidget.paste_bone_groups'
|
||||||
bl_label = "Paste Bone Groups"
|
bl_label = "Paste Bone Groups"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
clear : BoolProperty(default=False)
|
clear: BoolProperty(default=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(self, context):
|
def poll(self, context):
|
||||||
|
@ -316,7 +314,7 @@ class BW_OT_paste_bone_groups(Operator) :
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
class BW_OT_add_folder(Operator) :
|
class BW_OT_add_folder(Operator):
|
||||||
bl_idname = 'bonewidget.add_folder'
|
bl_idname = 'bonewidget.add_folder'
|
||||||
bl_label = "Add Folder"
|
bl_label = "Add Folder"
|
||||||
|
|
||||||
|
@ -327,12 +325,12 @@ class BW_OT_add_folder(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_remove_folder(Operator) :
|
class BW_OT_remove_folder(Operator):
|
||||||
bl_idname = 'bonewidget.remove_folder'
|
bl_idname = 'bonewidget.remove_folder'
|
||||||
bl_label = "Remove Folder"
|
bl_label = "Remove Folder"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
index : IntProperty()
|
index: IntProperty()
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
|
|
||||||
|
@ -348,7 +346,7 @@ class BW_OT_remove_folder(Operator) :
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_refresh_folders(Operator) :
|
class BW_OT_refresh_folders(Operator):
|
||||||
bl_idname = 'bonewidget.refresh_folders'
|
bl_idname = 'bonewidget.refresh_folders'
|
||||||
bl_label = "Refresh"
|
bl_label = "Refresh"
|
||||||
|
|
||||||
|
@ -364,7 +362,7 @@ class BW_OT_rename_folder(Operator):
|
||||||
bl_label = "Rename Folder"
|
bl_label = "Rename Folder"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
name : StringProperty(name='Name')
|
name: StringProperty(name='Name')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -384,6 +382,7 @@ class BW_OT_rename_folder(Operator):
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_show_preferences(Operator):
|
class BW_OT_show_preferences(Operator):
|
||||||
|
"""Display the preferences to the tab panel"""
|
||||||
bl_idname = 'bonewidget.show_preferences'
|
bl_idname = 'bonewidget.show_preferences'
|
||||||
bl_label = "Show Preferences"
|
bl_label = "Show Preferences"
|
||||||
bl_options = {'REGISTER'}
|
bl_options = {'REGISTER'}
|
||||||
|
@ -394,11 +393,12 @@ class BW_OT_show_preferences(Operator):
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_transform_widget(Operator):
|
class BW_OT_transform_widget(Operator):
|
||||||
|
"""Transform the Rotation Location or Scale of the selected shapes"""
|
||||||
bl_idname = 'bonewidget.transform_widget'
|
bl_idname = 'bonewidget.transform_widget'
|
||||||
bl_label = "Transfom"
|
bl_label = "Transfom"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
symmetrize : BoolProperty(name='Symmetrize', default=True)
|
symmetrize: BoolProperty(name='Symmetrize', default=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
@ -410,11 +410,16 @@ class BW_OT_transform_widget(Operator):
|
||||||
|
|
||||||
|
|
||||||
class BW_OT_create_widget(Operator):
|
class BW_OT_create_widget(Operator):
|
||||||
|
"""Create the widget shape and assign it to the bone"""
|
||||||
bl_idname = 'bonewidget.create_widget'
|
bl_idname = 'bonewidget.create_widget'
|
||||||
bl_label = "Create Widget"
|
bl_label = "Create Widget"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
symmetrize : BoolProperty(name='Symmetrize', default=True)
|
symmetrize: BoolProperty(name='Symmetrize', default=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return ctx.bone and ctx.active_widget
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
self.symmetrize = ctx.prefs.symmetrize
|
self.symmetrize = ctx.prefs.symmetrize
|
||||||
|
@ -429,7 +434,7 @@ class BW_OT_create_widget(Operator):
|
||||||
shape = data_src.objects[0]
|
shape = data_src.objects[0]
|
||||||
|
|
||||||
for bone in ctx.selected_bones:
|
for bone in ctx.selected_bones:
|
||||||
shape_copy = shape.copy()
|
#shape_copy = shape.copy()
|
||||||
|
|
||||||
if bpy.app.version_string < '3.0.0':
|
if bpy.app.version_string < '3.0.0':
|
||||||
bone.custom_shape_scale = 1.0
|
bone.custom_shape_scale = 1.0
|
||||||
|
@ -443,7 +448,7 @@ class BW_OT_create_widget(Operator):
|
||||||
|
|
||||||
#copy_shape = shape.copy()
|
#copy_shape = shape.copy()
|
||||||
#copy_shape.data = copy_shape.data.copy()
|
#copy_shape.data = copy_shape.data.copy()
|
||||||
bone.custom_shape = get_clean_shape(bone, shape_copy, col=ctx.widget_col, prefix=ctx.prefs.prefix, separate=False)
|
bone.custom_shape = get_clean_shape(bone, shape, col=ctx.widget_col, prefix=ctx.prefs.prefix)
|
||||||
|
|
||||||
if self.symmetrize:
|
if self.symmetrize:
|
||||||
symmetrize_bone_shape(bone, prefix=ctx.prefs.prefix)
|
symmetrize_bone_shape(bone, prefix=ctx.prefs.prefix)
|
||||||
|
@ -460,7 +465,7 @@ class BW_OT_match_transform(Operator):
|
||||||
bl_label = "Match Transforms"
|
bl_label = "Match Transforms"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
relative : BoolProperty(default=False)
|
relative: BoolProperty(default=False)
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
for bone in ctx.selected_bones:
|
for bone in ctx.selected_bones:
|
||||||
|
@ -518,7 +523,7 @@ class BW_OT_return_to_rig(Operator):
|
||||||
bl_label = "Return to rig"
|
bl_label = "Return to rig"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
symmetrize : BoolProperty(name='Symmetrize', default=True)
|
symmetrize: BoolProperty(name='Symmetrize', default=True)
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
self.symmetrize = ctx.prefs.symmetrize
|
self.symmetrize = ctx.prefs.symmetrize
|
||||||
|
@ -560,7 +565,7 @@ class BW_OT_symmetrize_widget(Operator):
|
||||||
bl_label = "Symmetrize"
|
bl_label = "Symmetrize"
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
match_transform : BoolProperty(True)
|
match_transform: BoolProperty(True)
|
||||||
|
|
||||||
def get_name_side(self, name, fallback=None):
|
def get_name_side(self, name, fallback=None):
|
||||||
if name.lower().endswith('.l'):
|
if name.lower().endswith('.l'):
|
||||||
|
@ -569,24 +574,24 @@ class BW_OT_symmetrize_widget(Operator):
|
||||||
return 'RIGHT'
|
return 'RIGHT'
|
||||||
return fallback
|
return fallback
|
||||||
|
|
||||||
def mirror_name(self, name) :
|
def mirror_name(self, name):
|
||||||
mirror = None
|
mirror = None
|
||||||
|
|
||||||
match = {
|
match = {
|
||||||
'R' : 'L',
|
'R': 'L',
|
||||||
'r' : 'l',
|
'r': 'l',
|
||||||
'L' : 'R',
|
'L': 'R',
|
||||||
'l' : 'r',
|
'l': 'r',
|
||||||
}
|
}
|
||||||
|
|
||||||
separator = ['.', '_']
|
separator = ['.', '_']
|
||||||
|
|
||||||
if name.startswith(tuple(match.keys())):
|
if name.startswith(tuple(match.keys())):
|
||||||
if name[1] in separator :
|
if name[1] in separator:
|
||||||
mirror = match[name[0]] + name[1:]
|
mirror = match[name[0]] + name[1:]
|
||||||
|
|
||||||
if name.endswith(tuple(match.keys())):
|
if name.endswith(tuple(match.keys())):
|
||||||
if name[-2] in separator :
|
if name[-2] in separator:
|
||||||
mirror = name[:-1] + match[name[-1]]
|
mirror = name[:-1] + match[name[-1]]
|
||||||
|
|
||||||
return mirror
|
return mirror
|
||||||
|
@ -648,9 +653,19 @@ class BW_OT_add_widget(Operator):
|
||||||
widget_path.parent.mkdir(exist_ok=True, parents=True)
|
widget_path.parent.mkdir(exist_ok=True, parents=True)
|
||||||
bpy.data.libraries.write(str(widget_path), {shape})
|
bpy.data.libraries.write(str(widget_path), {shape})
|
||||||
|
|
||||||
render_widget(shape, icon_path)
|
# Copy the shape to apply the bone matrix to the mesh
|
||||||
widget = folder.add_widget(name)
|
shape_copy = shape.copy()
|
||||||
|
shape_copy.data = shape_copy.data.copy()
|
||||||
|
|
||||||
|
shape_copy.matrix_world = get_bone_matrix(bone)
|
||||||
|
|
||||||
|
mat = custom_shape_matrix(bone)
|
||||||
|
shape_copy.data.transform(mat)
|
||||||
|
|
||||||
|
render_widget(shape_copy, icon_path)
|
||||||
|
folder.add_widget(name)
|
||||||
|
|
||||||
|
bpy.data.objects.remove(shape_copy)
|
||||||
|
|
||||||
bpy.context.area.tag_redraw()
|
bpy.context.area.tag_redraw()
|
||||||
|
|
||||||
|
@ -681,7 +696,7 @@ class BW_OT_clean_widget(Operator):
|
||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
all: BoolProperty(name='All', default=False)
|
all: BoolProperty(name='All', default=False)
|
||||||
symmetrize : BoolProperty(name='Symmetrize', default=True)
|
symmetrize: BoolProperty(name='Symmetrize', default=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
|
|
@ -19,7 +19,7 @@ from .shape_utils import symmetrize_bone_shape, get_flipped_bone
|
||||||
def undo_redo(self, context):
|
def undo_redo(self, context):
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
op_names = ('transform_widget','create_widget', 'match_transform', 'clean_widget')
|
op_names = ('transform_widget','create_widget', 'match_transform', 'clean_widget')
|
||||||
op_ids = [ctx.get_op_id(o) for o in op_ids]
|
op_ids = [ctx.get_op_id(o) for o in op_names]
|
||||||
|
|
||||||
if (ops and ops[-1].bl_idname in op_ids):
|
if (ops and ops[-1].bl_idname in op_ids):
|
||||||
bpy.ops.wm.undo()
|
bpy.ops.wm.undo()
|
||||||
|
@ -44,17 +44,17 @@ def transform_widgets(self, context):
|
||||||
|
|
||||||
|
|
||||||
class BW_PG_transforms(PropertyGroup):
|
class BW_PG_transforms(PropertyGroup):
|
||||||
size : FloatProperty(name='Size', default=1.0, min=0, update=transform_widgets)
|
size: FloatProperty(name='Size', default=1.0, min=0, update=transform_widgets)
|
||||||
xz_scale : FloatProperty(name='XZ Scale', default=1.0, min=0, update=transform_widgets)
|
xz_scale: FloatProperty(name='XZ Scale', default=1.0, min=0, update=transform_widgets)
|
||||||
slide : FloatProperty(name='Slide', default=0.0, update=transform_widgets)
|
slide: FloatProperty(name='Slide', default=0.0, update=transform_widgets)
|
||||||
|
|
||||||
loc : FloatVectorProperty(name='Location', default=(0.0, 0.0, 0.0),
|
loc: FloatVectorProperty(name='Location', default=(0.0, 0.0, 0.0),
|
||||||
subtype='TRANSLATION', update=transform_widgets)
|
subtype='TRANSLATION', update=transform_widgets)
|
||||||
|
|
||||||
rot : FloatVectorProperty(name = 'Rotation', default=(0.0, 0.0, 0.0),
|
rot: FloatVectorProperty(name = 'Rotation', default=(0.0, 0.0, 0.0),
|
||||||
subtype='EULER', step=100, precision=0, update=transform_widgets)
|
subtype='EULER', step=100, precision=0, update=transform_widgets)
|
||||||
|
|
||||||
scale : FloatVectorProperty(name='Scale', default=(1.0, 1.0, 1.0),
|
scale: FloatVectorProperty(name='Scale', default=(1.0, 1.0, 1.0),
|
||||||
subtype='XYZ', update=transform_widgets)
|
subtype='XYZ', update=transform_widgets)
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,16 +62,19 @@ def rename_widget(self, context):
|
||||||
ctx.active_folder.rename_widget(self, self.name)
|
ctx.active_folder.rename_widget(self, self.name)
|
||||||
|
|
||||||
class BW_PG_widget(PropertyGroup):
|
class BW_PG_widget(PropertyGroup):
|
||||||
name : StringProperty(update=rename_widget)
|
name: StringProperty(update=rename_widget)
|
||||||
#path : StringProperty(subtype='FILE_PATH')
|
source_bone: StringProperty()
|
||||||
|
#path: StringProperty(subtype='FILE_PATH')
|
||||||
|
|
||||||
|
def refresh(self, context):
|
||||||
|
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')
|
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
|
@property
|
||||||
def abspath(self):
|
def abspath(self):
|
||||||
|
@ -82,28 +85,33 @@ class BW_PG_folder(PropertyGroup):
|
||||||
return Path(self.path).name
|
return Path(self.path).name
|
||||||
|
|
||||||
def load_icon(self, widget):
|
def load_icon(self, widget):
|
||||||
icon = self.get_widget_icon(widget)
|
|
||||||
|
icon_name = self.get_icon_name(widget)
|
||||||
|
icon = self.icons.get(icon_name)
|
||||||
if icon:
|
if icon:
|
||||||
icon.reload()
|
icon.reload()
|
||||||
else :
|
else:
|
||||||
icon_path = self.get_icon_path(widget)
|
icon_path = self.get_icon_path(widget)
|
||||||
self.icons.load(widget.name, str(icon_path), 'IMAGE', True)
|
self.icons.load(icon_name, str(icon_path), 'IMAGE', True)
|
||||||
|
|
||||||
|
def get_icon_name(self, widget):
|
||||||
|
return f'{Path(self.path).stem}_{widget.name}'
|
||||||
|
|
||||||
def get_widget_icon(self, widget):
|
def get_widget_icon(self, widget):
|
||||||
return self.icons.get(widget.name)
|
return self.icons.get(self.get_icon_name(widget))
|
||||||
|
|
||||||
def add_widget(self, name):
|
def add_widget(self, name):
|
||||||
name = self.get_widget_display_name(name)
|
name = self.get_widget_display_name(name)
|
||||||
w = self.widgets.get(name)
|
w = self.widgets.get(name)
|
||||||
if w:
|
if w:
|
||||||
self.load_icon(w)
|
self.load_icon(w)
|
||||||
|
self.active_widget = w
|
||||||
return
|
return
|
||||||
|
|
||||||
w = self.widgets.add()
|
w = self.widgets.add()
|
||||||
w.name = name
|
w.name = name
|
||||||
|
|
||||||
self.active_widget = w
|
self.active_widget = w
|
||||||
|
|
||||||
self.load_icon(w)
|
self.load_icon(w)
|
||||||
|
|
||||||
return w
|
return w
|
||||||
|
@ -194,25 +202,25 @@ class BW_PG_bone_color(PropertyGroup):
|
||||||
class BW_prefs(AddonPreferences):
|
class BW_prefs(AddonPreferences):
|
||||||
bl_idname = __package__
|
bl_idname = __package__
|
||||||
|
|
||||||
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()
|
||||||
folder_enum : EnumProperty(name='Folders', items=lambda s,c : ctx.folder_items)
|
folder_enum: EnumProperty(name='Folders', items=lambda s,c: ctx.folder_items)
|
||||||
collection : StringProperty(name='Collection', default='Widget')
|
collection: StringProperty(name='Collection', default='Widgets', description='Name of the widget collection use {ob.name} to include the name of the rig')
|
||||||
prefix : StringProperty(name='Prefix', default='WGT-')
|
prefix: StringProperty(name='Prefix', default='WGT-', description='Prefix for the shape object and data name')
|
||||||
category : StringProperty(name='Tab', default='Rigging', update=lambda s,c : update_tab())
|
category: StringProperty(name='Tab', default='Rigging', update=lambda s,c: update_tab())
|
||||||
|
|
||||||
symmetrize : BoolProperty(name='Symmetrize', default=True, update=undo_redo)
|
symmetrize: BoolProperty(name='Symmetrize', default=True, update=undo_redo)
|
||||||
separate : BoolProperty(default=True, name="Separate", update=undo_redo)
|
separate: BoolProperty(default=True, name="Separate", update=undo_redo)
|
||||||
match_transform : BoolProperty(default=True, name="Match Transform", update=undo_redo)
|
match_transform: BoolProperty(default=True, name="Match Transform", update=undo_redo)
|
||||||
rename : BoolProperty(default=True, name="Rename", update=undo_redo)
|
rename: BoolProperty(default=True, name="Rename", update=undo_redo)
|
||||||
|
|
||||||
show_transforms : BoolProperty(default=False)
|
show_transforms: BoolProperty(default=False)
|
||||||
transforms : PointerProperty(type=BW_PG_transforms)
|
transforms: PointerProperty(type=BW_PG_transforms)
|
||||||
|
|
||||||
grid_view : BoolProperty(name='Grid View', default=True)
|
#grid_view: BoolProperty(name='Grid View', default=True)
|
||||||
|
|
||||||
#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 draw(self, context):
|
def draw(self, context):
|
||||||
draw_prefs(self.layout)
|
draw_prefs(self.layout)
|
||||||
|
@ -231,6 +239,8 @@ classes = (
|
||||||
def register():
|
def register():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
|
#bpy.types.Armature.widget_collection = PointerProperty(type=bpy.types.Collection)
|
||||||
|
|
||||||
#update_folder_items()
|
#update_folder_items()
|
||||||
|
|
||||||
|
@ -240,6 +250,7 @@ def unregister():
|
||||||
#for f in ctx.folders:
|
#for f in ctx.folders:
|
||||||
# bpy.utils.previews.remove(f.icons)
|
# bpy.utils.previews.remove(f.icons)
|
||||||
|
|
||||||
|
#del bpy.types.Armature.widget_collection
|
||||||
|
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from .transform_utils import get_bone_matrix, transform_matrix
|
from .transform_utils import get_bone_matrix, transform_matrix
|
||||||
|
from mathutils import Matrix
|
||||||
#from bone_widget import ctx
|
#from bone_widget import ctx
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,26 +74,42 @@ def link_to_col(shape, col):
|
||||||
|
|
||||||
col.objects.link(shape)
|
col.objects.link(shape)
|
||||||
|
|
||||||
def get_clean_shape(bone, shape, separate=True, rename=True,
|
def custom_shape_matrix(bone):
|
||||||
col=None, match=True, prefix='', apply_transforms=True):
|
loc = bone.custom_shape_translation.copy()
|
||||||
|
rot = bone.custom_shape_rotation_euler.copy()
|
||||||
|
scale = bone.custom_shape_scale_xyz.copy()
|
||||||
|
|
||||||
old_shape = shape
|
if bone.use_custom_shape_bone_size:
|
||||||
old_bone = get_bone(old_shape)
|
loc /= bone.bone.length
|
||||||
bone.custom_shape = None
|
else:
|
||||||
|
scale /= bone.bone.length
|
||||||
|
|
||||||
|
return Matrix.LocRotScale(loc, rot, scale)
|
||||||
|
|
||||||
|
def get_clean_shape(bone, shape, separate=True, rename=True,
|
||||||
|
col=None, match=True, prefix='', apply_transforms=True):
|
||||||
|
|
||||||
|
#bone.custom_shape = None
|
||||||
|
|
||||||
|
#Remove bone shape if no other bone are using it
|
||||||
|
if bone.custom_shape:
|
||||||
|
old_bones = get_bones(bone.custom_shape)
|
||||||
|
old_bones.remove(bone)
|
||||||
|
|
||||||
|
print('old_bones', old_bones)
|
||||||
|
|
||||||
|
if old_bones:
|
||||||
|
rename_shape(bone.custom_shape, old_bones[0], prefix=prefix)
|
||||||
|
elif bone.custom_shape != shape:
|
||||||
|
bpy.data.objects.remove(bone.custom_shape)
|
||||||
|
|
||||||
if separate:
|
if separate:
|
||||||
if old_bone:
|
|
||||||
rename_shape(old_shape, old_bone, prefix=prefix)
|
|
||||||
else:
|
|
||||||
bpy.data.objects.remove(old_shape)
|
|
||||||
|
|
||||||
shape = shape.copy()
|
shape = shape.copy()
|
||||||
shape.data = shape.data.copy()
|
shape.data = shape.data.copy()
|
||||||
|
|
||||||
bone.custom_shape = shape
|
bone.custom_shape = shape
|
||||||
|
|
||||||
if match:
|
|
||||||
shape.matrix_world = get_bone_matrix(bone)
|
|
||||||
|
|
||||||
if apply_transforms:
|
if apply_transforms:
|
||||||
if bpy.app.version_string < '3.0.0':
|
if bpy.app.version_string < '3.0.0':
|
||||||
|
@ -108,23 +125,19 @@ col=None, match=True, prefix='', apply_transforms=True):
|
||||||
bone.custom_shape_scale = 1
|
bone.custom_shape_scale = 1
|
||||||
#mirror_bone.custom_shape_scale =
|
#mirror_bone.custom_shape_scale =
|
||||||
else:
|
else:
|
||||||
loc = bone.custom_shape_translation
|
|
||||||
rot = bone.custom_shape_rotation_euler
|
|
||||||
scale = bone.custom_shape_scale_xyz
|
|
||||||
|
|
||||||
if not bone.use_custom_shape_bone_size:
|
|
||||||
scale /= bone.bone.length
|
|
||||||
|
|
||||||
mat = transform_matrix(loc=loc, rot=rot, scale=scale)
|
|
||||||
|
|
||||||
|
mat = custom_shape_matrix(bone)
|
||||||
shape.data.transform(mat)
|
shape.data.transform(mat)
|
||||||
|
|
||||||
bone.custom_shape_translation = 0, 0, 0
|
bone.custom_shape_translation = (0, 0, 0)
|
||||||
bone.custom_shape_rotation_euler = 0, 0, 0
|
bone.custom_shape_rotation_euler = (0, 0, 0)
|
||||||
bone.custom_shape_scale_xyz = 1, 1, 1
|
bone.custom_shape_scale_xyz = (1, 1, 1)
|
||||||
|
|
||||||
bone.use_custom_shape_bone_size = True
|
bone.use_custom_shape_bone_size = True
|
||||||
|
|
||||||
|
if match:
|
||||||
|
shape.matrix_world = get_bone_matrix(bone)
|
||||||
|
|
||||||
if rename:
|
if rename:
|
||||||
rename_shape(shape, bone, prefix=prefix)
|
rename_shape(shape, bone, prefix=prefix)
|
||||||
|
|
||||||
|
@ -134,10 +147,14 @@ col=None, match=True, prefix='', apply_transforms=True):
|
||||||
return shape
|
return shape
|
||||||
|
|
||||||
|
|
||||||
def get_bone(shape):
|
def get_bones(shape):
|
||||||
armatures = [o for o in bpy.context.scene.objects if o.type == 'ARMATURE']
|
armatures = [o for o in bpy.context.scene.objects if o.type == 'ARMATURE']
|
||||||
return next((b for a in armatures for b in a.pose.bones if b.custom_shape == shape), None)
|
return [b for a in armatures for b in a.pose.bones if b.custom_shape == shape]
|
||||||
|
|
||||||
|
def get_bone(shape):
|
||||||
|
bones = get_bones(shape)
|
||||||
|
if bones:
|
||||||
|
return bones[0]
|
||||||
|
|
||||||
def symmetrize_bone_shape(bone, prefix=None):
|
def symmetrize_bone_shape(bone, prefix=None):
|
||||||
active_side = get_side(bone.name, 'LEFT')
|
active_side = get_side(bone.name, 'LEFT')
|
||||||
|
|
45
ui.py
|
@ -59,24 +59,26 @@ def add_color_row(layout, data=None, name='', index=0):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def draw_prefs(layout):
|
def draw_prefs(layout):
|
||||||
layout = layout.column(align=False)
|
|
||||||
|
|
||||||
add_row(layout, 'category', name='Tab', icon='COPY_ID')
|
box = layout.box()
|
||||||
add_row(layout, 'collection', name='Collection', icon='OUTLINER_COLLECTION')
|
col = box.column(align=False)
|
||||||
add_row(layout, 'prefix', name='Prefix', icon='SYNTAX_OFF')
|
|
||||||
|
|
||||||
layout.separator()
|
add_row(col, 'category', name='Tab', icon='COPY_ID')
|
||||||
|
add_row(col, 'collection', name='Collection', icon='OUTLINER_COLLECTION')
|
||||||
|
add_row(col, 'prefix', name='Prefix', icon='SYNTAX_OFF')
|
||||||
|
|
||||||
add_row(layout, 'path', data=ctx.prefs.default_folder, name='Folders',
|
col.separator()
|
||||||
|
|
||||||
|
add_row(col, 'path', data=ctx.prefs.default_folder, name='Folders',
|
||||||
icon='ADD', operator='bonewidget.add_folder')
|
icon='ADD', operator='bonewidget.add_folder')
|
||||||
|
|
||||||
for i, f in enumerate(ctx.prefs.folders):
|
for i, f in enumerate(ctx.prefs.folders):
|
||||||
add_row(layout, 'path', icon='REMOVE',
|
add_row(col, 'path', icon='REMOVE',
|
||||||
operator='bonewidget.remove_folder', data=f, properties={'index': i})
|
operator='bonewidget.remove_folder', data=f, properties={'index': i})
|
||||||
|
|
||||||
layout.separator()
|
col.separator()
|
||||||
|
|
||||||
split = layout.split(factor=0.33, align=True)
|
split = col.split(factor=0.33, align=True)
|
||||||
split.alignment= 'RIGHT'
|
split.alignment= 'RIGHT'
|
||||||
split.label(text='Auto:')
|
split.label(text='Auto:')
|
||||||
|
|
||||||
|
@ -88,6 +90,10 @@ def draw_prefs(layout):
|
||||||
add_bool_row(col, 'match_transform', name='Match Transform', icon='TRANSFORM_ORIGINS')
|
add_bool_row(col, 'match_transform', name='Match Transform', icon='TRANSFORM_ORIGINS')
|
||||||
add_bool_row(col, 'rename', name='Rename', icon='SYNTAX_OFF')
|
add_bool_row(col, 'rename', name='Rename', icon='SYNTAX_OFF')
|
||||||
|
|
||||||
|
#bpy.ops.wm.save_userpref()
|
||||||
|
prefs_unsaved = bpy.context.preferences.is_dirty
|
||||||
|
layout.operator('wm.save_userpref', text="Save Preferences" + (" *" if prefs_unsaved else ""))
|
||||||
|
|
||||||
#col.prop(ctx.prefs, 'symmetrize', text='Symetrize', icon='MOD_MIRROR')
|
#col.prop(ctx.prefs, 'symmetrize', text='Symetrize', icon='MOD_MIRROR')
|
||||||
#col.prop(ctx.prefs, 'separate', text='Separate', icon='UNLINKED')
|
#col.prop(ctx.prefs, 'separate', text='Separate', icon='UNLINKED')
|
||||||
#col.prop(ctx.prefs, 'match_transform', text='Match Transform', icon='TRANSFORM_ORIGINS')
|
#col.prop(ctx.prefs, 'match_transform', text='Match Transform', icon='TRANSFORM_ORIGINS')
|
||||||
|
@ -115,17 +121,14 @@ def draw_prefs(layout):
|
||||||
class BW_UL_widget(UIList):
|
class BW_UL_widget(UIList):
|
||||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
|
||||||
|
|
||||||
icon = data.icons.get(item.name)
|
icon = data.get_widget_icon(item)
|
||||||
icon_id = icon.icon_id if icon else -1
|
icon_id = icon.icon_id if icon else -1
|
||||||
|
|
||||||
#layout.scale_x = 1.5
|
#layout.scale_x = 1.5
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.use_property_split = False
|
||||||
|
|
||||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
row.prop(item, 'name', text="", emboss=False, icon_value=icon_id)
|
||||||
layout.prop(item, 'name', text="", emboss=False, icon_value=icon_id)
|
|
||||||
|
|
||||||
elif self.layout_type in {'GRID'}:
|
|
||||||
layout.alignment = 'CENTER'
|
|
||||||
layout.label(text="", icon_value=icon_id)
|
|
||||||
|
|
||||||
|
|
||||||
class BW_MT_folder(Menu):
|
class BW_MT_folder(Menu):
|
||||||
|
@ -142,7 +145,7 @@ class BW_MT_folder(Menu):
|
||||||
|
|
||||||
layout.operator('bonewidget.copy_widgets', icon='COPYDOWN')
|
layout.operator('bonewidget.copy_widgets', icon='COPYDOWN')
|
||||||
layout.operator('bonewidget.paste_widgets', icon='PASTEDOWN')
|
layout.operator('bonewidget.paste_widgets', icon='PASTEDOWN')
|
||||||
layout.prop(ctx.prefs, 'grid_view')
|
#layout.prop(ctx.prefs, 'grid_view')
|
||||||
|
|
||||||
|
|
||||||
class BW_PT_transforms(Panel):
|
class BW_PT_transforms(Panel):
|
||||||
|
@ -231,7 +234,7 @@ class BW_PT_main(Panel):
|
||||||
|
|
||||||
if folder:
|
if folder:
|
||||||
widget_col.template_list('BW_UL_widget', 'BW_widgets', folder, 'widgets', folder, 'widget_index',
|
widget_col.template_list('BW_UL_widget', 'BW_widgets', folder, 'widgets', folder, 'widget_index',
|
||||||
rows=5, columns=self.get_nb_col(context), type='GRID' if ctx.prefs.grid_view else 'DEFAULT')
|
rows=5, columns=self.get_nb_col(context), type='DEFAULT')
|
||||||
#widget_col.template_list('UI_UL_list', 'BW_widgets', folder, 'widgets', folder, 'widget_index', rows=4)
|
#widget_col.template_list('UI_UL_list', 'BW_widgets', folder, 'widgets', folder, 'widget_index', rows=4)
|
||||||
#layout.prop(self, 'folder_enum')
|
#layout.prop(self, 'folder_enum')
|
||||||
|
|
||||||
|
@ -267,13 +270,9 @@ class BW_PT_main(Panel):
|
||||||
#opt_col = layout.column()
|
#opt_col = layout.column()
|
||||||
|
|
||||||
elif ctx.show_prefs_op:
|
elif ctx.show_prefs_op:
|
||||||
layout.separator()
|
#layout.separator()
|
||||||
draw_prefs(layout)
|
draw_prefs(layout)
|
||||||
|
|
||||||
#bpy.ops.wm.save_userpref()
|
|
||||||
prefs_unsaved = context.preferences.is_dirty
|
|
||||||
layout.operator('wm.save_userpref', text="Save Preferences" + (" *" if prefs_unsaved else ""))
|
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
BW_UL_widget,
|
BW_UL_widget,
|
||||||
|
|
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 723 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |