refacto
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
|
||||
import bpy
|
||||
from .bl_utils import get_mat
|
||||
|
||||
def is_shape(ob):
|
||||
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.type in ('MESH', 'CURVE', 'FONT') and ob in shapes:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_object_color(ob):
|
||||
if not ob.data.materials:
|
||||
return
|
||||
|
||||
mat = get_mat(ob)
|
||||
if not mat or not mat.node_tree or not mat.node_tree.nodes:
|
||||
return
|
||||
|
||||
emit_node = mat.node_tree.nodes.get('Emission')
|
||||
if not emit_node:
|
||||
return
|
||||
|
||||
return emit_node.inputs['Color'].default_value
|
||||
|
||||
def get_operator_from_id(idname):
|
||||
if not '.' in idname:
|
||||
return
|
||||
|
||||
m, o = idname.split(".")
|
||||
try:
|
||||
op = getattr(getattr(bpy.ops, m), o)
|
||||
op.get_rna_type()
|
||||
except Exception:
|
||||
return
|
||||
|
||||
return op
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def get_view_3d_override():
|
||||
windows = bpy.context.window_manager.windows
|
||||
areas = [a for w in windows for a in w.screen.areas if a.type == 'VIEW_3D']
|
||||
|
||||
if not areas:
|
||||
print('No view 3d found')
|
||||
return
|
||||
|
||||
view_3d = None
|
||||
for area in areas:
|
||||
if area.spaces.active.camera:
|
||||
view_3d = area
|
||||
|
||||
if not view_3d:
|
||||
view_3d = max(areas, key=lambda x :x.width)
|
||||
|
||||
return {'area': view_3d, 'region': view_3d.regions[-1]}
|
||||
|
||||
def get_mat(ob):
|
||||
for sl in ob.material_slots:
|
||||
if sl.material:
|
||||
return sl.material
|
||||
|
||||
def link_mat_to_object(ob):
|
||||
for sl in ob.material_slots:
|
||||
m = sl.material
|
||||
sl.link = 'OBJECT'
|
||||
sl.material = m
|
||||
|
||||
def find_mirror(name):
|
||||
mirror = None
|
||||
prop= False
|
||||
|
||||
if name:
|
||||
|
||||
if name.startswith('[')and name.endswith(']'):
|
||||
prop = True
|
||||
name= name[:-2][2:]
|
||||
|
||||
match={
|
||||
'R': 'L',
|
||||
'r': 'l',
|
||||
'L': 'R',
|
||||
'l': 'r',
|
||||
}
|
||||
|
||||
separator=['.','_']
|
||||
|
||||
if name.startswith(tuple(match.keys())):
|
||||
if name[1] in separator:
|
||||
mirror = match[name[0]]+name[1:]
|
||||
|
||||
if name.endswith(tuple(match.keys())):
|
||||
if name[-2] in separator:
|
||||
mirror = name[:-1]+match[name[-1]]
|
||||
|
||||
if mirror and prop == True:
|
||||
mirror='["%s"]'%mirror
|
||||
|
||||
return mirror
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def hide_layers(args):
|
||||
""" """
|
||||
ob = bpy.context.object
|
||||
|
||||
layers = []
|
||||
for bone in [b for b in ob.pose.bones if b.bone.select]:
|
||||
for i,l in enumerate(bone.bone.layers):
|
||||
if l and i not in layers:
|
||||
layers.append(i)
|
||||
|
||||
for i in layers:
|
||||
ob.data.layers[i] = not ob.data.layers[i]
|
||||
|
||||
def select_layer(args):
|
||||
ob = bpy.context.object
|
||||
|
||||
layers =[]
|
||||
for bone in [b for b in ob.pose.bones if b.bone.select]:
|
||||
bone_layers = [i for i,l in enumerate(bone.bone.layers) if l]
|
||||
|
||||
for l in bone_layers:
|
||||
if l not in layers:
|
||||
layers.append(l)
|
||||
|
||||
for bone in ob.pose.bones:
|
||||
bone_layers = [i for i,l in enumerate(bone.bone.layers) if l]
|
||||
|
||||
if len(set(bone_layers).intersection(layers)):
|
||||
bone.bone.select = True
|
||||
|
||||
def hide_bones(args):
|
||||
ob = bpy.context.object
|
||||
selected_bone = [b for b in ob.pose.bones if b.bone.select]
|
||||
|
||||
hide = [b.bone.hide for b in selected_bone if not b.bone.hide]
|
||||
|
||||
visibility = True if len(hide) else False
|
||||
|
||||
for bone in selected_bone:
|
||||
bone.bone.hide = visibility
|
||||
|
||||
def select_all(args):
|
||||
ob = bpy.context.object
|
||||
shapes = ob.data.rig_picker['shapes']
|
||||
bones = [s['bone'] for s in shapes if s['shape_type']=='BONE']
|
||||
|
||||
for bone_name in bones:
|
||||
bone = ob.pose.bones.get(bone_name)
|
||||
|
||||
if bone:
|
||||
bone.bone.select = True
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
import bpy
|
||||
from mathutils import Vector
|
||||
from mathutils.geometry import intersect_line_line_2d
|
||||
|
||||
|
||||
def is_over_region(self,context,event):
|
||||
inside = 2 < event.mouse_region_x < context.region.width -2 and \
|
||||
2 < event.mouse_region_y < context.region.height -2 and \
|
||||
[a for a in context.screen.areas if a.as_pointer()==self.adress] and \
|
||||
not context.screen.show_fullscreen
|
||||
|
||||
return inside
|
||||
|
||||
def bound_box_center(ob):
|
||||
points = [ob.matrix_world@Vector(p) for p in ob.bound_box]
|
||||
|
||||
x = [v[0] for v in points]
|
||||
y = [v[1] for v in points]
|
||||
z = [v[2] for v in points]
|
||||
|
||||
return (sum(x) / len(points), sum(y) / len(points),sum(z) / len(points))
|
||||
|
||||
|
||||
def intersect_rectangles(bound, border): # returns None if rectangles don't intersect
|
||||
dx = min(border[1][0],bound[1][0]) - max(border[0][0],bound[0][0])
|
||||
dy = min(border[0][1],bound[0][1]) - max(border[2][1],bound[2][1])
|
||||
|
||||
if (dx>=0) and (dy>=0):
|
||||
return dx*dy
|
||||
|
||||
def point_inside_rectangle(point, rect):
|
||||
return rect[0][0]< point[0]< rect[1][0] and rect[2][1]< point[1]< rect[0][1]
|
||||
|
||||
def point_over_shape(point,verts,loops,outside_point=(-1,-1)):
|
||||
out = Vector(outside_point)
|
||||
pt = Vector(point)
|
||||
|
||||
intersections = 0
|
||||
for loop in loops:
|
||||
for i,p in enumerate(loop):
|
||||
a = Vector(verts[loop[i-1]])
|
||||
b = Vector(verts[p])
|
||||
|
||||
if intersect_line_line_2d(pt,out,a,b):
|
||||
intersections += 1
|
||||
|
||||
if intersections%2 == 1: #chek if the nb of intersection is odd
|
||||
return True
|
||||
+610
@@ -0,0 +1,610 @@
|
||||
|
||||
import bpy
|
||||
import gpu
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
import blf
|
||||
from mathutils import bvhtree, Vector
|
||||
from mathutils.geometry import intersect_point_quad_2d, intersect_point_tri_2d, intersect_tri_tri_2d
|
||||
from ..constants import PICKERS
|
||||
from .addon_utils import get_operator_from_id
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
|
||||
import threading
|
||||
|
||||
|
||||
|
||||
class Shape:
|
||||
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
|
||||
|
||||
|
||||
self.shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
|
||||
|
||||
#self.hover_shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
|
||||
#self.hover_shader.uniform_float("color", [1, 1, 1, 0.1])
|
||||
self.hover_color = [1, 1, 1, 0.1]
|
||||
|
||||
self.tooltip = tooltip
|
||||
self.color = color
|
||||
self.points = points
|
||||
self.polygons = polygons or []
|
||||
self.edges = edges or []
|
||||
|
||||
#print(points, self.polygons)
|
||||
|
||||
self.p_batch = batch_for_shader(self.shader, 'TRIS', {"pos": self.points}, indices=self.polygons)
|
||||
self.e_batch = batch_for_shader(self.shader, 'LINES', {"pos": self.points}, indices=self.edges)
|
||||
|
||||
#if polygons:
|
||||
# self.batch = batch_for_shader(self.shader, 'TRIS', {"pos": points}, indices=polygons)
|
||||
#else:
|
||||
#pts = []
|
||||
#for loop in self.edges:
|
||||
# pts += [self.points[i] for i in loop]
|
||||
|
||||
# self.batch = batch_for_shader(self.shader, 'LINES', {"pos": points}, indices=indices)
|
||||
|
||||
points_x = [v[0] for v in points]
|
||||
points_y = [v[1] for v in points]
|
||||
|
||||
self.bound = [
|
||||
(min(points_x), max(points_y)),
|
||||
(max(points_x), max(points_y)),
|
||||
(max(points_x), min(points_y)),
|
||||
(min(points_x), min(points_y))
|
||||
]
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
return self._color
|
||||
|
||||
@color.setter
|
||||
def color(self, color=None):
|
||||
if not color:
|
||||
color = [0.5, 0.5, 0.5, 1]
|
||||
elif isinstance(color, (tuple, list)) and len(color) in (3, 4):
|
||||
if len(color) == 3:
|
||||
color = [*color, 1]
|
||||
elif len(color) == 4:
|
||||
color = list(color)
|
||||
else:
|
||||
raise Exception('color must have a len of 3 or 4')
|
||||
else:
|
||||
raise Exception(f'color is {type(color)} must be None or (tuple, list)')
|
||||
|
||||
#self.shader.uniform_float("color", color)
|
||||
self._color = color
|
||||
|
||||
def draw(self):
|
||||
|
||||
self.shader.bind()
|
||||
self.shader.uniform_float("color", self.color)
|
||||
|
||||
if self.polygons:
|
||||
self.p_batch.draw(self.shader)
|
||||
if self.edges:
|
||||
self.e_batch.draw(self.shader)
|
||||
|
||||
def move_event(self, location):
|
||||
if not intersect_point_quad_2d(location, *self.bound):
|
||||
self.hover = False
|
||||
return False
|
||||
|
||||
for p in self.polygons:
|
||||
if intersect_point_tri_2d(location, *[self.points[i] for i in p]):
|
||||
self.hover = True
|
||||
return True
|
||||
|
||||
self.hover = False
|
||||
return False
|
||||
|
||||
def press_event(self, mode='SET'):
|
||||
self.press = True
|
||||
|
||||
def release_event(self, mode='SET'):
|
||||
self.press = False
|
||||
|
||||
|
||||
class BoneShape(Shape):
|
||||
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, source_name=source_name)
|
||||
|
||||
self.type = 'bone'
|
||||
self.bone = bone
|
||||
self.active_color = [1, 1, 1, 0.1]
|
||||
#self.contour_shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
|
||||
|
||||
#self.contour_batches = []
|
||||
|
||||
#self.line_batch =
|
||||
#for loop in edges:
|
||||
# loop_points = [points[i] for i in loop]
|
||||
# batch = batch_for_shader(self.shader, 'LINE_LOOP', {"pos": loop_points})
|
||||
# #self.contour_batches.append(batch)
|
||||
|
||||
theme = bpy.context.preferences.themes['Default']
|
||||
self.bone_colors = {
|
||||
'select': [*theme.view_3d.bone_pose, 1],
|
||||
'normal': [0.05, 0.05, 0.05, 1],
|
||||
'active': [*theme.view_3d.bone_pose_active, 1],
|
||||
'hide': [0.85, 0.85, 0.85, 0.2],
|
||||
}
|
||||
|
||||
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]
|
||||
return self.bone.bone.hide or not len(set(bl).intersection(rl))
|
||||
|
||||
@property
|
||||
def bone_color(self):
|
||||
if not self.bone:
|
||||
return [0, 0, 0, 1]
|
||||
|
||||
bone = self.bone.bone
|
||||
|
||||
bl = bone.layers
|
||||
rl = self.rig.data.layers
|
||||
|
||||
if self.select and self.active:
|
||||
return self.bone_colors['active']
|
||||
elif self.select:
|
||||
return self.bone_colors['select']
|
||||
elif self.hide:
|
||||
return self.bone_colors['hide']
|
||||
else:
|
||||
return self.bone_colors['normal']
|
||||
|
||||
def draw(self):
|
||||
gpu.state.blend_set('ALPHA')
|
||||
|
||||
if self.hide:
|
||||
self.shader.uniform_float("color", (*self.color[:3], 0.4))
|
||||
self.p_batch.draw(self.shader)
|
||||
#elif self.select:
|
||||
# self.shader.uniform_float("color", self.bone_color)
|
||||
# self.p_batch.draw(self.shader)
|
||||
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
|
||||
|
||||
if self.select or self.hover:
|
||||
color = self.hover_color
|
||||
|
||||
if self.select and self.hover:
|
||||
color = self.active_color
|
||||
|
||||
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()
|
||||
|
||||
#print(self.bone_color)
|
||||
if self.select or self.active:
|
||||
gpu.state.line_width_set(2.0)
|
||||
|
||||
#if not self.hide:
|
||||
self.shader.uniform_float("color", self.bone_color)
|
||||
#for b in self.contour_batches:
|
||||
self.e_batch.draw(self.shader)
|
||||
|
||||
gpu.state.line_width_set(1.0)
|
||||
gpu.state.blend_set('NONE')
|
||||
|
||||
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 or not self.bone:
|
||||
return
|
||||
|
||||
select = True
|
||||
if mode == 'SUBSTRACT':
|
||||
select = False
|
||||
|
||||
self.bone.bone.select = select
|
||||
if self.hover:
|
||||
|
||||
if mode != 'SUBSTRACT':
|
||||
self.rig.data.bones.active = self.bone.bone
|
||||
|
||||
|
||||
def border_select(self, border, mode='SET'):
|
||||
'''
|
||||
if ( not any(intersect_point_quad_2d(b, *self.bound) for b in border) and
|
||||
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
|
||||
return
|
||||
|
||||
bound_tri1 = self.bound[0], self.bound[1], self.bound[2]
|
||||
bound_tri2 = self.bound[2], self.bound[3], self.bound[0]
|
||||
|
||||
border_tri1 = border[0], border[1], border[2]
|
||||
border_tri2 = border[2], border[3], border[0]
|
||||
|
||||
if (not intersect_tri_tri_2d(*border_tri1, *bound_tri1) and
|
||||
not intersect_tri_tri_2d(*border_tri1, *bound_tri2) and
|
||||
not intersect_tri_tri_2d(*border_tri2, *bound_tri1) and
|
||||
not intersect_tri_tri_2d(*border_tri2, *bound_tri2)):
|
||||
return
|
||||
|
||||
select = True
|
||||
if mode == 'SUBSTRACT':
|
||||
select = False
|
||||
|
||||
for polygon in self.polygons:
|
||||
points = [self.points[i] for i in polygon]
|
||||
|
||||
if intersect_tri_tri_2d(*border_tri1, *points):
|
||||
self.bone.bone.select = select
|
||||
return
|
||||
|
||||
if intersect_tri_tri_2d(*border_tri2, *points):
|
||||
self.bone.bone.select = select
|
||||
return
|
||||
|
||||
'''
|
||||
for b in border:
|
||||
if intersect_point_tri_2d(b, *points):
|
||||
self.bone.bone.select = select
|
||||
return
|
||||
|
||||
for p in points:
|
||||
if intersect_point_quad_2d(p, *border):
|
||||
self.bone.bone.select = select
|
||||
return
|
||||
'''
|
||||
|
||||
class OperatorShape(Shape):
|
||||
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]
|
||||
self.press_color = [0, 0, 0, 0.25]
|
||||
self.operator = operator
|
||||
#self.arguments = arguments#{k:eval(v)}
|
||||
#self.operator = get_operator_from_id(self.operator)
|
||||
|
||||
if not tooltip:
|
||||
self.tooltip = self.operator.replace('bpy.ops.', '').replace("'INVOKE_DEFAULT', ", '')
|
||||
|
||||
#self.reg_args = re.compile(r'(\w+)=')
|
||||
'''
|
||||
def parse_args(self):
|
||||
|
||||
args = self.reg_args.split(self.arguments)[1:]
|
||||
#print(args, zip(args[::2], args[1::2]))
|
||||
return {k: eval(v) for k, v in zip(args[::2], args[1::2])}
|
||||
#return {k:eval(v) for k, v in self.reg_args.split(self.arguments)}
|
||||
'''
|
||||
|
||||
def release_event(self, mode='SET'):
|
||||
super().release_event(mode)
|
||||
|
||||
#args = self.parse_args()
|
||||
if not self.operator:
|
||||
return
|
||||
|
||||
exec(self.operator)
|
||||
#f'bpy.ops;{idname}'
|
||||
|
||||
#print(self.idname)
|
||||
#print(self.arguments)
|
||||
#else:
|
||||
# self.bone.bone.select = False
|
||||
|
||||
def draw(self):
|
||||
super().draw()
|
||||
|
||||
if self.press:
|
||||
color = self.press_color
|
||||
elif self.hover:
|
||||
color = self.hover_color
|
||||
else:
|
||||
return
|
||||
|
||||
gpu.state.blend_set('ALPHA')
|
||||
self.shader.uniform_float("color", color)
|
||||
self.p_batch.draw(self.shader)
|
||||
gpu.state.blend_set('NONE')
|
||||
|
||||
|
||||
class Picker:
|
||||
def __init__(self, rig, shapes):
|
||||
|
||||
self.region = bpy.context.region
|
||||
self.rig = rig
|
||||
|
||||
self.shapes = []
|
||||
self.box_select = None
|
||||
self.hover_shape = None
|
||||
self.shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
|
||||
|
||||
self.tooltip_shape = None
|
||||
self.tooltip_mouse = None
|
||||
self.tooltip = ''
|
||||
|
||||
self.timer = None
|
||||
self.mouse = None
|
||||
|
||||
for s in shapes:
|
||||
if not s['points']:
|
||||
continue
|
||||
|
||||
if s['type'] in ('CANVAS', 'DISPLAY'):
|
||||
shape = Shape(
|
||||
self,
|
||||
points=s['points'],
|
||||
polygons=s['polygons'],
|
||||
edges=s['edges'],
|
||||
color=s['color']
|
||||
)
|
||||
|
||||
elif s['type'] == 'BONE':
|
||||
bone = rig.pose.bones.get(s['bone'])
|
||||
#if not bone:
|
||||
# print(f'Bone {s["bone"]} not exist')
|
||||
# continue
|
||||
|
||||
shape = BoneShape(
|
||||
self,
|
||||
source_name=s['source_name'],
|
||||
points=s['points'],
|
||||
polygons=s['polygons'],
|
||||
edges=s['edges'],
|
||||
bone=bone,
|
||||
color=s['color']
|
||||
)
|
||||
|
||||
elif s['type'] == 'OPERATOR':
|
||||
shape = OperatorShape(
|
||||
self,
|
||||
source_name=s['source_name'],
|
||||
points=s['points'],
|
||||
polygons=s['polygons'],
|
||||
operator=s['operator'],
|
||||
color=s['color'],
|
||||
tooltip=s['tooltip'],
|
||||
)
|
||||
|
||||
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:
|
||||
s.press_event(mode)
|
||||
else:
|
||||
s.press = False
|
||||
|
||||
def release_event(self, mode='SET'):
|
||||
if mode == 'SET':
|
||||
for b in self.rig.pose.bones:
|
||||
b.bone.select = False
|
||||
|
||||
#bpy.ops.pose.select_all(action='DESELECT')
|
||||
|
||||
#print('PICKER release event', mode)
|
||||
#print(f'type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
||||
|
||||
for s in self.shapes:
|
||||
if s.hover:
|
||||
s.release_event(mode)
|
||||
|
||||
s.press = False
|
||||
|
||||
#bpy.context.area.tag_redraw()
|
||||
|
||||
|
||||
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
|
||||
else:
|
||||
self.tooltip = self.hover_shape.tooltip
|
||||
self.tooltip_shape = self.hover_shape
|
||||
else:
|
||||
self.tooltip = ''
|
||||
self.tooltip_shape = None
|
||||
|
||||
self.tooltip_mouse = self.mouse
|
||||
|
||||
self.timer.cancel()
|
||||
|
||||
#print(self.tooltip)
|
||||
|
||||
self.region.tag_redraw()
|
||||
|
||||
'''
|
||||
picker.tooltip_event(event='SHOW')
|
||||
region.tag_redraw()
|
||||
|
||||
|
||||
|
||||
#context.region.tag_redraw()
|
||||
|
||||
picker.tooltip_event(event='HIDE')
|
||||
bpy.app.timers.register(partial(tooltip, context.region), first_interval=1)
|
||||
'''
|
||||
'''
|
||||
def tooltip_event(self, event):
|
||||
|
||||
|
||||
|
||||
self.tooltip = ''
|
||||
|
||||
if event == 'SHOW':
|
||||
if self.hover_shape.type == 'bone':
|
||||
self.tooltip = self.hover_shape.bone.name
|
||||
|
||||
#bpy.context.region.tag_redraw()
|
||||
'''
|
||||
|
||||
def border_select(self, border, mode):
|
||||
border = [bpy.context.region.view2d.region_to_view(*b) for b in border]
|
||||
|
||||
if mode == 'SET':
|
||||
for b in self.rig.pose.bones:
|
||||
b.bone.select = False
|
||||
|
||||
for s in (s for s in self.shapes if s.type=='bone'):
|
||||
s.border_select(border, mode)
|
||||
|
||||
def move_event(self, location):
|
||||
self.mouse = location
|
||||
location = self.region.view2d.region_to_view(*location)
|
||||
|
||||
self.hover_shape = None
|
||||
for shape in reversed(self.shapes):
|
||||
if self.hover_shape:
|
||||
shape.hover = False
|
||||
elif shape.move_event(location):
|
||||
self.hover_shape = shape
|
||||
|
||||
#if point_inside_rectangle(self.end, bound):
|
||||
# over = point_over_shape(self.end,points, edges)
|
||||
|
||||
#if bpy.app.timers.is_registered(self.tooltip_event):
|
||||
#try:
|
||||
# bpy.app.timers.unregister(self.tooltip_event)
|
||||
#except:
|
||||
# pass
|
||||
if self.tooltip_shape is not self.hover_shape:
|
||||
self.tooltip = ''
|
||||
|
||||
if self.timer:
|
||||
self.timer.cancel()
|
||||
|
||||
self.timer = threading.Timer(0.5, self.tooltip_event)
|
||||
self.timer.start()
|
||||
|
||||
|
||||
#bpy.app.timers.register(self.tooltip_event, first_interval=1)
|
||||
|
||||
def draw(self):
|
||||
for s in self.shapes:
|
||||
s.draw()
|
||||
'''
|
||||
if self.box_select:
|
||||
|
||||
self.box_shader.uniform_float("color", self.box_select_color)
|
||||
batch = batch_for_shader(self.shader, 'LINE_LOOP', {"pos": []})
|
||||
|
||||
|
||||
for b in self.contour_batches:
|
||||
b.draw(self.contour_shader)
|
||||
|
||||
self.batch.draw(self.shader)
|
||||
|
||||
|
||||
gpu.state.blend_set('NONE')
|
||||
'''
|
||||
|
||||
def get_picker_path(rig, start=None):
|
||||
picker_path = rig.data.get('rig_picker', {}).get('source')
|
||||
if not picker_path:
|
||||
return
|
||||
|
||||
picker_path = bpy.path.abspath(picker_path, library=rig.data.library, start=start)
|
||||
|
||||
return Path(os.path.abspath(picker_path))
|
||||
|
||||
def pack_picker(rig, start=None):
|
||||
picker_path = get_picker_path(rig, start=start)
|
||||
if picker_path and picker_path.exists():
|
||||
if 'rig_picker' not in rig.data.keys():
|
||||
rig.data['rig_picker'] = {}
|
||||
|
||||
rig.data['rig_picker']['picker'] = json.loads(picker_path.read_text())
|
||||
|
||||
def unpack_picker(rig):
|
||||
if 'rig_picker' not in rig.data.keys():
|
||||
return
|
||||
|
||||
if 'picker' in rig.data['rig_picker'].keys():
|
||||
del rig.data['rig_picker']['picker']
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
import bpy
|
||||
import bmesh
|
||||
from mathutils import Vector, Matrix
|
||||
from bpy_extras import mesh_utils
|
||||
from .geometry_utils import bound_box_center
|
||||
from .addon_utils import get_object_color
|
||||
|
||||
|
||||
|
||||
def border_over_shape(border,verts,loops):
|
||||
for loop in loops:
|
||||
for i,p in enumerate(loop):
|
||||
a = Vector(verts[loop[i-1]])
|
||||
b = Vector(verts[p])
|
||||
|
||||
for j in range(0,4):
|
||||
c = border[j-1]
|
||||
d = border[j]
|
||||
if intersect_line_line_2d(a,b,c,d):
|
||||
return True
|
||||
|
||||
for point in verts:
|
||||
if point_inside_rectangle(point,border):
|
||||
return True
|
||||
|
||||
for point in border:
|
||||
if point_over_shape(point,verts,loops):
|
||||
return True
|
||||
|
||||
|
||||
def border_loop(vert, loop):
|
||||
border_edge =[e for e in vert.link_edges if e.is_boundary]
|
||||
|
||||
if border_edge:
|
||||
for edge in border_edge:
|
||||
other_vert = edge.other_vert(vert)
|
||||
|
||||
if not other_vert in loop:
|
||||
loop.append(other_vert)
|
||||
border_loop(other_vert, loop)
|
||||
|
||||
return loop
|
||||
else:
|
||||
return [vert]
|
||||
|
||||
def contour_loops(bm, vert_index=0, loops=None, vert_indices=None):
|
||||
loops = loops or []
|
||||
vert_indices = vert_indices or [v.index for v in bm.verts]
|
||||
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
loop = border_loop(bm.verts[vert_index], [bm.verts[vert_index]])
|
||||
if len(loop) >1:
|
||||
loops.append(loop)
|
||||
|
||||
for v in loop:
|
||||
vert_indices.remove(v.index)
|
||||
|
||||
if len(vert_indices):
|
||||
contour_loops(bm, vert_indices[0], loops, vert_indices)
|
||||
|
||||
return loops
|
||||
|
||||
def get_picker_datas(objects, canvas, rig):
|
||||
picker_datas = []
|
||||
gamma = 1 / 2.2
|
||||
|
||||
if canvas.type =='CURVE':
|
||||
canvas_points = canvas.data.splines[0].points
|
||||
else:
|
||||
canvas_points = canvas.data.vertices
|
||||
|
||||
canvas_coords = [canvas.matrix_world@Vector((p.co)) for p in canvas_points]
|
||||
|
||||
canvas_x = [p[0] for p in canvas_coords]
|
||||
canvas_y = [p[1] for p in canvas_coords]
|
||||
|
||||
canvas_center = sum(canvas_coords, Vector()) / len(canvas_coords)
|
||||
canvas_scale_fac = 4096 / (max(canvas_y) - min(canvas_y))# Reference height for the canvas
|
||||
|
||||
objects.append(canvas)
|
||||
|
||||
dg = bpy.context.evaluated_depsgraph_get()
|
||||
|
||||
#sorted by their z axes
|
||||
for ob in sorted(objects, key=lambda x: bound_box_center(x)[2]):
|
||||
|
||||
|
||||
print('Storing shape', ob.name)
|
||||
mesh = bpy.data.meshes.new_from_object(ob.evaluated_get(dg))
|
||||
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(mesh)
|
||||
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.002)
|
||||
bmesh.ops.dissolve_limit(bm, angle_limit=0.001745, verts=bm.verts, edges=bm.edges)
|
||||
|
||||
bmesh.ops.connect_verts_concave(bm, faces=bm.faces)
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||
|
||||
#bm_loops = contour_loops(bm)
|
||||
#loops = [[l.index for l in loop] for loop in bm_loops]
|
||||
loops = []
|
||||
|
||||
edges = [[v.index for v in e.verts] for e in bm.edges if len(e.link_faces)<=1]
|
||||
|
||||
bm.to_mesh(mesh)
|
||||
mesh.update()
|
||||
bm.clear()
|
||||
|
||||
points = []
|
||||
#edges = []
|
||||
polygons = []
|
||||
|
||||
for p in mesh.vertices:
|
||||
point = ob.matrix_world@Vector((p.co))
|
||||
point = (point - canvas_center) * canvas_scale_fac
|
||||
points.append([round(point[0]), round(point[1])])
|
||||
|
||||
for f in mesh.polygons:
|
||||
polygons.append([v for v in f.vertices])
|
||||
|
||||
#for e in mesh.edges:
|
||||
#
|
||||
# edges.append([v for v in e.vertices])
|
||||
|
||||
color = get_object_color(ob)
|
||||
if color:
|
||||
color = [round(pow(c, gamma), 4) for c in color]
|
||||
else:
|
||||
color = [0.5, 0.5, 0.5]
|
||||
|
||||
shape = {
|
||||
'source_name': ob.name,
|
||||
'tooltip': ob.rig_picker.name,
|
||||
'points': points,
|
||||
'polygons': polygons,
|
||||
'edges': edges,
|
||||
'loops': loops,
|
||||
'color': color,
|
||||
'type': 'CANVAS' if ob == canvas else ob.rig_picker.shape_type
|
||||
}
|
||||
|
||||
if shape['type'] =='OPERATOR':
|
||||
shape['operator'] = ob.rig_picker.operator
|
||||
#if ob.rig_picker.arguments:
|
||||
#shape['arguments'] = ob.rig_picker.arguments
|
||||
#if ob.rig_picker.shortcut:
|
||||
shape['shortcut'] = ob.rig_picker.shortcut
|
||||
|
||||
elif shape['type'] =='BONE':
|
||||
shape['bone'] = ob.rig_picker.name
|
||||
|
||||
picker_datas.append(shape)
|
||||
|
||||
|
||||
#print(picker_datas)
|
||||
|
||||
return picker_datas
|
||||
#rig.data.rig_picker['shapes'] = picker_datas
|
||||
Reference in New Issue
Block a user