bone_widget/context.py

294 lines
8.0 KiB
Python
Raw Normal View History

2022-10-28 23:23:06 +02:00
import sys
import bpy
from pathlib import Path
import os
from bone_widget.shape_utils import get_bone
2023-01-18 16:02:42 +01:00
class BW_context:
2022-10-28 23:23:06 +02:00
def __init__(self):
self.module_dir = Path(__file__).parent
self.module_name = self.module_dir.name
self.id_name = 'bonewidget'
self._rig = None
self._folder_items = []
self.shapes = {} # used to store vert co for the transform properties
@property
def addon(self):
from bpy import context
return context.preferences.addons[__package__]
@property
def prefs(self):
return self.addon.preferences
#def settings(self):
# return bpy.context.window_manager.
@property
def show_transforms(self):
ops = bpy.context.window_manager.operators
id_names = [self.get_op_id(o) for o in ('transform_widget','create_widget', 'match_transform')]
return (ops and ops[-1].bl_idname in id_names)
@property
def clean_widget_op(self):
ops = bpy.context.window_manager.operators
op_idname = self.get_op_id('clean_widget')
#transforms = self.prefs.transforms
if ops and ops[-1].bl_idname == op_idname:
return ops[-1]
2023-01-22 00:35:21 +01:00
# @property
# def show_prefs_op(self):
# ops = bpy.context.window_manager.operators
# id_names = [
# self.get_op_id('show_preferences'),
# self.get_op_id('add_folder'),
# self.get_op_id('remove_folder')
# ]
2022-10-28 23:23:06 +02:00
2023-01-22 00:35:21 +01:00
# #transforms = self.prefs.transforms
# if ops and ops[-1].bl_idname in id_names:
# return True
2022-10-28 23:23:06 +02:00
@property
def category(self):
if not self.prefs:
return 'Rig'
return self.prefs.category
@property
def rig(self):
bone = self.bone
if bone:
return bone.id_data
@property
def widget_col(self):
col_name = self.prefs.collection
2023-01-18 16:02:42 +01:00
col_name = col_name.format(ob=bpy.context.object)
2022-10-28 23:23:06 +02:00
col = bpy.data.collections.get(col_name)
if not col:
col = bpy.data.collections.new(col_name)
col.hide_viewport = True
if col not in self.get_scene_cols():
bpy.context.scene.collection.children.link(col)
return col
@property
def widget_layer_col(self):
return next((c for c in self.get_layer_cols() if c.collection == self.widget_col), None)
@property
def default_folder_path(self):
return self.prefs.default_folder.abspath
@property
def custom_folder_paths(self):
return [f.abspath for f in self.prefs.folders if f.path]
@property
def folder_paths(self):
return [self.default_folder_path] + self.custom_folder_paths
@property
def folders(self):
return list(self.prefs.folders) + [self.prefs.default_folder]
@property
def active_folder(self):
folder = self.abspath(self.prefs.folder_enum)
if folder == self.default_folder_path:
return self.prefs.default_folder
else:
return next((f for f in self.prefs.folders if f.abspath==folder), None)
@property
def active_widget(self):
folder = self.active_folder
if not folder:
return
index = folder.widget_index
return folder.active_widget
@property
def bone(self):
if not self.poll():
return
ob = bpy.context.object
if ob.type == 'ARMATURE':
return bpy.context.active_pose_bone
else:
return get_bone(ob)
@property
def bones(self):
ob = bpy.context.object
if ob.type == 'ARMATURE':
return list(ob.pose.bones)
else:
widgets = self.widgets
return [b for b in self.rig.pose.bones if b.custom_shape in widgets]
@property
def selected_bones(self):
if not self.poll():
return []
ob = bpy.context.object
if ob.type == 'ARMATURE':
2023-02-06 15:10:00 +01:00
return bpy.context.selected_pose_bones
#bones = ob.pose.bones
#return [b for b in bones if b.bone.select]
elif self.rig:
2022-10-28 23:23:06 +02:00
widgets = self.selected_widgets
return [b for b in self.rig.pose.bones if b.custom_shape in widgets]
2023-02-06 15:10:00 +01:00
return []
2022-10-28 23:23:06 +02:00
@property
def widget(self):
if not self.poll():
return
ob = bpy.context.object
if ob.type == 'ARMATURE':
if bpy.context.active_pose_bone:
return bpy.context.active_pose_bone.custom_shape
else:
return ob
@property
def widgets(self):
ob = bpy.context.object
if ob.type == 'ARMATURE':
return [b.custom_shape for b in self.bones if b.custom_shape]
@property
def selected_widgets(self):
if not self.poll():
return []
ob = bpy.context.object
if ob.type == 'ARMATURE':
bones = self.selected_bones
return [b.custom_shape for b in bones if b.custom_shape]
else:
objects = bpy.context.selected_objects
return [o for o in objects if o.select_get() and o.type in ('MESH', 'CURVE')]
@property
def folder_items(self):
for folder in self.folder_paths:
if not any(self.abspath(f[0])==folder for f in self._folder_items):
id = 0
if self._folder_items:
id = max([i[-1] for i in self._folder_items])+1
2023-10-03 11:59:40 +02:00
self._folder_items.append((str(folder), bpy.path.display_name(folder.name), '', '', id))
2022-10-28 23:23:06 +02:00
for f in reversed(self._folder_items):
if self.abspath(f[0]) not in self.folder_paths:
self._folder_items.remove(f)
return self._folder_items
def get_flipped_bone(self, bone):
pass
#def get_bone(self, shape):
# 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)
def get_scene_cols(self, col=None, children=None):
if children is None:
children = set()
if col is None:
col = bpy.context.scene.collection
for c in col.children:
children.add(c)
self.get_scene_cols(c, children)
return list(children)
def get_layer_cols(self, col=None, children=None):
if children is None:
children = set()
if col is None:
col = bpy.context.view_layer.layer_collection
for c in col.children:
children.add(c)
self.get_layer_cols(c, children)
return list(children)
def abspath(self, path):
if not path:
return
if path.startswith('//'):
path = './' + path[2:]
2023-10-03 11:59:40 +02:00
elif path.startswith('./') or not '/' in str(path):
path = self.module_dir/'widgets' / path
2022-10-28 23:23:06 +02:00
return Path(path).absolute().resolve()
def poll(self):
ob = bpy.context.object
if not ob:
return False
if ob.type == 'ARMATURE' and ob.mode == 'POSE':
return True
2023-02-06 15:10:00 +01:00
if ob.type in ('MESH', 'CURVE'):
2022-10-28 23:23:06 +02:00
return True
return False
def store_shapes(self):
self.shapes.clear()
for widget in self.selected_widgets:
coords = [0]*len(widget.data.vertices)*3
widget.data.vertices.foreach_get('co', coords)
self.shapes[widget] = coords
def reset_transforms(self):
transforms = self.prefs.transforms
transforms['size'] = 1
transforms['xz_scale'] = 1
transforms['slide'] = 0
transforms['loc'] = (0, 0, 0)
transforms['rot'] = (0, 0, 0)
transforms['scale'] = (1, 1, 1)
def init_transforms(self):
self.store_shapes()
self.reset_transforms()
def get_op_id(self, name):
return f'{self.id_name.upper()}_OT_{name}'
#def call(self, op):
# ops_data = getattr(bpy.ops, ctx.id_name)
# getattr(ops_data, op)()
2023-01-18 16:02:42 +01:00
2022-10-28 23:23:06 +02:00