Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPullusb <bernou.samuel@gmail.com>2021-07-12 22:28:00 +0300
committerPullusb <bernou.samuel@gmail.com>2021-07-12 22:28:00 +0300
commit4ecb089854c286cd20fc508ce4fe6dab9aaa5387 (patch)
tree613fe5815948ba4bf25da023a428be7e9fb86e9f /greasepencil_tools
parent5be927b2f67d7ca3f453fe598f5c37a506be91ef (diff)
GPencil Tools: Box deform multi object edit
Box deform not limited to active object in object mode. Now affect all selected grease pencils objects. Also can keep lattice object on confirm when using Shift + valid buttons.
Diffstat (limited to 'greasepencil_tools')
-rw-r--r--greasepencil_tools/__init__.py2
-rw-r--r--greasepencil_tools/box_deform.py131
-rw-r--r--greasepencil_tools/prefs.py1
3 files changed, 100 insertions, 34 deletions
diff --git a/greasepencil_tools/__init__.py b/greasepencil_tools/__init__.py
index 646f4862..0a8042c9 100644
--- a/greasepencil_tools/__init__.py
+++ b/greasepencil_tools/__init__.py
@@ -21,7 +21,7 @@ bl_info = {
"name": "Grease Pencil Tools",
"description": "Extra tools for Grease Pencil",
"author": "Samuel Bernou, Antonio Vazquez, Daniel Martinez Lara, Matias Mendiola",
-"version": (1, 5, 0),
+"version": (1, 5, 2),
"blender": (2, 91, 0),
"location": "Sidebar > Grease Pencil > Grease Pencil Tools",
"warning": "",
diff --git a/greasepencil_tools/box_deform.py b/greasepencil_tools/box_deform.py
index 0ac08987..a9a47ce2 100644
--- a/greasepencil_tools/box_deform.py
+++ b/greasepencil_tools/box_deform.py
@@ -31,6 +31,31 @@ def region_to_location(viewcoords, depthcoords):
from bpy_extras import view3d_utils
return view3d_utils.region_2d_to_location_3d(bpy.context.region, bpy.context.space_data.region_3d, viewcoords, depthcoords)
+def store_cage(self, vg_name):
+ import time
+ unique_id = time.strftime(r'%y%m%d%H%M%S') # ex: 20210711111117
+ # name = f'gp_lattice_{unique_id}'
+ name = f'{self.gp_obj.name}_lat{unique_id}'
+ vg = self.gp_obj.vertex_groups.get(vg_name)
+ if vg:
+ vg.name = name
+ for o in self.other_gp:
+ vg = o.vertex_groups.get(vg_name)
+ if vg:
+ vg.name = name
+
+ self.cage.name = name
+ self.cage.data.name = name
+ mod = self.gp_obj.grease_pencil_modifiers.get('tmp_lattice')
+ if mod:
+ mod.name = name #f'Lattice_{unique_id}'
+ mod.vertex_group = name
+ for o in self.other_gp:
+ mod = o.grease_pencil_modifiers.get('tmp_lattice')
+ if mod:
+ mod.name = name
+ mod.vertex_group = name
+
def assign_vg(obj, vg_name, delete=False):
## create vertex group
vg = obj.vertex_groups.get(vg_name)
@@ -51,6 +76,10 @@ def view_cage(obj):
gp = obj.data
gpl = gp.layers
+ from_obj = bpy.context.mode == 'OBJECT'
+ all_gps = [o for o in bpy.context.selected_objects if o.type == 'GPENCIL']
+ other_gp = [o for o in all_gps if o is not obj]
+
coords = []
initial_mode = bpy.context.mode
@@ -73,13 +102,14 @@ def view_cage(obj):
# get real location
coords.append(obj.matrix_world @ p.co)
- elif bpy.context.mode == 'OBJECT':#object mode -> all points
- for l in gpl:# if l.hide:continue# only visible ? (might break things)
- if not len(l.frames):
- continue#skip frameless layer
- for s in l.active_frame.strokes:
- for p in s.points:
- coords.append(obj.matrix_world @ p.co)
+ elif bpy.context.mode == 'OBJECT': # object mode -> all points of all selected gp objects
+ for gpo in all_gps:
+ for l in gpo.data.layers:# if l.hide:continue# only visible ? (might break things)
+ if not len(l.frames):
+ continue # skip frameless layer
+ for s in l.active_frame.strokes:
+ for p in s.points:
+ coords.append(gpo.matrix_world @ p.co)
elif bpy.context.mode == 'PAINT_GPENCIL':
# get last stroke points coordinated
@@ -189,7 +219,7 @@ def view_cage(obj):
## Master (root) collection
bpy.context.scene.collection.objects.link(cage)
- # spawn cage and align it to view (Again ! align something to a vector !!! argg)
+ # spawn cage and align it to view
r3d = bpy.context.space_data.region_3d
viewmat = r3d.view_matrix
@@ -205,17 +235,28 @@ def view_cage(obj):
lattice.points_v = 2
lattice.points_w = 1
- lattice.interpolation_type_u = lattice_interp#'KEY_LINEAR'-'KEY_BSPLINE'
- lattice.interpolation_type_v = lattice_interp#'KEY_LINEAR'-'KEY_BSPLINE'
- lattice.interpolation_type_w = lattice_interp#'KEY_LINEAR'-'KEY_BSPLINE'
+ lattice.interpolation_type_u = lattice_interp #'KEY_LINEAR'-'KEY_BSPLINE'
+ lattice.interpolation_type_v = lattice_interp
+ lattice.interpolation_type_w = lattice_interp
mod = obj.grease_pencil_modifiers.new('tmp_lattice', 'GP_LATTICE')
+ if from_obj:
+ mods = []
+ for o in other_gp:
+ mods.append( o.grease_pencil_modifiers.new('tmp_lattice', 'GP_LATTICE') )
# move to top if modifiers exists
for _ in range(len(obj.grease_pencil_modifiers)):
bpy.ops.object.gpencil_modifier_move_up(modifier='tmp_lattice')
+ if from_obj:
+ for o in other_gp:
+ for _ in range(len(o.grease_pencil_modifiers)):
+ bpy.ops.object.gpencil_modifier_move_up({'object':o}, modifier='tmp_lattice')
mod.object = cage
+ if from_obj:
+ for m in mods:
+ m.object = cage
if initial_mode == 'PAINT_GPENCIL':
mod.layer = gpl.active.info
@@ -225,29 +266,32 @@ def view_cage(obj):
if bpy.context.mode == 'EDIT_GPENCIL':
mod.vertex_group = vg.name
- #Go in object mode if not already
+ # Go in object mode if not already
if bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# Store name of deformed object in case of 'revive modal'
cage.vertex_groups.new(name=obj.name)
+ if from_obj:
+ for o in other_gp:
+ cage.vertex_groups.new(name=o.name)
## select and make cage active
# cage.select_set(True)
bpy.context.view_layer.objects.active = cage
- obj.select_set(False)#deselect GP object
- bpy.ops.object.mode_set(mode='EDIT')# go in lattice edit mode
- bpy.ops.lattice.select_all(action='SELECT')# select all points
+ obj.select_set(False) # deselect GP object
+ bpy.ops.object.mode_set(mode='EDIT') # go in lattice edit mode
+ bpy.ops.lattice.select_all(action='SELECT') # select all points
if prefs.use_clic_drag:
## Eventually change tool mode to tweak for direct point editing (reset after before leaving)
- bpy.ops.wm.tool_set_by_id(name="builtin.select")# Tweaktoolcode
+ bpy.ops.wm.tool_set_by_id(name="builtin.select") # Tweaktoolcode
return cage
def back_to_obj(obj, gp_mode, org_lattice_toolset, context):
- if context.mode == 'EDIT_LATTICE' and org_lattice_toolset:# Tweaktoolcode - restore the active tool used by lattice edit..
- bpy.ops.wm.tool_set_by_id(name = org_lattice_toolset)# Tweaktoolcode
+ if context.mode == 'EDIT_LATTICE' and org_lattice_toolset: # Tweaktoolcode - restore the active tool used by lattice edit..
+ bpy.ops.wm.tool_set_by_id(name = org_lattice_toolset) # Tweaktoolcode
# gp object active and selected
bpy.ops.object.mode_set(mode='OBJECT')
@@ -260,7 +304,7 @@ def delete_cage(cage):
bpy.data.objects.remove(cage)
bpy.data.lattices.remove(lattice)
-def apply_cage(gp_obj, cage):
+def apply_cage(gp_obj):
mod = gp_obj.grease_pencil_modifiers.get('tmp_lattice')
multi_user = None
if mod:
@@ -270,7 +314,8 @@ def apply_cage(gp_obj, cage):
other_user = [o for o in bpy.data.objects if o is not gp_obj and o.data is old]
gp_obj.data = gp_obj.data.copy()
- bpy.ops.object.gpencil_modifier_apply(apply_as='DATA', modifier=mod.name)
+ # bpy.ops.object.gpencil_modifier_apply(apply_as='DATA', modifier=mod.name)
+ bpy.ops.object.gpencil_modifier_apply({'object': gp_obj}, apply_as='DATA', modifier=mod.name)
if multi_user:
for o in other_user: # relink
@@ -281,17 +326,22 @@ def apply_cage(gp_obj, cage):
else:
print('tmp_lattice modifier not found to apply...')
- delete_cage(cage)
-
-def cancel_cage(gp_obj, cage):
+def cancel_cage(self):
#remove modifier
- mod = gp_obj.grease_pencil_modifiers.get('tmp_lattice')
+ mod = self.gp_obj.grease_pencil_modifiers.get('tmp_lattice')
if mod:
- gp_obj.grease_pencil_modifiers.remove(mod)
+ self.gp_obj.grease_pencil_modifiers.remove(mod)
else:
- print('tmp_lattice modifier not found to remove...')
+ print(f'tmp_lattice modifier not found to remove on {self.gp_obj.name}')
+
+ for ob in self.other_gp:
+ mod = ob.grease_pencil_modifiers.get('tmp_lattice')
+ if mod:
+ ob.grease_pencil_modifiers.remove(mod)
+ else:
+ print(f'tmp_lattice modifier not found to remove on {ob.name}')
- delete_cage(cage)
+ delete_cage(self.cage)
class GP_OT_latticeGpDeform(bpy.types.Operator):
@@ -413,8 +463,16 @@ valid:Spacebar/Enter, cancel:Del/Backspace/Tab/Ctrl+T"
context.window_manager.boxdeform_running = False
self.restore_prefs(context)
back_to_obj(self.gp_obj, self.gp_mode, self.org_lattice_toolset, context)
- apply_cage(self.gp_obj, self.cage)#must be in object mode
- assign_vg(self.gp_obj, 'lattice_cage_deform_group', delete=True)
+ if event.shift:
+ # Let the cage as is with a unique ID
+ store_cage(self, 'lattice_cage_deform_group')
+ else:
+ apply_cage(self.gp_obj) # must be in object mode
+ assign_vg(self.gp_obj, 'lattice_cage_deform_group', delete=True)
+ for o in self.other_gp:
+ apply_cage(o)
+ assign_vg(o, 'lattice_cage_deform_group', delete=True)
+ delete_cage(self.cage)
# back to original mode
if self.gp_mode != 'OBJECT':
@@ -448,7 +506,7 @@ valid:Spacebar/Enter, cancel:Del/Backspace/Tab/Ctrl+T"
context.window_manager.boxdeform_running = False
self.restore_prefs(context)
back_to_obj(self.gp_obj, self.gp_mode, self.org_lattice_toolset, context)
- cancel_cage(self.gp_obj, self.cage)
+ cancel_cage(self)
assign_vg(self.gp_obj, 'lattice_cage_deform_group', delete=True)
context.area.header_text_set(None)
if self.gp_mode != 'OBJECT':
@@ -523,16 +581,23 @@ valid:Spacebar/Enter, cancel:Del/Backspace/Tab/Ctrl+T"
## silent return
return {'CANCELLED'}
- #paint need VG workaround. object need good shortcut
if context.mode not in ('EDIT_GPENCIL', 'OBJECT', 'PAINT_GPENCIL'):
- # self.report({'WARNING'}, "Works only in following GPencil modes: edit")# ERROR
+ # self.report({'WARNING'}, "Works only in following GPencil modes: object / edit/ paint")# ERROR
## silent return
return {'CANCELLED'}
+
# bpy.ops.ed.undo_push(message="Box deform step")#don't work as expected (+ might be obsolete)
# https://developer.blender.org/D6147 <- undo forget
self.gp_obj = context.object
+
+ self.from_object = context.mode == 'OBJECT'
+ self.all_gps = self.other_gp = []
+ if self.from_object:
+ self.all_gps = [o for o in bpy.context.selected_objects if o.type == 'GPENCIL']
+ self.other_gp = [o for o in self.all_gps if o is not self.gp_obj]
+
# Clean potential failed previous job (delete tmp lattice)
mod = self.gp_obj.grease_pencil_modifiers.get('tmp_lattice')
if mod:
@@ -549,7 +614,7 @@ valid:Spacebar/Enter, cancel:Del/Backspace/Tab/Ctrl+T"
self.report({'ERROR'}, "Grease pencil object already has a lattice modifier (multi-lattices are enabled in blender 2.93+)")
return {'CANCELLED'}
- self.gp_mode = context.mode#store mode for restore
+ self.gp_mode = context.mode # store mode for restore
# All good, create lattice and start modal
diff --git a/greasepencil_tools/prefs.py b/greasepencil_tools/prefs.py
index 57cf0ee5..929197d5 100644
--- a/greasepencil_tools/prefs.py
+++ b/greasepencil_tools/prefs.py
@@ -230,6 +230,7 @@ class GPT_MT_box_deform_doc(bpy.types.Menu):
col.separator()
col.label(text="Shortcuts:", icon='HAND')
col.label(text="Spacebar / Enter : Confirm")
+ col.label(text="Shift + Spacebar / Enter : Confirm and let the lattice in place")
col.label(text="Delete / Backspace / Tab(twice) / Ctrl+T : Cancel")
col.label(text="M : Toggle between Linear and Spline mode at any moment")
col.label(text="1-9 top row number : Subdivide the box")