2022-04-06 10:12:32 +02:00
|
|
|
import bpy
|
2024-02-19 11:53:15 +01:00
|
|
|
from bpy.props import EnumProperty, IntProperty
|
2023-11-09 10:29:56 +01:00
|
|
|
from ..constants import PICKERS
|
|
|
|
from ..core.bl_utils import get_view_3d_override
|
2024-02-19 11:53:15 +01:00
|
|
|
from ..core.geometry_utils import bounding_rect
|
2023-11-09 10:29:56 +01:00
|
|
|
from ..core.picker import get_picker_path, pack_picker, unpack_picker
|
2022-04-06 10:12:32 +02:00
|
|
|
#from .func_bgl import draw_callback_px
|
|
|
|
#from .func_bgl import select_bone
|
2023-11-09 10:29:56 +01:00
|
|
|
#from core.picker import *
|
2022-04-06 10:12:32 +02:00
|
|
|
#from .utils import is_over_region
|
|
|
|
import gpu
|
|
|
|
from mathutils import Vector
|
|
|
|
from gpu_extras.batch import batch_for_shader
|
2022-04-12 18:14:56 +02:00
|
|
|
from pathlib import Path
|
|
|
|
import json
|
2023-11-09 10:29:56 +01:00
|
|
|
import os
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
vertex_shader = '''
|
|
|
|
layout (location = 0) in vec2 pos;
|
|
|
|
|
|
|
|
flat out vec2 startPos;
|
|
|
|
out vec2 vertPos;
|
|
|
|
|
|
|
|
uniform mat4 viewMatrix;
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
vec4 outPos = viewMatrix * vec4(pos.x, pos.y, 0.0, 1.0);
|
|
|
|
gl_Position = outPos;
|
|
|
|
vertPos = pos.xy / outPos.w;
|
|
|
|
startPos = vertPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
fragment_shader = '''
|
|
|
|
flat in vec2 startPos;
|
|
|
|
in vec2 vertPos;
|
|
|
|
|
|
|
|
out vec4 fragColor;
|
|
|
|
|
|
|
|
uniform vec4 color;
|
|
|
|
uniform float dashSize;
|
|
|
|
uniform float gapSize;
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
vec2 dir = (vertPos.xy - startPos.xy);
|
|
|
|
float dist = length(dir);
|
|
|
|
|
|
|
|
if (fract(dist / (dashSize + gapSize)) > dashSize/(dashSize + gapSize))
|
|
|
|
discard;
|
|
|
|
fragColor = color;
|
|
|
|
}
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def draw_callback(self):
|
|
|
|
#print('draw callback border')
|
|
|
|
if not self.draw_border:
|
|
|
|
return
|
|
|
|
|
2023-10-03 11:49:21 +02:00
|
|
|
gpu.state.blend_set('ALPHA')
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
#print('DRAW BORDER')
|
|
|
|
|
|
|
|
self.color_shader.bind()
|
|
|
|
self.color_shader.uniform_float("color", self.bg_color)
|
|
|
|
self.bg_batch.draw(self.color_shader)
|
|
|
|
|
|
|
|
self.dash_shader.bind()
|
|
|
|
matrix = gpu.matrix.get_projection_matrix()
|
|
|
|
|
|
|
|
self.dash_shader.uniform_float("color", self.border_color)
|
|
|
|
self.dash_shader.uniform_float("viewMatrix", matrix)
|
|
|
|
self.dash_shader.uniform_float("dashSize", 5)
|
|
|
|
self.dash_shader.uniform_float("gapSize", 4)
|
|
|
|
|
|
|
|
self.contour_batch.draw(self.dash_shader)
|
|
|
|
|
2023-10-03 11:49:21 +02:00
|
|
|
gpu.state.blend_set('NONE')
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
2022-04-12 18:14:56 +02:00
|
|
|
def is_picker_space(context):
|
|
|
|
sp = context.space_data
|
|
|
|
if sp and (sp.type == 'NODE_EDITOR' and sp.tree_type == 'RigPickerTree'):
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
class RP_OT_box_select(bpy.types.Operator):
|
|
|
|
"""Tooltip"""
|
|
|
|
bl_idname = "node.rp_box_select"
|
|
|
|
bl_label = "Picker Box Select"
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
mode: EnumProperty(items=[(i, i.title(), '') for i in ('SET', 'EXTEND', 'SUBSTRACT')])
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-21 11:40:15 +01:00
|
|
|
color_shader = gpu.shader.from_builtin('UNIFORM_COLOR')
|
2022-04-06 10:12:32 +02:00
|
|
|
dash_shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
2022-04-12 18:14:56 +02:00
|
|
|
if not is_picker_space(context):
|
2022-04-06 10:12:32 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
ob = context.object
|
|
|
|
return ob and ob in PICKERS
|
|
|
|
|
|
|
|
'''
|
|
|
|
def mode_from_event(self, event):
|
|
|
|
if event.alt:
|
|
|
|
return 'SUBSTRACT'
|
|
|
|
elif event.ctrl or event.shift:
|
|
|
|
return 'EXTEND'
|
|
|
|
else:
|
|
|
|
return 'SET'
|
|
|
|
'''
|
|
|
|
|
|
|
|
def invoke(self, context, event):
|
|
|
|
#print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
|
|
|
|
|
|
|
if context.object.mode != 'POSE':
|
|
|
|
bpy.ops.object.posemode_toggle()
|
|
|
|
|
|
|
|
self.timer = None
|
|
|
|
#self.mode = self.mode_from_event(event)
|
|
|
|
#self.invoke_event = event.copy()
|
|
|
|
self.region = context.region
|
|
|
|
self.draw_border = False
|
|
|
|
|
|
|
|
self.picker = PICKERS[context.object]
|
|
|
|
|
|
|
|
self.start_mouse = event.mouse_region_x, event.mouse_region_y
|
|
|
|
#self.shader = line_strip_shader
|
|
|
|
self.border_color = [1, 1, 1, 1]
|
|
|
|
self.bg_color = [1, 1, 1, 0.05]
|
|
|
|
|
|
|
|
#args = (self, context)
|
|
|
|
self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(draw_callback, (self,), 'WINDOW', 'POST_PIXEL')
|
|
|
|
|
|
|
|
context.window_manager.modal_handler_add(self)
|
|
|
|
|
|
|
|
self.picker.press_event(self.mode)
|
|
|
|
self.region.tag_redraw()
|
|
|
|
|
|
|
|
return {'RUNNING_MODAL'}
|
|
|
|
|
|
|
|
def modal(self, context, event):
|
|
|
|
|
|
|
|
self.mouse = event.mouse_region_x, event.mouse_region_y
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
self.border = bounding_rect((self.start_mouse, self.mouse))
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
self.bg_batch = batch_for_shader(self.color_shader, 'TRI_FAN', {"pos": self.border})
|
|
|
|
self.contour_batch = batch_for_shader(self.dash_shader, 'LINE_LOOP', {"pos": self.border})
|
|
|
|
|
|
|
|
self.draw_border = True
|
|
|
|
|
|
|
|
self.region.tag_redraw()
|
|
|
|
|
|
|
|
if event.value == 'RELEASE':
|
|
|
|
return self.release_event()
|
|
|
|
|
|
|
|
return {'RUNNING_MODAL'}
|
|
|
|
|
|
|
|
def release_event(self):
|
2023-03-31 14:53:41 +02:00
|
|
|
scn = bpy.context.scene
|
|
|
|
|
|
|
|
if scn.rig_picker.use_pick_bone:
|
|
|
|
self.picker.assign_bone_event()
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]):
|
2022-04-06 10:12:32 +02:00
|
|
|
self.picker.border_select(self.border, self.mode)
|
|
|
|
else:
|
|
|
|
self.picker.move_event(self.mouse)
|
|
|
|
self.picker.release_event(self.mode)
|
2022-05-05 11:58:33 +02:00
|
|
|
|
|
|
|
bpy.ops.ed.undo_push(message="Box Select")
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
return self.exit()
|
|
|
|
|
|
|
|
def exit(self):
|
|
|
|
#print('Border Select Finished')
|
|
|
|
|
|
|
|
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
|
|
|
|
self.region.tag_redraw()
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
class RP_OT_picker_transform(bpy.types.Operator):
|
2022-04-06 10:12:32 +02:00
|
|
|
"""Tooltip"""
|
2023-11-09 10:29:56 +01:00
|
|
|
bl_idname = "node.picker_transform"
|
2022-04-06 10:12:32 +02:00
|
|
|
bl_label = "Move Bone in Picker View"
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
mode : EnumProperty(items=[(m, m.title(), '') for m in ('TRANSLATE', 'ROTATE', 'SCALE')])
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
2023-11-09 10:29:56 +01:00
|
|
|
return is_picker_space(context)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
def execute(self, context):
|
|
|
|
with context.temp_override(**get_view_3d_override()):
|
|
|
|
if self.mode == 'TRANSLATE':
|
|
|
|
bpy.ops.transform.translate("INVOKE_DEFAULT")
|
|
|
|
elif self.mode == 'ROTATE':
|
|
|
|
bpy.ops.transform.rotate("INVOKE_DEFAULT")
|
|
|
|
elif self.mode == 'SCALE':
|
|
|
|
bpy.ops.transform.resize("INVOKE_DEFAULT")
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
return {"FINISHED"}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# def invoke(self, context, event):
|
|
|
|
# self.mouse = event.mouse_region_x, event.mouse_region_y
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# self.bone_data = {b: b.matrix.copy() for b in context.selected_pose_bones}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# context.window_manager.modal_handler_add(self)
|
|
|
|
# return {'RUNNING_MODAL'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# def modal(self, context, event):
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# delta_x = (event.mouse_region_x - self.mouse[0]) / 1000
|
|
|
|
# delta_y = (event.mouse_region_y - self.mouse[1]) / 1000
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# for bone, matrix in self.bone_data.items():
|
|
|
|
# bone.matrix.translation = matrix.translation + Vector((delta_x, 0, delta_y))
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# #print(delta_x, delta_y)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# if event.type=="LEFTMOUSE" and event.value == 'RELEASE':
|
|
|
|
# return {'FINISHED'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
# if event.type=="RIGHTMOUSE":
|
|
|
|
# for bone, matrix in self.bone_data.items():
|
|
|
|
# bone.matrix = matrix
|
|
|
|
|
|
|
|
# return {'CANCELLED'}
|
|
|
|
|
|
|
|
# return {'RUNNING_MODAL'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
class RP_OT_function_execute(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.function_execute"
|
|
|
|
bl_label = 'Function Execute'
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
shape_index = IntProperty()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2022-09-06 15:58:16 +02:00
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
if not is_picker_space(context):
|
|
|
|
return
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
def execute(self,context):
|
|
|
|
event = self.event
|
|
|
|
ob = context.object
|
|
|
|
shape = ob.data.rig_picker['shapes'][self.shape_index]
|
|
|
|
|
|
|
|
function = shape['function']
|
|
|
|
if shape.get('variables'):
|
|
|
|
variables=shape['variables'].to_dict()
|
|
|
|
else:
|
|
|
|
variables={}
|
|
|
|
|
|
|
|
variables['event']=event
|
|
|
|
globals()[function](variables)
|
|
|
|
|
|
|
|
return {'FINISHED'}
|
|
|
|
|
|
|
|
def invoke(self,context,event):
|
|
|
|
self.event = event
|
|
|
|
return self.execute(context)
|
|
|
|
|
|
|
|
|
|
|
|
class RP_OT_reload_picker(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.reload_picker"
|
|
|
|
bl_label = 'Reload Picker'
|
|
|
|
|
2022-09-06 15:58:16 +02:00
|
|
|
#@classmethod
|
|
|
|
#def poll(cls, context):
|
|
|
|
# if not is_picker_space(context):
|
|
|
|
# return
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
def execute(self,context):
|
|
|
|
PICKERS.clear()
|
2022-09-06 15:58:16 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
for a in context.screen.areas:
|
2022-09-06 15:58:16 +02:00
|
|
|
a.tag_redraw()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
|
class RP_OT_toogle_bone_layer(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.toogle_bone_layer"
|
|
|
|
bl_label = 'Toogle Bone Layer'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
2022-04-12 18:14:56 +02:00
|
|
|
if not is_picker_space(context):
|
2022-04-06 10:12:32 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
ob = context.object
|
|
|
|
picker = PICKERS.get(ob)
|
|
|
|
|
2022-04-12 18:14:56 +02:00
|
|
|
if picker.hover_shape and picker.hover_shape.type == 'bone':
|
2022-04-06 10:12:32 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
ob = context.object
|
|
|
|
picker = PICKERS.get(ob)
|
|
|
|
|
|
|
|
bone = picker.hover_shape.bone
|
|
|
|
hide = picker.hover_shape.hide
|
|
|
|
|
|
|
|
if bone:
|
2023-11-21 11:40:15 +01:00
|
|
|
for layer in bone.bone.collections:
|
|
|
|
layer.is_visible = hide
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
context.region.tag_redraw()
|
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
class RP_OT_context_menu_picker(bpy.types.Operator):
|
|
|
|
bl_idname = "node.context_menu_picker"
|
|
|
|
bl_label = 'Context Menu Picker'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
return is_picker_space(context)
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
bpy.ops.wm.call_menu(name='RP_MT_context_menu')
|
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
2022-04-12 18:14:56 +02:00
|
|
|
class RP_OT_pack_picker(bpy.types.Operator):
|
|
|
|
"""Pack Unpack the picker on the rig"""
|
|
|
|
bl_idname = "rigpicker.pack_picker"
|
|
|
|
bl_label = 'Toogle Bone Layer'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
ob = context.object
|
|
|
|
return (ob and ob.type == 'ARMATURE' and ob.data.rig_picker.source)
|
|
|
|
|
|
|
|
def execute(self, context):
|
|
|
|
print('Pack Picker')
|
2023-11-09 10:29:56 +01:00
|
|
|
|
|
|
|
rig = context.object
|
|
|
|
picker_path = get_picker_path(rig)
|
2022-04-12 18:14:56 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
if 'picker' in rig.data.rig_picker.keys():
|
|
|
|
unpack_picker(rig)
|
|
|
|
self.report({"INFO"}, f'The picker is unpacked')
|
2022-04-12 18:14:56 +02:00
|
|
|
return {"FINISHED"}
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
if not picker_path.exists():
|
|
|
|
self.report({"ERROR"}, f'The path of the picker not exist: {picker_path}')
|
2022-04-12 18:14:56 +02:00
|
|
|
return {"CANCELLED"}
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
pack_picker(rig)
|
|
|
|
self.report({"INFO"}, f'The picker is packed')
|
2022-04-12 18:14:56 +02:00
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
class RP_OT_call_operator(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.call_operator"
|
2024-02-19 11:53:15 +01:00
|
|
|
bl_label = 'Call operator'
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
operator : bpy.props.StringProperty()
|
|
|
|
view_3d : bpy.props.BoolProperty()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
2022-04-12 18:14:56 +02:00
|
|
|
return is_picker_space(context)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
def execute(self, context):
|
2024-02-19 11:53:15 +01:00
|
|
|
if not self.operator.startswith('bpy.ops'):
|
|
|
|
print("Operator call_operator can only execute operator")
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
print('CAll Operator')
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
context.area.tag_redraw()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
override = {}
|
|
|
|
if self.view_3d:
|
|
|
|
override = get_view_3d_override()
|
|
|
|
|
|
|
|
with context.temp_override(**override):
|
|
|
|
try:
|
|
|
|
exec(self.operator)
|
|
|
|
except Exception as e:
|
|
|
|
self.report({"ERROR"}, e)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
context.area.tag_redraw()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
return {"FINISHED"}
|
|
|
|
|
|
|
|
|
|
|
|
class RP_MT_context_menu(bpy.types.Menu):
|
|
|
|
bl_label = "Context Menu"
|
2022-04-12 18:14:56 +02:00
|
|
|
#bl_idname = "RP_MT_context_menu"
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
# Set the menu operators and draw functions
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
2023-11-09 10:29:56 +01:00
|
|
|
col = layout.column()
|
|
|
|
col.use_property_split = True
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
ob = context.object
|
|
|
|
picker = PICKERS.get(ob)
|
|
|
|
|
|
|
|
if picker.hover_shape and picker.hover_shape.type == 'bone':
|
|
|
|
bone = picker.hover_shape.bone
|
|
|
|
|
|
|
|
for key in bone.keys():
|
|
|
|
layout.prop(bone,f'["{key}"]', slider=True)
|
|
|
|
|
|
|
|
#layout.operator("rigpicker.show_bone_layer", text="Show Bone Layer", ).type = 'ACTIVE'
|
2022-04-06 10:12:32 +02:00
|
|
|
#layout.operator("rigidbody.objects_add", text="B Add Passive").type = 'PASSIVE'
|
|
|
|
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
class RP_OT_add_picker_source(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.add_picker_source"
|
|
|
|
bl_label = "Add a Picker source"
|
|
|
|
bl_description = "Add a Picker source"
|
|
|
|
bl_options = {'UNDO', 'REGISTER'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
def execute(self, context):
|
|
|
|
arm = context.object.data
|
|
|
|
arm.rig_picker.sources.add()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
return {'FINISHED'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
class RP_OT_remove_picker_source(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.remove_picker_source"
|
|
|
|
bl_label = "Delete a Picker source"
|
|
|
|
bl_description = "Delete a Picker source"
|
|
|
|
bl_options = {'UNDO', 'REGISTER'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
index : IntProperty(default=-1)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
def execute(self, context):
|
|
|
|
arm = context.object.data
|
|
|
|
arm.rig_picker.sources.remove(self.index)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
return {'FINISHED'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
class RP_OT_fit_picker(bpy.types.Operator):
|
|
|
|
bl_idname = "rigpicker.fit_picker"
|
|
|
|
bl_label = "Fit Picker"
|
|
|
|
bl_description = "Fit Picker in 2d view"
|
|
|
|
bl_options = {'UNDO', 'REGISTER'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
index : IntProperty()
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
@classmethod
|
|
|
|
def poll(cls, context):
|
|
|
|
return is_picker_space(context) and PICKERS.get(context.object)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
def execute(self, context):
|
|
|
|
ob = context.object
|
|
|
|
picker_group = PICKERS[ob]
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
if self.index >= len(picker_group.pickers):
|
|
|
|
return {"CANCELLED"}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
picker = picker_group.pickers[self.index]
|
|
|
|
view2d = context.region.view2d
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
if self.index == -1:
|
|
|
|
#print('Picker Group')
|
|
|
|
picker = picker_group
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
view_rect = [view2d.view_to_region(*co, clip=False) for co in picker.rect]
|
|
|
|
bpy.ops.view2d.zoom_border(
|
|
|
|
xmin=round(view_rect[3][0]), xmax=round(view_rect[1][0]),
|
|
|
|
ymin=round(view_rect[3][1]), ymax=round(view_rect[1][1]),
|
|
|
|
wait_for_input=False, zoom_out=False
|
|
|
|
)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
region_center = Vector((context.region.width * 0.5, context.region.height * 0.5))
|
|
|
|
view_center = view2d.region_to_view(*region_center)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
view_offset = Vector(view_center) + (picker.center - Vector(view_center))
|
|
|
|
region_offset = view2d.view_to_region(*view_offset, clip=False)
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
delta = Vector(region_offset) - region_center
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
bpy.ops.view2d.pan(deltax=round(delta[0]), deltay=round(delta[1]))
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
return {'FINISHED'}
|
2022-04-06 10:12:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
keymaps = []
|
|
|
|
def register_keymaps():
|
|
|
|
wm = bpy.context.window_manager
|
|
|
|
|
|
|
|
km = wm.keyconfigs.addon.keymaps.new(name="Node Editor", space_type="NODE_EDITOR")
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
for i in range(10):
|
|
|
|
kmi = km.keymap_items.new("rigpicker.fit_picker", type=f"NUMPAD_{i}", value="PRESS")
|
|
|
|
kmi.properties.index = i - 1
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("rigpicker.call_operator", type="NUMPAD_PERIOD", value="PRESS")
|
|
|
|
kmi.properties.operator = "bpy.ops.view3d.view_selected()"
|
|
|
|
kmi.properties.view_3d = True
|
2022-04-06 10:12:32 +02:00
|
|
|
keymaps.append((km, kmi))
|
2024-02-19 11:53:15 +01:00
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
kmi = km.keymap_items.new("rigpicker.call_operator", type="A", value="PRESS")
|
|
|
|
kmi.properties.operator = "bpy.ops.pose.select_all(action='SELECT')"
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("rigpicker.call_operator", type="A", value="PRESS", alt=True)
|
|
|
|
kmi.properties.operator = "bpy.ops.pose.select_all(action='DESELECT')"
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("rigpicker.toogle_bone_layer", type="LEFTMOUSE", value="DOUBLE_CLICK")
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
kmi = km.keymap_items.new("node.picker_transform", type="G", value="PRESS")
|
|
|
|
kmi.properties.mode = 'TRANSLATE'
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("node.picker_transform", type="R", value="PRESS")
|
|
|
|
kmi.properties.mode = 'ROTATE'
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("node.picker_transform", type="S", value="PRESS")
|
|
|
|
kmi.properties.mode = 'SCALE'
|
2022-04-06 10:12:32 +02:00
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
2023-11-09 10:29:56 +01:00
|
|
|
kmi = km.keymap_items.new("node.context_menu_picker", type="RIGHTMOUSE", value="PRESS")
|
2022-04-06 10:12:32 +02:00
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
|
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS")
|
|
|
|
kmi.properties.mode = 'SET'
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS", shift=True)
|
|
|
|
kmi.properties.mode = 'EXTEND'
|
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
|
|
|
#kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS", ctrl=True)
|
|
|
|
kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS", alt=True)
|
|
|
|
kmi.properties.mode = 'SUBSTRACT'
|
2024-02-19 11:53:15 +01:00
|
|
|
keymaps.append((km, kmi))
|
2022-04-06 10:12:32 +02:00
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
#km = wm.keyconfigs.addon.keymaps.new(name="View2D")
|
|
|
|
kmi = km.keymap_items.new("rigpicker.call_operator", type="MIDDLEMOUSE", value="PRESS")
|
|
|
|
kmi.properties.operator = "bpy.ops.view2d.pan('INVOKE_DEFAULT')"
|
2022-04-06 10:12:32 +02:00
|
|
|
keymaps.append((km, kmi))
|
|
|
|
|
2024-02-19 11:53:15 +01:00
|
|
|
|
2022-04-06 10:12:32 +02:00
|
|
|
def unregister_keymaps():
|
|
|
|
for km, kmi in keymaps:
|
|
|
|
km.keymap_items.remove(kmi)
|
|
|
|
keymaps.clear()
|
|
|
|
|
|
|
|
classes = (
|
|
|
|
RP_OT_box_select,
|
|
|
|
RP_OT_function_execute,
|
|
|
|
RP_OT_reload_picker,
|
|
|
|
RP_OT_toogle_bone_layer,
|
|
|
|
RP_OT_call_operator,
|
|
|
|
RP_MT_context_menu,
|
2023-11-09 10:29:56 +01:00
|
|
|
RP_OT_picker_transform,
|
|
|
|
RP_OT_context_menu_picker,
|
2024-02-19 11:53:15 +01:00
|
|
|
RP_OT_pack_picker,
|
|
|
|
RP_OT_add_picker_source,
|
|
|
|
RP_OT_remove_picker_source,
|
|
|
|
RP_OT_fit_picker
|
2022-04-06 10:12:32 +02:00
|
|
|
#RP_OT_ui_draw
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def register():
|
|
|
|
for cls in classes:
|
|
|
|
bpy.utils.register_class(cls)
|
|
|
|
|
|
|
|
register_keymaps()
|
|
|
|
|
|
|
|
def unregister():
|
|
|
|
unregister_keymaps()
|
|
|
|
for cls in reversed(classes):
|
|
|
|
bpy.utils.unregister_class(cls)
|