backport cursor follow fix from gpv3 - add msg_bus on selection change owned by GreasePencil type
3.3.2 - added: fix cursor follow and add optional target object (backported from gpv3)gpv2
parent
e51cc474d6
commit
cca9494ae4
|
@ -1,10 +1,15 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
GPv2
|
3.3.2
|
||||||
|
|
||||||
|
- added: fix cursor follow and add optional target object (backported from gpv3)
|
||||||
|
|
||||||
3.3.1
|
3.3.1
|
||||||
|
|
||||||
- added: improve file checker and visibility conflict feature (backported from gpv3)
|
- added: improve file checker and visibility conflict feature (backported from gpv3)
|
||||||
|
|
||||||
|
-- GPv2 code - Above this line, version is separated from 4.3+ version (using GPv3) --
|
||||||
|
|
||||||
3.3.0
|
3.3.0
|
||||||
|
|
||||||
- added: `Move Material To Layer` has now option to copy instead of moving in pop-up menu.
|
- added: `Move Material To Layer` has now option to copy instead of moving in pop-up menu.
|
||||||
|
|
|
@ -3,6 +3,7 @@ import bpy
|
||||||
import mathutils
|
import mathutils
|
||||||
from bpy_extras import view3d_utils
|
from bpy_extras import view3d_utils
|
||||||
from .utils import get_gp_draw_plane, region_to_location, get_view_origin_position
|
from .utils import get_gp_draw_plane, region_to_location, get_view_origin_position
|
||||||
|
from bpy.app.handlers import persistent
|
||||||
|
|
||||||
## override all sursor snap shortcut with this in keymap
|
## override all sursor snap shortcut with this in keymap
|
||||||
class GPTB_OT_cusor_snap(bpy.types.Operator):
|
class GPTB_OT_cusor_snap(bpy.types.Operator):
|
||||||
|
@ -110,15 +111,20 @@ prev_matrix = None
|
||||||
|
|
||||||
# @call_once(bpy.app.handlers.frame_change_post)
|
# @call_once(bpy.app.handlers.frame_change_post)
|
||||||
|
|
||||||
def cursor_follow_update(self,context):
|
## used in properties file to register in boolprop update
|
||||||
|
def cursor_follow_update(self, context):
|
||||||
'''append or remove cursor_follow handler according a boolean'''
|
'''append or remove cursor_follow handler according a boolean'''
|
||||||
|
ob = bpy.context.object
|
||||||
|
if bpy.context.scene.gptoolprops.cursor_follow_target:
|
||||||
|
## override with target object is specified
|
||||||
|
ob = bpy.context.scene.gptoolprops.cursor_follow_target
|
||||||
global prev_matrix
|
global prev_matrix
|
||||||
# imported in properties to register in boolprop update
|
# imported in properties to register in boolprop update
|
||||||
if self.cursor_follow:#True
|
if self.cursor_follow:#True
|
||||||
|
if ob:
|
||||||
|
# out of below condition to be called when setting target as well
|
||||||
|
prev_matrix = ob.matrix_world.copy()
|
||||||
if not cursor_follow.__name__ in [hand.__name__ for hand in bpy.app.handlers.frame_change_post]:
|
if not cursor_follow.__name__ in [hand.__name__ for hand in bpy.app.handlers.frame_change_post]:
|
||||||
if context.object:
|
|
||||||
prev_matrix = context.object.matrix_world
|
|
||||||
|
|
||||||
bpy.app.handlers.frame_change_post.append(cursor_follow)
|
bpy.app.handlers.frame_change_post.append(cursor_follow)
|
||||||
|
|
||||||
else:#False
|
else:#False
|
||||||
|
@ -129,11 +135,13 @@ def cursor_follow_update(self,context):
|
||||||
|
|
||||||
def cursor_follow(scene):
|
def cursor_follow(scene):
|
||||||
'''Handler to make the cursor follow active object matrix changes on frame change'''
|
'''Handler to make the cursor follow active object matrix changes on frame change'''
|
||||||
## TODO update global prev_matrix to equal current_matrix on selection change (need another handler)...
|
ob = bpy.context.object
|
||||||
if not bpy.context.object:
|
if bpy.context.scene.gptoolprops.cursor_follow_target:
|
||||||
|
## override with target object is specified
|
||||||
|
ob = bpy.context.scene.gptoolprops.cursor_follow_target
|
||||||
|
if not ob:
|
||||||
return
|
return
|
||||||
global prev_matrix
|
global prev_matrix
|
||||||
ob = bpy.context.object
|
|
||||||
current_matrix = ob.matrix_world
|
current_matrix = ob.matrix_world
|
||||||
if not prev_matrix:
|
if not prev_matrix:
|
||||||
prev_matrix = current_matrix.copy()
|
prev_matrix = current_matrix.copy()
|
||||||
|
@ -147,8 +155,6 @@ def cursor_follow(scene):
|
||||||
## translation only
|
## translation only
|
||||||
# scene.cursor.location += (current_matrix - prev_matrix).to_translation()
|
# scene.cursor.location += (current_matrix - prev_matrix).to_translation()
|
||||||
|
|
||||||
# print('offset:', (current_matrix - prev_matrix).to_translation())
|
|
||||||
|
|
||||||
## full
|
## full
|
||||||
scene.cursor.location = current_matrix @ (prev_matrix.inverted() @ scene.cursor.location)
|
scene.cursor.location = current_matrix @ (prev_matrix.inverted() @ scene.cursor.location)
|
||||||
|
|
||||||
|
@ -156,6 +162,38 @@ def cursor_follow(scene):
|
||||||
prev_matrix = current_matrix.copy()
|
prev_matrix = current_matrix.copy()
|
||||||
|
|
||||||
|
|
||||||
|
prev_active_obj = None
|
||||||
|
|
||||||
|
## Add check for object selection change
|
||||||
|
def selection_changed():
|
||||||
|
"""Callback function for selection changes"""
|
||||||
|
if not bpy.context.scene.gptoolprops.cursor_follow:
|
||||||
|
return
|
||||||
|
if bpy.context.scene.gptoolprops.cursor_follow_target:
|
||||||
|
# we are following a target, nothing to update on selection change
|
||||||
|
return
|
||||||
|
global prev_matrix, prev_active_obj
|
||||||
|
if prev_active_obj != bpy.context.object:
|
||||||
|
## Set stored matrix to active object
|
||||||
|
prev_matrix = bpy.context.object.matrix_world.copy()
|
||||||
|
prev_active_obj = bpy.context.object
|
||||||
|
|
||||||
|
## Note: Same owner as layer manager (will be removed as well)
|
||||||
|
def subscribe_object_change():
|
||||||
|
subscribe_to = (bpy.types.LayerObjects, 'active')
|
||||||
|
bpy.msgbus.subscribe_rna(
|
||||||
|
key=subscribe_to,
|
||||||
|
# owner of msgbus subcribe (for clearing later)
|
||||||
|
owner=bpy.types.GreasePencil, # <-- attach to ID during it's lifetime.
|
||||||
|
args=(),
|
||||||
|
notify=selection_changed,
|
||||||
|
options={'PERSISTENT'},
|
||||||
|
)
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def subscribe_object_change_handler(dummy):
|
||||||
|
subscribe_object_change()
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
GPTB_OT_cusor_snap,
|
GPTB_OT_cusor_snap,
|
||||||
)
|
)
|
||||||
|
@ -163,14 +201,18 @@ GPTB_OT_cusor_snap,
|
||||||
def register():
|
def register():
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
|
|
||||||
# swap_keymap_by_id('view3d.cursor3d','view3d.cursor_snap')#auto swap to custom GP snap wrap
|
# swap_keymap_by_id('view3d.cursor3d','view3d.cursor_snap')#auto swap to custom GP snap wrap
|
||||||
|
|
||||||
# bpy.app.handlers.frame_change_post.append(cursor_follow)
|
## Follow cursor matrix update on object change
|
||||||
|
bpy.app.handlers.load_post.append(subscribe_object_change_handler) # select_change
|
||||||
|
## Directly set msgbus to work at first addon activation # select_change
|
||||||
|
bpy.app.timers.register(subscribe_object_change, first_interval=1) # select_change
|
||||||
|
|
||||||
|
## No need to frame_change_post.append(cursor_follow). Added by property update, when activating 'cursor follow'
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
# bpy.app.handlers.frame_change_post.remove(cursor_follow)
|
bpy.app.handlers.load_post.remove(subscribe_object_change_handler) # select_change
|
||||||
|
|
||||||
# swap_keymap_by_id('view3d.cursor_snap','view3d.cursor3d')#Restore normal snap
|
# swap_keymap_by_id('view3d.cursor_snap','view3d.cursor3d')#Restore normal snap
|
||||||
|
|
||||||
|
@ -180,3 +222,5 @@ def unregister():
|
||||||
# force remove handler if it's there at unregister
|
# force remove handler if it's there at unregister
|
||||||
if cursor_follow.__name__ in [hand.__name__ for hand in bpy.app.handlers.frame_change_post]:
|
if cursor_follow.__name__ in [hand.__name__ for hand in bpy.app.handlers.frame_change_post]:
|
||||||
bpy.app.handlers.frame_change_post.remove(cursor_follow)
|
bpy.app.handlers.frame_change_post.remove(cursor_follow)
|
||||||
|
|
||||||
|
bpy.msgbus.clear_by_owner(bpy.types.GreasePencil)
|
|
@ -279,7 +279,8 @@ class GPTB_PT_anim_manager(Panel):
|
||||||
col.use_property_split = False
|
col.use_property_split = False
|
||||||
text, icon = ('Cursor Follow On', 'PIVOT_CURSOR') if context.scene.gptoolprops.cursor_follow else ('Cursor Follow Off', 'CURSOR')
|
text, icon = ('Cursor Follow On', 'PIVOT_CURSOR') if context.scene.gptoolprops.cursor_follow else ('Cursor Follow Off', 'CURSOR')
|
||||||
col.prop(context.scene.gptoolprops, 'cursor_follow', text=text, icon=icon)
|
col.prop(context.scene.gptoolprops, 'cursor_follow', text=text, icon=icon)
|
||||||
|
if context.scene.gptoolprops.cursor_follow:
|
||||||
|
col.prop(context.scene.gptoolprops, 'cursor_follow_target', text='Target', icon='OBJECT_DATA')
|
||||||
|
|
||||||
class GPTB_PT_toolbox_playblast(Panel):
|
class GPTB_PT_toolbox_playblast(Panel):
|
||||||
bl_label = "Playblast"
|
bl_label = "Playblast"
|
||||||
|
|
|
@ -4,7 +4,7 @@ bl_info = {
|
||||||
"name": "GP toolbox",
|
"name": "GP toolbox",
|
||||||
"description": "Tool set for Grease Pencil in animation production",
|
"description": "Tool set for Grease Pencil in animation production",
|
||||||
"author": "Samuel Bernou, Christophe Seux",
|
"author": "Samuel Bernou, Christophe Seux",
|
||||||
"version": (3, 3, 1),
|
"version": (3, 3, 2),
|
||||||
"blender": (4, 0, 0),
|
"blender": (4, 0, 0),
|
||||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
|
|
@ -177,6 +177,11 @@ class GP_PG_ToolsSettings(PropertyGroup):
|
||||||
name='Cursor Follow', description="3D cursor follow active object animation when activated",
|
name='Cursor Follow', description="3D cursor follow active object animation when activated",
|
||||||
default=False, update=cursor_follow_update)
|
default=False, update=cursor_follow_update)
|
||||||
|
|
||||||
|
cursor_follow_target : bpy.props.PointerProperty(
|
||||||
|
name='Cursor Follow Target',
|
||||||
|
description="Optional target object to follow for cursor instead of active object",
|
||||||
|
type=bpy.types.Object, update=cursor_follow_update)
|
||||||
|
|
||||||
edit_lines_opacity : FloatProperty(
|
edit_lines_opacity : FloatProperty(
|
||||||
name="Edit Lines Opacity", description="Change edit lines opacity for all grease pencils",
|
name="Edit Lines Opacity", description="Change edit lines opacity for all grease pencils",
|
||||||
default=0.5, min=0.0, max=1.0, step=3, precision=2, update=change_edit_lines_opacity)
|
default=0.5, min=0.0, max=1.0, step=3, precision=2, update=change_edit_lines_opacity)
|
||||||
|
|
Loading…
Reference in New Issue