remap relative off, realign obj
1.1.0: - Important change : Remap relative is now disabled by default in addon preferences - feat: Add realign operator in sidebar with reproject as true by default - UI: Batch reproject all frames is now in menus. Same places as native reprojectgpv2
parent
492095d333
commit
bf85582f28
|
@ -5,6 +5,15 @@ from math import pi
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
|
||||||
|
def get_scale_matrix(scale):
|
||||||
|
# recreate a neutral mat scale
|
||||||
|
matscale_x = Matrix.Scale(scale[0], 4,(1,0,0))
|
||||||
|
matscale_y = Matrix.Scale(scale[1], 4,(0,1,0))
|
||||||
|
matscale_z = Matrix.Scale(scale[2], 4,(0,0,1))
|
||||||
|
matscale = matscale_x @ matscale_y @ matscale_z
|
||||||
|
return matscale
|
||||||
|
|
||||||
def batch_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False):
|
def batch_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False):
|
||||||
'''Reproject - ops method
|
'''Reproject - ops method
|
||||||
:all_stroke: affect hided, locked layers
|
:all_stroke: affect hided, locked layers
|
||||||
|
@ -23,11 +32,13 @@ def batch_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False
|
||||||
l.lock_frame = False
|
l.lock_frame = False
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode='EDIT_GPENCIL')
|
bpy.ops.object.mode_set(mode='EDIT_GPENCIL')
|
||||||
# TODO : need to toggle visible and unlock all layers before attacking, and store restore.
|
|
||||||
|
|
||||||
for l in obj.data.layers:
|
for l in obj.data.layers:
|
||||||
for f in l.frames:
|
for f in l.frames:
|
||||||
|
if not len(f.strokes):
|
||||||
|
continue
|
||||||
bpy.context.scene.frame_set(f.frame_number)
|
bpy.context.scene.frame_set(f.frame_number)
|
||||||
|
|
||||||
# switch to edit to reproject through ops
|
# switch to edit to reproject through ops
|
||||||
bpy.ops.gpencil.select_all(action='SELECT')
|
bpy.ops.gpencil.select_all(action='SELECT')
|
||||||
bpy.ops.gpencil.reproject(type=proj_type) # default is VIEW
|
bpy.ops.gpencil.reproject(type=proj_type) # default is VIEW
|
||||||
|
@ -211,7 +222,7 @@ class GPTB_OT_realign(bpy.types.Operator):
|
||||||
description='Reproject stroke on the new alignment')
|
description='Reproject stroke on the new alignment')
|
||||||
|
|
||||||
all_strokes : bpy.props.BoolProperty(
|
all_strokes : bpy.props.BoolProperty(
|
||||||
name='All Strokes', default=False,
|
name='All Strokes', default=True,
|
||||||
description='Hided and locked layer will also be reprojected')
|
description='Hided and locked layer will also be reprojected')
|
||||||
|
|
||||||
## add option to bake strokes if rotation anim is not constant ? might generate too many Keyframes
|
## add option to bake strokes if rotation anim is not constant ? might generate too many Keyframes
|
||||||
|
@ -237,13 +248,14 @@ class GPTB_OT_realign(bpy.types.Operator):
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
layout.label(text='Realign the GP : Front axis facing active camera')
|
||||||
if self.alert:
|
if self.alert:
|
||||||
layout.label(text=self.alert, icon='INFO')
|
layout.label(text=self.alert, icon='ERROR')
|
||||||
layout.label(text='(rotations key will be overwritten to face camera)')
|
layout.label(text='(rotations key will be overwritten to face camera)')
|
||||||
|
layout.separator()
|
||||||
layout.prop(self, "reproject")
|
layout.prop(self, "reproject")
|
||||||
layout.label(text='Realign the GP front axis with active camera')
|
|
||||||
if self.reproject:
|
if self.reproject:
|
||||||
|
layout.label(text='After Realigning, reproject each frames on front axis')
|
||||||
if not context.region_data.view_perspective == 'CAMERA':
|
if not context.region_data.view_perspective == 'CAMERA':
|
||||||
layout.label(text='Not in camera ! (reprojection is made from view)', icon='ERROR')
|
layout.label(text='Not in camera ! (reprojection is made from view)', icon='ERROR')
|
||||||
layout.prop(self, "all_strokes")
|
layout.prop(self, "all_strokes")
|
||||||
|
@ -280,10 +292,8 @@ class GPTB_OT_batch_reproject_all_frames(bpy.types.Operator):
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return context.object and context.object.type == 'GPENCIL'
|
return context.object and context.object.type == 'GPENCIL'
|
||||||
|
|
||||||
# reproject : bpy.props.BoolProperty(name='Reproject', default=True)
|
|
||||||
|
|
||||||
all_strokes : bpy.props.BoolProperty(
|
all_strokes : bpy.props.BoolProperty(
|
||||||
name='All Strokes', default=False,
|
name='All Strokes', default=True,
|
||||||
description='Hided and locked layer will also be reprojected')
|
description='Hided and locked layer will also be reprojected')
|
||||||
|
|
||||||
type: bpy.props.EnumProperty(name='Type',
|
type: bpy.props.EnumProperty(name='Type',
|
||||||
|
@ -319,9 +329,18 @@ class GPTB_OT_batch_reproject_all_frames(bpy.types.Operator):
|
||||||
|
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
### -- MENU ENTRY --
|
||||||
|
|
||||||
|
def reproject_clean_menu(self, context):
|
||||||
|
if context.mode == 'EDIT_GPENCIL':
|
||||||
|
self.layout.operator('gp.batch_reproject_all_frames', icon='SMALL_TRI_RIGHT_VEC') # KEYTYPE_JITTER_VEC
|
||||||
|
|
||||||
|
def reproject_context_menu(self, context):
|
||||||
|
if context.mode == 'EDIT_GPENCIL' and context.scene.tool_settings.gpencil_selectmode_edit == 'STROKE':
|
||||||
|
self.layout.operator('gp.batch_reproject_all_frames', icon='SMALL_TRI_RIGHT_VEC') # KEYTYPE_JITTER_VEC
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
# GPTB_OT_realign,
|
GPTB_OT_realign,
|
||||||
GPTB_OT_batch_reproject_all_frames,
|
GPTB_OT_batch_reproject_all_frames,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -329,6 +348,12 @@ def register():
|
||||||
for cl in classes:
|
for cl in classes:
|
||||||
bpy.utils.register_class(cl)
|
bpy.utils.register_class(cl)
|
||||||
|
|
||||||
|
bpy.types.VIEW3D_MT_gpencil_edit_context_menu.append(reproject_context_menu)
|
||||||
|
bpy.types.GPENCIL_MT_cleanup.append(reproject_clean_menu)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
|
bpy.types.GPENCIL_MT_cleanup.remove(reproject_clean_menu)
|
||||||
|
bpy.types.VIEW3D_MT_gpencil_edit_context_menu.remove(reproject_context_menu)
|
||||||
|
|
||||||
for cl in reversed(classes):
|
for cl in reversed(classes):
|
||||||
bpy.utils.unregister_class(cl)
|
bpy.utils.unregister_class(cl)
|
|
@ -112,6 +112,12 @@ Panel in sidebar : 3D view > sidebar 'N' > Gpencil
|
||||||
|
|
||||||
## Changelog:
|
## Changelog:
|
||||||
|
|
||||||
|
1.1.0:
|
||||||
|
|
||||||
|
- Important change : Remap relative is now disabled by default in addon preferences
|
||||||
|
- feat: Add realign operator in sidebar with reproject as true by default
|
||||||
|
- UI: Batch reproject all frames is now in menus. Same places as native reproject
|
||||||
|
|
||||||
1.0.9:
|
1.0.9:
|
||||||
|
|
||||||
- feat: Reproject all frames operator
|
- feat: Reproject all frames operator
|
||||||
|
|
|
@ -167,8 +167,9 @@ class GPTB_PT_sidebar_panel(bpy.types.Panel):
|
||||||
|
|
||||||
layout.prop(context.scene.gptoolprops, 'edit_lines_opacity')
|
layout.prop(context.scene.gptoolprops, 'edit_lines_opacity')
|
||||||
|
|
||||||
# layout.operator('gp.realign')
|
## realign / reproject
|
||||||
layout.operator('gp.batch_reproject_all_frames') # text=Batch Reproject
|
layout.operator('gp.realign')
|
||||||
|
# layout.operator('gp.batch_reproject_all_frames') # text=Batch Reproject
|
||||||
## Create empty frame on layer (ops stored under GP_colorize... might be best to separate in another panel )
|
## Create empty frame on layer (ops stored under GP_colorize... might be best to separate in another panel )
|
||||||
layout.operator('gp.create_empty_frames', icon='DECORATE_KEYFRAME')
|
layout.operator('gp.create_empty_frames', icon='DECORATE_KEYFRAME')
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ bl_info = {
|
||||||
"name": "GP toolbox",
|
"name": "GP toolbox",
|
||||||
"description": "Set of tools for Grease Pencil in animation production",
|
"description": "Set of tools for Grease Pencil in animation production",
|
||||||
"author": "Samuel Bernou",
|
"author": "Samuel Bernou",
|
||||||
"version": (1, 0, 9),
|
"version": (1, 1, 0),
|
||||||
"blender": (2, 91, 0),
|
"blender": (2, 91, 0),
|
||||||
"location": "sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
"location": "sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
@ -74,11 +74,14 @@ from pathlib import Path
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def remap_relative(dummy):
|
def remap_relative(dummy):
|
||||||
|
# try:
|
||||||
all_path = [lib for lib in bpy.utils.blend_paths(local=True)]
|
all_path = [lib for lib in bpy.utils.blend_paths(local=True)]
|
||||||
bpy.ops.file.make_paths_relative()
|
bpy.ops.file.make_paths_relative()
|
||||||
for i, lib in enumerate(bpy.utils.blend_paths(local=True)):
|
for i, lib in enumerate(bpy.utils.blend_paths(local=True)):
|
||||||
if all_path[i] != lib:
|
if all_path[i] != lib:
|
||||||
print('Remapped:', all_path[i], '\n>> ', lib)
|
print('Remapped:', all_path[i], '\n>> ', lib)
|
||||||
|
# except Exception as e:
|
||||||
|
# print(e)
|
||||||
|
|
||||||
def remap_on_save_update(self, context):
|
def remap_on_save_update(self, context):
|
||||||
pref = get_addon_prefs()
|
pref = get_addon_prefs()
|
||||||
|
@ -150,7 +153,7 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
||||||
use_relative_remap_on_save : BoolProperty(
|
use_relative_remap_on_save : BoolProperty(
|
||||||
name="Relative Remap On Save",
|
name="Relative Remap On Save",
|
||||||
description="Always remap all external path to relative when saving\nNeed blender restart if changed",
|
description="Always remap all external path to relative when saving\nNeed blender restart if changed",
|
||||||
default=True,
|
default=False,
|
||||||
update=remap_on_save_update
|
update=remap_on_save_update
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue