Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
c7df358fe8 | |||
|
21c4fe2117 | ||
|
f35fbb95b8 | ||
30064faf3d | |||
f4f8ee1613 | |||
e6c9dde63c | |||
e1abb88b7e | |||
747cfa0f7a | |||
fbdd994d67 | |||
7d2216bc3b | |||
b4defc1296 | |||
6798053389 | |||
de3b78e741 | |||
76ea717df8 | |||
|
7d2d69ba0f | ||
|
75bc414e26 |
@ -2,6 +2,8 @@
|
|||||||
> Blender addon for picking rig contollers
|
> Blender addon for picking rig contollers
|
||||||
|
|
||||||
Rig_picker is an OpenGl tool for having a 2d interface for the 3d animators allowing them to pick a controller easily.
|
Rig_picker is an OpenGl tool for having a 2d interface for the 3d animators allowing them to pick a controller easily.
|
||||||
|
The addon is drawing 2d shapes inside a dedicated Node Editor Area using the gpu module.
|
||||||
|
You can use multiple pickers for one rig, each picker shapes are in there own collection.
|
||||||
|
|
||||||
Video of the previous version : https://vimeo.com/241970235
|
Video of the previous version : https://vimeo.com/241970235
|
||||||
|
|
||||||
@ -23,7 +25,12 @@ Video of the previous version : https://vimeo.com/241970235
|
|||||||
|
|
||||||
<!-- INSTALLATION -->
|
<!-- INSTALLATION -->
|
||||||
## Installation
|
## Installation
|
||||||
|
For external user, you can clone the repository using:
|
||||||
|
```sh
|
||||||
|
git clone https://git.autourdeminuit.com/autour_de_minuit/rig_picker.git
|
||||||
|
```
|
||||||
|
|
||||||
|
For Internal user:
|
||||||
1. Create your own local directory in
|
1. Create your own local directory in
|
||||||
```sh
|
```sh
|
||||||
/home/<USER>/dev
|
/home/<USER>/dev
|
||||||
|
@ -459,7 +459,7 @@ class Picker:
|
|||||||
if shape.type == 'bone' and shape.hover:
|
if shape.type == 'bone' and shape.hover:
|
||||||
shape.assign_bone_event()
|
shape.assign_bone_event()
|
||||||
|
|
||||||
bpy.ops._rigpicker.save_picker(index=self.index)
|
bpy.ops.rigpicker.save_picker(index=self.index)
|
||||||
|
|
||||||
def press_event(self, mode='SET'):
|
def press_event(self, mode='SET'):
|
||||||
for shape in self.shapes:
|
for shape in self.shapes:
|
||||||
@ -712,7 +712,7 @@ class PickerGroup:
|
|||||||
|
|
||||||
def load_picker_data(rig):
|
def load_picker_data(rig):
|
||||||
if 'pickers' in rig.data.rig_picker:
|
if 'pickers' in rig.data.rig_picker:
|
||||||
picker_datas = [p.to_dict() for p in rig.rig_picker['pickers']]
|
picker_datas = [[s.to_dict() for s in p] for p in rig.data.rig_picker['pickers']]
|
||||||
else:
|
else:
|
||||||
picker_datas = []
|
picker_datas = []
|
||||||
|
|
||||||
@ -736,8 +736,11 @@ def get_picker_path(rig, source, start=None):
|
|||||||
|
|
||||||
|
|
||||||
def pack_picker(rig, start=None):
|
def pack_picker(rig, start=None):
|
||||||
|
if not 'rig_picker' in rig.data:
|
||||||
|
return
|
||||||
|
|
||||||
pickers = []
|
pickers = []
|
||||||
for picker_source in rig.data.get('rig_picker', {}).get('sources', {}):
|
for picker_source in rig.data['rig_picker'].get('sources', []):
|
||||||
picker_path = get_picker_path(rig, picker_source['source'], start)
|
picker_path = get_picker_path(rig, picker_source['source'], start)
|
||||||
if not picker_path.exists():
|
if not picker_path.exists():
|
||||||
print(f'{picker_path} not exists')
|
print(f'{picker_path} not exists')
|
||||||
|
@ -93,7 +93,7 @@ def get_shape_data(ob, matrix=None, depsgraph=None):
|
|||||||
|
|
||||||
for vert in mesh.vertices:
|
for vert in mesh.vertices:
|
||||||
co = matrix @ (ob.matrix_world @ Vector(vert.co))
|
co = matrix @ (ob.matrix_world @ Vector(vert.co))
|
||||||
points.append([round(co[0]), round(co[1])])
|
points.append([round(co[0], 1), round(co[1], 1)])
|
||||||
|
|
||||||
depths += [co[2]]
|
depths += [co[2]]
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ def get_picker_data(collection):
|
|||||||
|
|
||||||
canvas_coords = [canvas.matrix_world@Vector((p.co)) for p in canvas_points]
|
canvas_coords = [canvas.matrix_world@Vector((p.co)) for p in canvas_points]
|
||||||
|
|
||||||
height = abs(max(canvas_coords).y - min(canvas_coords).y)
|
height = abs(max(co.y for co in canvas_coords) - min(co.y for co in canvas_coords))
|
||||||
width = abs(max(canvas_coords).x - min(canvas_coords).x)
|
width = abs(max(co.x for co in canvas_coords) - min(co.x for co in canvas_coords))
|
||||||
|
|
||||||
center = sum(canvas_coords, Vector()) / len(canvas_coords)
|
center = sum(canvas_coords, Vector()) / len(canvas_coords)
|
||||||
scale = 2048 / max(height, width)# Reference height for the canvas
|
scale = 2048 / max(height, width)# Reference height for the canvas
|
||||||
|
235
gizmo.py
235
gizmo.py
@ -3,13 +3,10 @@ import bpy
|
|||||||
|
|
||||||
from bpy.props import (IntProperty, EnumProperty, BoolProperty)
|
from bpy.props import (IntProperty, EnumProperty, BoolProperty)
|
||||||
from bpy.types import (AddonPreferences, GizmoGroup, Operator, Gizmo)
|
from bpy.types import (AddonPreferences, GizmoGroup, Operator, Gizmo)
|
||||||
import gpu
|
|
||||||
from mathutils import Vector, Matrix, Euler
|
|
||||||
from gpu_extras.batch import batch_for_shader
|
|
||||||
|
|
||||||
from .constants import PICKERS, SHADERS
|
from mathutils import Vector, Matrix, Euler
|
||||||
|
from .constants import PICKERS
|
||||||
from .core.picker import Picker
|
from .core.picker import Picker
|
||||||
from .core.geometry_utils import bounding_rect
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -41,133 +38,14 @@ class RP_OT_simple_operator(bpy.types.Operator):
|
|||||||
print('Select Shape')
|
print('Select Shape')
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
'''
|
'''
|
||||||
'''
|
|
||||||
class RP_OT_box_select(Operator):
|
|
||||||
"""Box Select bones in the picker view"""
|
|
||||||
bl_idname = "node.rp_box_select"
|
|
||||||
bl_label = "Picker Box Select"
|
|
||||||
|
|
||||||
mode: EnumProperty(items=[(i, i.title(), '') for i in ('SET', 'EXTEND', 'SUBSTRACT')])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
if not is_picker_space(context.space_data):
|
|
||||||
return
|
|
||||||
|
|
||||||
ob = context.object
|
|
||||||
return ob and ob in PICKERS
|
|
||||||
|
|
||||||
def draw_callback(self):
|
|
||||||
#print('draw callback border')
|
|
||||||
if not self.draw_border:
|
|
||||||
return
|
|
||||||
|
|
||||||
gpu.state.blend_set('ALPHA')
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
gpu.state.blend_set('NONE')
|
|
||||||
|
|
||||||
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.color_shader = gpu.shader.from_builtin('UNIFORM_COLOR')
|
|
||||||
self.dash_shader = SHADERS['dashed_line']
|
|
||||||
self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(self.draw_callback, (), '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
|
|
||||||
|
|
||||||
self.border = bounding_rect((self.start_mouse, self.mouse))
|
|
||||||
|
|
||||||
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(context)
|
|
||||||
|
|
||||||
return {'RUNNING_MODAL'}
|
|
||||||
|
|
||||||
def release_event(self, context):
|
|
||||||
scn = context.scene
|
|
||||||
|
|
||||||
if scn.rig_picker.use_pick_bone:
|
|
||||||
self.picker.assign_bone_event()
|
|
||||||
|
|
||||||
elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]):
|
|
||||||
self.picker.border_select(self.border, self.mode)
|
|
||||||
else:
|
|
||||||
self.picker.move_event(self.mouse)
|
|
||||||
self.picker.release_event(self.mode)
|
|
||||||
|
|
||||||
bpy.ops.ed.undo_push(message="Box Select")
|
|
||||||
|
|
||||||
return self.exit(context)
|
|
||||||
|
|
||||||
def exit(self, context):
|
|
||||||
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
|
|
||||||
context.region.tag_redraw()
|
|
||||||
return {'FINISHED'}
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RP_GT_gizmo(Gizmo):
|
class RP_GT_gizmo(Gizmo):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mode_from_event(self, event):
|
|
||||||
if event.alt:
|
|
||||||
return 'SUBSTRACT'
|
|
||||||
elif event.ctrl or event.shift:
|
|
||||||
return 'EXTEND'
|
|
||||||
else:
|
|
||||||
return 'SET'
|
|
||||||
|
|
||||||
def test_select(self, context, location):
|
def test_select(self, context, location):
|
||||||
ob = context.object
|
ob = context.object
|
||||||
|
|
||||||
@ -176,109 +54,41 @@ class RP_GT_gizmo(Gizmo):
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
picker.move_event(location)
|
picker.move_event(location)
|
||||||
|
|
||||||
|
#if bpy.app.timers.is_registered(tooltip):
|
||||||
|
# bpy.app.timers.unregister(tooltip)
|
||||||
|
#context.region.tag_redraw()
|
||||||
|
|
||||||
|
#picker.tooltip_event(event='START')
|
||||||
|
#bpy.app.timers.register(partial(tooltip, context.region), first_interval=1)
|
||||||
|
|
||||||
|
#print(location)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
context.region.tag_redraw()
|
context.region.tag_redraw()
|
||||||
|
|
||||||
return 1
|
#print(location)
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
|
|
||||||
print('DRAW_SELECT', self.border)
|
|
||||||
|
|
||||||
if not self.draw_border:
|
|
||||||
return
|
return
|
||||||
|
'''
|
||||||
gpu.state.blend_set('ALPHA')
|
|
||||||
gpu.state.depth_test_set('ALWAYS')
|
|
||||||
gpu.state.depth_mask_set(False)
|
|
||||||
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
#gpu.state.depth_mask_set(False)
|
|
||||||
gpu.state.blend_set('NONE')
|
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
||||||
|
|
||||||
print(self)
|
|
||||||
|
|
||||||
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.color_shader = gpu.shader.from_builtin('UNIFORM_COLOR')
|
|
||||||
self.dash_shader = SHADERS['dashed_line']
|
|
||||||
#self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(self.draw_callback, (), 'WINDOW', 'POST_PIXEL')
|
|
||||||
|
|
||||||
self.border = [(0, 0), (0, 0), (0, 0), (0, 0)]
|
|
||||||
#context.window_manager.modal_handler_add(self)
|
|
||||||
self.mode = self.mode_from_event(event)
|
|
||||||
self.picker.press_event(self.mode)
|
|
||||||
context.region.tag_redraw()
|
|
||||||
|
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
def modal(self, context, event, tweak):
|
def modal(self, context, event, tweak):
|
||||||
#print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
print(f'invoke: type={event.type}, value={event.value}, ctrl={event.ctrl}, shift={event.shift}, alt={event.alt}')
|
||||||
|
|
||||||
self.mouse = event.mouse_region_x, event.mouse_region_y
|
|
||||||
|
|
||||||
self.border = bounding_rect((self.start_mouse, self.mouse))
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
context.region.tag_redraw()
|
|
||||||
#self.draw(context)
|
|
||||||
|
|
||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
def exit(self, context, cancel):
|
def exit(self, context, cancel):
|
||||||
scn = context.scene
|
print('EXIT')
|
||||||
|
|
||||||
if scn.rig_picker.use_pick_bone:
|
|
||||||
self.picker.assign_bone_event()
|
|
||||||
|
|
||||||
elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]):
|
|
||||||
self.picker.border_select(self.border, self.mode)
|
|
||||||
else:
|
|
||||||
self.picker.move_event(self.mouse)
|
|
||||||
self.picker.release_event(self.mode)
|
|
||||||
|
|
||||||
bpy.ops.ed.undo_push(message="Box Select")
|
|
||||||
self.draw_border = False
|
|
||||||
context.region.tag_redraw()
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -296,9 +106,6 @@ class RP_GT_gizmogroup(GizmoGroup):
|
|||||||
|
|
||||||
def setup(self, context):
|
def setup(self, context):
|
||||||
self.gizmo = self.gizmos.new("RP_GT_gizmo")
|
self.gizmo = self.gizmos.new("RP_GT_gizmo")
|
||||||
self.gizmo.draw_border = False
|
|
||||||
self.gizmo.border = []
|
|
||||||
self.gizmo.use_draw_modal = True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,9 +130,8 @@ class RP_OT_box_select(Operator):
|
|||||||
return {'RUNNING_MODAL'}
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
def release_event(self, context):
|
def release_event(self, context):
|
||||||
scn = context.scene
|
|
||||||
|
|
||||||
if scn.rig_picker.use_pick_bone:
|
if get_picker_collection():
|
||||||
self.picker.assign_bone_event()
|
self.picker.assign_bone_event()
|
||||||
|
|
||||||
elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]):
|
elif (self.start_mouse[0] != self.mouse[0] or self.start_mouse[1] != self.mouse[1]):
|
||||||
@ -392,24 +391,19 @@ class RP_OT_reload_picker(Operator):
|
|||||||
# return
|
# return
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
#PICKERS.clear()
|
|
||||||
if context.object.type == 'ARMATURE':
|
if context.object.type == 'ARMATURE':
|
||||||
rig = context.object
|
rig = context.object
|
||||||
else:
|
else:
|
||||||
collection = get_picker_collection(context.object)
|
collection = get_picker_collection(context.object)
|
||||||
rig = collection.rig_picker.rig
|
rig = collection.rig_picker.rig
|
||||||
|
|
||||||
|
#print('Reload', rig)
|
||||||
load_picker_data(rig)
|
load_picker_data(rig)
|
||||||
|
|
||||||
'''
|
|
||||||
for area in context.screen.areas:
|
for area in context.screen.areas:
|
||||||
#print(area.type, is_picker_space(area.spaces.active))
|
|
||||||
if is_picker_space(area.spaces.active):
|
if is_picker_space(area.spaces.active):
|
||||||
|
|
||||||
print('Tag Redraw Region', area.type)
|
|
||||||
area.regions[0].tag_redraw()
|
|
||||||
area.tag_redraw()
|
area.tag_redraw()
|
||||||
'''
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@ -551,7 +545,8 @@ class RP_MT_context_menu(Menu):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
col.use_property_split = True
|
col.operator_context = 'INVOKE_DEFAULT'
|
||||||
|
#col.use_property_split = True
|
||||||
|
|
||||||
ob = context.object
|
ob = context.object
|
||||||
picker = PICKERS.get(ob)
|
picker = PICKERS.get(ob)
|
||||||
@ -561,9 +556,25 @@ class RP_MT_context_menu(Menu):
|
|||||||
else:
|
else:
|
||||||
bone = context.active_pose_bone
|
bone = context.active_pose_bone
|
||||||
|
|
||||||
|
# Draw Space Switch Operator
|
||||||
|
if getattr(ob.data, 'space_switch'):
|
||||||
|
space_switch = ob.data.space_switch
|
||||||
|
|
||||||
|
data_paths = [f'pose.bones["{bone.name}"]["{k}"]' for k in bone.keys()]
|
||||||
|
space_bone = next((s for s in space_switch.bones if s.data_path in data_paths), None)
|
||||||
|
if space_bone:
|
||||||
|
|
||||||
|
index = list(space_switch.bones).index(space_bone)
|
||||||
|
value = ob.path_resolve(space_bone.data_path)
|
||||||
|
space = next((s.name for s in space_bone.spaces if s.value == value), None)
|
||||||
|
|
||||||
|
op = col.operator("spaceswitch.change_space", text=f'({space})', icon='PINNED')
|
||||||
|
op.index=index
|
||||||
|
col.separator()
|
||||||
|
|
||||||
if bone:
|
if bone:
|
||||||
for key in bone.keys():
|
for key in bone.keys():
|
||||||
layout.prop(bone,f'["{key}"]', slider=True)
|
col.prop(bone,f'["{key}"]', slider=True)
|
||||||
|
|
||||||
#layout.operator("rigpicker.show_bone_layer", text="Show Bone Layer", ).type = 'ACTIVE'
|
#layout.operator("rigpicker.show_bone_layer", text="Show Bone Layer", ).type = 'ACTIVE'
|
||||||
#layout.operator("rigidbody.objects_add", text="B Add Passive").type = 'PASSIVE'
|
#layout.operator("rigidbody.objects_add", text="B Add Passive").type = 'PASSIVE'
|
||||||
@ -755,7 +766,7 @@ def register_keymaps():
|
|||||||
|
|
||||||
kmi = km.keymap_items.new("node.context_menu_picker", type="RIGHTMOUSE", value="PRESS")
|
kmi = km.keymap_items.new("node.context_menu_picker", type="RIGHTMOUSE", value="PRESS")
|
||||||
keymaps.append((km, kmi))
|
keymaps.append((km, kmi))
|
||||||
'''
|
|
||||||
kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS")
|
kmi = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS")
|
||||||
kmi.properties.mode = 'SET'
|
kmi.properties.mode = 'SET'
|
||||||
keymaps.append((km, kmi))
|
keymaps.append((km, kmi))
|
||||||
@ -764,10 +775,11 @@ def register_keymaps():
|
|||||||
kmi.properties.mode = 'EXTEND'
|
kmi.properties.mode = 'EXTEND'
|
||||||
keymaps.append((km, kmi))
|
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 = km.keymap_items.new("node.rp_box_select", type="LEFTMOUSE", value="PRESS", alt=True)
|
||||||
kmi.properties.mode = 'SUBSTRACT'
|
kmi.properties.mode = 'SUBSTRACT'
|
||||||
keymaps.append((km, kmi))
|
keymaps.append((km, kmi))
|
||||||
'''
|
|
||||||
#km = wm.keyconfigs.addon.keymaps.new(name="View2D")
|
#km = wm.keyconfigs.addon.keymaps.new(name="View2D")
|
||||||
#kmi = km.keymap_items.new("rigpicker.call_operator", type="MIDDLEMOUSE", value="PRESS")
|
#kmi = km.keymap_items.new("rigpicker.call_operator", type="MIDDLEMOUSE", value="PRESS")
|
||||||
#kmi.properties.operator = "bpy.ops.view2d.pan('INVOKE_DEFAULT')"
|
#kmi.properties.operator = "bpy.ops.view2d.pan('INVOKE_DEFAULT')"
|
||||||
|
@ -21,6 +21,14 @@ class RP_OT_create_shape(Operator):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return (context.object and context.object.mode == 'POSE')
|
return (context.object and context.object.mode == 'POSE')
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
for col in bpy.data.collections:
|
||||||
|
if col.rig_picker.enabled:
|
||||||
|
self.layout.prop(col.rig_picker, 'link_shape', text=col.name)
|
||||||
|
|
||||||
def execute(self,context):
|
def execute(self,context):
|
||||||
scn = context.scene
|
scn = context.scene
|
||||||
vl = context.view_layer
|
vl = context.view_layer
|
||||||
@ -40,8 +48,10 @@ class RP_OT_create_shape(Operator):
|
|||||||
|
|
||||||
mesh.from_pydata(verts, edges, faces)
|
mesh.from_pydata(verts, edges, faces)
|
||||||
|
|
||||||
for c in scn.rig_picker.canvas.users_collection:
|
picker_selected_cols = [col for col in bpy.data.collections if col.rig_picker.link_shape]
|
||||||
c.objects.link(ob)
|
|
||||||
|
for col in picker_selected_cols or [scn.collection]:
|
||||||
|
col.objects.link(ob)
|
||||||
|
|
||||||
ob.location.z = 0.05
|
ob.location.z = 0.05
|
||||||
ob.location.x = offset
|
ob.location.x = offset
|
||||||
@ -60,16 +70,16 @@ class RP_OT_create_shape(Operator):
|
|||||||
class RP_OT_name_from_bone(Operator):
|
class RP_OT_name_from_bone(Operator):
|
||||||
bl_label = 'Name Shape from selected bones'
|
bl_label = 'Name Shape from selected bones'
|
||||||
bl_idname = 'rigpicker.name_from_bone'
|
bl_idname = 'rigpicker.name_from_bone'
|
||||||
|
bl_description = 'Rename all shapes from related bones name'
|
||||||
#bl_options = {'REGISTER', 'UNDO'}
|
#bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
def execute(self,context):
|
def execute(self,context):
|
||||||
scene = context.scene
|
|
||||||
rig = scene.rig_picker.rig
|
|
||||||
bone = rig.data.bones.active
|
|
||||||
|
|
||||||
if bone:
|
col = get_picker_collection(context.object)
|
||||||
context.object.name = bone.name
|
|
||||||
context.object.rig_picker.name = bone.name
|
for ob in col.all_objects:
|
||||||
|
if ob.rig_picker.shape_type == 'BONE':
|
||||||
|
ob.name = ob.rig_picker.name
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -84,9 +94,7 @@ class RP_OT_mirror_shape(Operator):
|
|||||||
return (context.object and context.object.type in ('MESH', 'CURVE', 'TEXT'))
|
return (context.object and context.object.type in ('MESH', 'CURVE', 'TEXT'))
|
||||||
|
|
||||||
def execute(self,context):
|
def execute(self,context):
|
||||||
scn = context.scene
|
collection = get_picker_collection(context.object)
|
||||||
ob = context.object
|
|
||||||
collection = get_picker_collection(ob)
|
|
||||||
objects = context.selected_objects
|
objects = context.selected_objects
|
||||||
|
|
||||||
# Remove mirror object:
|
# Remove mirror object:
|
||||||
@ -95,7 +103,7 @@ class RP_OT_mirror_shape(Operator):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
for mod in ob.modifiers:
|
for mod in ob.modifiers:
|
||||||
if (mod.type == 'NODES' and mod.node_group.name == 'Symmetrize' and
|
if (mod.type == 'NODES' and mod.node_group and mod.node_group.name == 'Symmetrize' and
|
||||||
mod.get('Socket_2') in objects):
|
mod.get('Socket_2') in objects):
|
||||||
|
|
||||||
bpy.data.objects.remove(ob)
|
bpy.data.objects.remove(ob)
|
||||||
@ -124,7 +132,7 @@ class RP_OT_mirror_shape(Operator):
|
|||||||
for mod in list(flipped_object.modifiers):
|
for mod in list(flipped_object.modifiers):
|
||||||
flipped_object.modifiers.remove(mod)
|
flipped_object.modifiers.remove(mod)
|
||||||
|
|
||||||
# Add symmetrize modifier
|
# Add symmetrize modifier TODO add it into a resource
|
||||||
mod = flipped_object.modifiers.new(name='Symmetrize', type='NODES')
|
mod = flipped_object.modifiers.new(name='Symmetrize', type='NODES')
|
||||||
mod.node_group = bpy.data.node_groups['Symmetrize']
|
mod.node_group = bpy.data.node_groups['Symmetrize']
|
||||||
mod['Socket_2'] = ob
|
mod['Socket_2'] = ob
|
||||||
@ -222,7 +230,6 @@ class RP_OT_save_picker(Operator):
|
|||||||
|
|
||||||
bpy.ops.rigpicker.reload_picker()
|
bpy.ops.rigpicker.reload_picker()
|
||||||
|
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
|
@ -44,14 +44,17 @@ class RP_PG_object_ui_settings(bpy.types.PropertyGroup):
|
|||||||
name: StringProperty()
|
name: StringProperty()
|
||||||
|
|
||||||
|
|
||||||
class RP_PG_scene_ui_settings(bpy.types.PropertyGroup):
|
class RP_PG_collection_ui_settings(bpy.types.PropertyGroup):
|
||||||
enabled : BoolProperty(default=False)
|
enabled : BoolProperty(default=False)
|
||||||
rig: PointerProperty(type=bpy.types.Object)
|
rig: PointerProperty(type=bpy.types.Object)
|
||||||
canvas: PointerProperty(type=bpy.types.Object)
|
canvas: PointerProperty(type=bpy.types.Object)
|
||||||
symmetry: PointerProperty(type=bpy.types.Object)
|
symmetry: PointerProperty(type=bpy.types.Object)
|
||||||
#idname: EnumProperty(items=[])
|
|
||||||
destination: StringProperty(subtype='FILE_PATH')
|
destination: StringProperty(subtype='FILE_PATH')
|
||||||
#bone_list: bpy.props.EnumProperty(items = bones_item
|
use_pick_bone : BoolProperty(default=False)
|
||||||
|
link_shape : BoolProperty(default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class RP_PG_scene_ui_settings(bpy.types.PropertyGroup):
|
||||||
use_pick_bone : BoolProperty(default=False)
|
use_pick_bone : BoolProperty(default=False)
|
||||||
|
|
||||||
|
|
||||||
@ -78,6 +81,7 @@ class RP_OT_operator_selector(bpy.types.Operator):
|
|||||||
classes = (
|
classes = (
|
||||||
RP_PG_picker_source,
|
RP_PG_picker_source,
|
||||||
RP_PG_object_ui_settings,
|
RP_PG_object_ui_settings,
|
||||||
|
RP_PG_collection_ui_settings,
|
||||||
RP_PG_scene_ui_settings,
|
RP_PG_scene_ui_settings,
|
||||||
RP_PG_armature_ui_settings,
|
RP_PG_armature_ui_settings,
|
||||||
RP_OT_operator_selector,
|
RP_OT_operator_selector,
|
||||||
@ -89,11 +93,12 @@ def register():
|
|||||||
|
|
||||||
bpy.types.Armature.rig_picker = bpy.props.PointerProperty(type=RP_PG_armature_ui_settings)
|
bpy.types.Armature.rig_picker = bpy.props.PointerProperty(type=RP_PG_armature_ui_settings)
|
||||||
bpy.types.Object.rig_picker = bpy.props.PointerProperty(type=RP_PG_object_ui_settings)
|
bpy.types.Object.rig_picker = bpy.props.PointerProperty(type=RP_PG_object_ui_settings)
|
||||||
|
bpy.types.Collection.rig_picker = bpy.props.PointerProperty(type=RP_PG_collection_ui_settings)
|
||||||
bpy.types.Scene.rig_picker = bpy.props.PointerProperty(type=RP_PG_scene_ui_settings)
|
bpy.types.Scene.rig_picker = bpy.props.PointerProperty(type=RP_PG_scene_ui_settings)
|
||||||
bpy.types.Collection.rig_picker = bpy.props.PointerProperty(type=RP_PG_scene_ui_settings)
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
del bpy.types.Scene.rig_picker
|
del bpy.types.Scene.rig_picker
|
||||||
|
del bpy.types.Collection.rig_picker
|
||||||
del bpy.types.Object.rig_picker
|
del bpy.types.Object.rig_picker
|
||||||
del bpy.types.Armature.rig_picker
|
del bpy.types.Armature.rig_picker
|
||||||
|
|
||||||
|
6
ui.py
6
ui.py
@ -91,8 +91,12 @@ class RP_PT_shape(bpy.types.Panel):
|
|||||||
row = col.row(align=True)
|
row = col.row(align=True)
|
||||||
row.operator('rigpicker.create_shape', icon='MESH_DATA', text='Create Shape')
|
row.operator('rigpicker.create_shape', icon='MESH_DATA', text='Create Shape')
|
||||||
row.operator('rigpicker.mirror_shape', icon='MOD_MIRROR', text='Mirror Shape')
|
row.operator('rigpicker.mirror_shape', icon='MOD_MIRROR', text='Mirror Shape')
|
||||||
col.operator('rigpicker.name_from_bone', icon='SORTALPHA' , text='Name From Bones')
|
|
||||||
col.prop(scn.rig_picker, 'use_pick_bone', icon='EYEDROPPER', text='Auto Bone Assign')
|
col.prop(scn.rig_picker, 'use_pick_bone', icon='EYEDROPPER', text='Auto Bone Assign')
|
||||||
|
col.operator('rigpicker.name_from_bone', icon='SORTALPHA' , text='Name From Bones')
|
||||||
|
else:
|
||||||
|
col = layout.column(align=True)
|
||||||
|
row = col.row(align=True)
|
||||||
|
row.operator('rigpicker.create_shape', icon='MESH_DATA', text='Create Shape')
|
||||||
|
|
||||||
if ob.type != 'ARMATURE':
|
if ob.type != 'ARMATURE':
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user