Respect group lock and hide state
parent
1c39d81ef1
commit
cf3f39b730
|
@ -6,6 +6,7 @@ from bpy.props import (FloatProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
IntProperty)
|
IntProperty)
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
from ..utils import is_hidden
|
||||||
|
|
||||||
## copied from OP_key_duplicate_send
|
## copied from OP_key_duplicate_send
|
||||||
def get_layer_list(self, context):
|
def get_layer_list(self, context):
|
||||||
|
@ -142,7 +143,7 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
||||||
tgt_layers = [l for i, l in enumerate(gpl) if i == active_index - 1]
|
tgt_layers = [l for i, l in enumerate(gpl) if i == active_index - 1]
|
||||||
|
|
||||||
elif self.targeted_layers == 'ALL_VISIBLE':
|
elif self.targeted_layers == 'ALL_VISIBLE':
|
||||||
tgt_layers = [l for l in gpl if not l.hide and l != gpl.active]
|
tgt_layers = [l for l in gpl if not is_hidden(l) and l != gpl.active]
|
||||||
|
|
||||||
elif self.targeted_layers == 'CHOSEN':
|
elif self.targeted_layers == 'CHOSEN':
|
||||||
if not self.layers_enum:
|
if not self.layers_enum:
|
||||||
|
@ -220,4 +221,4 @@ def register():
|
||||||
bpy.utils.register_class(GP_OT_create_empty_frames)
|
bpy.utils.register_class(GP_OT_create_empty_frames)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
bpy.utils.unregister_class(GP_OT_create_empty_frames)
|
bpy.utils.unregister_class(GP_OT_create_empty_frames)
|
||||||
|
|
|
@ -5,11 +5,14 @@ from ..utils import (location_to_region,
|
||||||
vector_length,
|
vector_length,
|
||||||
draw_gp_stroke,
|
draw_gp_stroke,
|
||||||
extrapolate_points_by_length,
|
extrapolate_points_by_length,
|
||||||
simple_draw_gp_stroke)
|
simple_draw_gp_stroke,
|
||||||
|
is_hidden,
|
||||||
|
is_locked)
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from math import degrees
|
from math import degrees
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
|
|
||||||
# from os.path import join, basename, exists, dirname, abspath, splitext
|
# from os.path import join, basename, exists, dirname, abspath, splitext
|
||||||
|
|
||||||
# iterate over selected layer and all/selected frame and close gaps between line extermities with a tolerance level
|
# iterate over selected layer and all/selected frame and close gaps between line extermities with a tolerance level
|
||||||
|
@ -276,9 +279,9 @@ class GPSTK_OT_extend_lines(bpy.types.Operator):
|
||||||
if self.layer_tgt == 'ACTIVE':
|
if self.layer_tgt == 'ACTIVE':
|
||||||
lays = [ob.data.layers.active]
|
lays = [ob.data.layers.active]
|
||||||
elif self.layer_tgt == 'SELECTED':
|
elif self.layer_tgt == 'SELECTED':
|
||||||
lays = [l for l in ob.data.layers if l.select and not l.hide]
|
lays = [l for l in ob.data.layers if l.select and not is_hidden(l)]
|
||||||
elif self.layer_tgt == 'ALL_VISIBLE':
|
elif self.layer_tgt == 'ALL_VISIBLE':
|
||||||
lays = [l for l in ob.data.layers if not l.hide]
|
lays = [l for l in ob.data.layers if not is_hidden(l)]
|
||||||
else:
|
else:
|
||||||
lays = [l for l in ob.data.layers if not any(x in l.name for x in ('spot', 'colo'))]
|
lays = [l for l in ob.data.layers if not any(x in l.name for x in ('spot', 'colo'))]
|
||||||
|
|
||||||
|
@ -337,9 +340,9 @@ class GPSTK_OT_change_closeline_length(bpy.types.Operator):
|
||||||
if self.layer_tgt == 'ACTIVE':
|
if self.layer_tgt == 'ACTIVE':
|
||||||
lays = [ob.data.layers.active]
|
lays = [ob.data.layers.active]
|
||||||
elif self.layer_tgt == 'SELECTED':
|
elif self.layer_tgt == 'SELECTED':
|
||||||
lays = [l for l in ob.data.layers if l.select and not l.hide]
|
lays = [l for l in ob.data.layers if l.select and not is_hidden(l)]
|
||||||
elif self.layer_tgt == 'ALL_VISIBLE':
|
elif self.layer_tgt == 'ALL_VISIBLE':
|
||||||
lays = [l for l in ob.data.layers if not l.hide]
|
lays = [l for l in ob.data.layers if not is_hidden(l)]
|
||||||
else:
|
else:
|
||||||
lays = [l for l in ob.data.layers if not any(x in l.name for x in ('spot', 'colo'))]
|
lays = [l for l in ob.data.layers if not any(x in l.name for x in ('spot', 'colo'))]
|
||||||
|
|
||||||
|
@ -375,7 +378,7 @@ class GPSTK_OT_comma_finder(bpy.types.Operator):
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
ct = 0
|
ct = 0
|
||||||
ob = context.object
|
ob = context.object
|
||||||
lays = [l for l in ob.data.layers if not l.hide and not l.lock]
|
lays = [l for l in ob.data.layers if not is_hidden(l) and not is_locked(l)]
|
||||||
for l in lays:
|
for l in lays:
|
||||||
if not l.current_frame():continue
|
if not l.current_frame():continue
|
||||||
for s in l.current_frame().drawing.strokes:
|
for s in l.current_frame().drawing.strokes:
|
||||||
|
|
|
@ -9,6 +9,7 @@ import json
|
||||||
from time import time
|
from time import time
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
|
from .utils import is_locked, is_hidden
|
||||||
|
|
||||||
def convertAttr(Attr):
|
def convertAttr(Attr):
|
||||||
'''Convert given value to a Json serializable format'''
|
'''Convert given value to a Json serializable format'''
|
||||||
|
@ -139,7 +140,7 @@ def copycut_strokes(layers=None, copy=True, keep_empty=True):
|
||||||
# color = gp.palettes.active.colors.active.name
|
# color = gp.palettes.active.colors.active.name
|
||||||
if not layers:
|
if not layers:
|
||||||
# by default all visible layers
|
# by default all visible layers
|
||||||
layers = [l for l in gpl if not l.hide and not l.lock] # []
|
layers = [l for l in gpl if not is_hidden(l) and not is_locked(l)] # []
|
||||||
if not isinstance(layers, list):
|
if not isinstance(layers, list):
|
||||||
# if a single layer object is send put in a list
|
# if a single layer object is send put in a list
|
||||||
layers = [layers]
|
layers = [layers]
|
||||||
|
@ -235,7 +236,7 @@ def copy_all_strokes(layers=None):
|
||||||
|
|
||||||
if not layers:
|
if not layers:
|
||||||
# by default all visible layers
|
# by default all visible layers
|
||||||
layers = [l for l in gpl if not l.hide and not l.lock]# include locked ?
|
layers = [l for l in gpl if not is_hidden(l) and not is_locked(l)]# include locked ?
|
||||||
if not isinstance(layers, list):
|
if not isinstance(layers, list):
|
||||||
# if a single layer object is send put in a list
|
# if a single layer object is send put in a list
|
||||||
layers = [layers]
|
layers = [layers]
|
||||||
|
@ -275,7 +276,7 @@ def copy_all_strokes_in_frame(frame=None, layers=None, obj=None,
|
||||||
|
|
||||||
if not layers:
|
if not layers:
|
||||||
# by default all visible layers
|
# by default all visible layers
|
||||||
layers = [l for l in gpl if not l.hide and not l.lock] # include locked ?
|
layers = [l for l in gpl if not is_hidden(l) and not is_locked(l)] # include locked ?
|
||||||
if not isinstance(layers, list):
|
if not isinstance(layers, list):
|
||||||
# if a single layer object is send put in a list
|
# if a single layer object is send put in a list
|
||||||
layers = [layers]
|
layers = [layers]
|
||||||
|
@ -521,7 +522,7 @@ class GPCLIP_OT_copy_multi_strokes(bpy.types.Operator):
|
||||||
#ct = check_radius()
|
#ct = check_radius()
|
||||||
layerdic = {}
|
layerdic = {}
|
||||||
|
|
||||||
layerpool = [l for l in gpl if not l.hide and l.select] # and not l.lock
|
layerpool = [l for l in gpl if not is_hidden(l) and l.select] # and not is_locked(l)
|
||||||
if not layerpool:
|
if not layerpool:
|
||||||
self.report({'ERROR'}, 'No layers selected in GP dopesheet (needs to be visible and selected to be copied)\nHint: Changing active layer reset selection to active only')
|
self.report({'ERROR'}, 'No layers selected in GP dopesheet (needs to be visible and selected to be copied)\nHint: Changing active layer reset selection to active only')
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
|
@ -11,6 +11,7 @@ from bpy_extras.view3d_utils import region_2d_to_location_3d, region_2d_to_vecto
|
||||||
location_3d_to_region_2d, region_2d_to_origin_3d, region_2d_to_location_3d
|
location_3d_to_region_2d, region_2d_to_origin_3d, region_2d_to_location_3d
|
||||||
from time import time
|
from time import time
|
||||||
from math import pi, cos, sin
|
from math import pi, cos, sin
|
||||||
|
from .utils import is_locked, is_hidden
|
||||||
|
|
||||||
|
|
||||||
def get_gp_mat(gp, name, set_active=False):
|
def get_gp_mat(gp, name, set_active=False):
|
||||||
|
@ -440,7 +441,7 @@ class GPTB_OT_eraser(Operator):
|
||||||
|
|
||||||
t0 = time()
|
t0 = time()
|
||||||
gp_mats = gp.data.materials
|
gp_mats = gp.data.materials
|
||||||
gp_layers = [l for l in gp.data.layers if not l.lock or l.hide]
|
gp_layers = [l for l in gp.data.layers if not is_locked(l) or is_hidden(l)]
|
||||||
self.gp_frames = [l.current_frame() for l in gp_layers]
|
self.gp_frames = [l.current_frame() for l in gp_layers]
|
||||||
'''
|
'''
|
||||||
points_data = [(s, f, gp_mats[s.material_index]) for f in gp_frames for s in f.drawing.strokes]
|
points_data = [(s, f, gp_mats[s.material_index]) for f in gp_frames for s in f.drawing.strokes]
|
||||||
|
|
|
@ -2,6 +2,7 @@ import bpy
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
from bpy.props import (BoolProperty,
|
from bpy.props import (BoolProperty,
|
||||||
|
|
|
@ -12,7 +12,7 @@ from .utils import (location_to_region, region_to_location)
|
||||||
## Do not work on multiple object
|
## Do not work on multiple object
|
||||||
def batch_flat_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False):
|
def batch_flat_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False):
|
||||||
'''Reproject
|
'''Reproject
|
||||||
:all_stroke: affect hided, locked layers
|
:all_stroke: affect hidden, locked layers
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if restore_frame:
|
if restore_frame:
|
||||||
|
|
|
@ -2,7 +2,6 @@ import bpy
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from . import utils
|
from . import utils
|
||||||
|
|
||||||
|
|
||||||
class GPTB_OT_create_follow_path_curve(bpy.types.Operator):
|
class GPTB_OT_create_follow_path_curve(bpy.types.Operator):
|
||||||
bl_idname = "object.create_follow_path_curve"
|
bl_idname = "object.create_follow_path_curve"
|
||||||
bl_label = "Create Follow Path Curve"
|
bl_label = "Create Follow Path Curve"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import bpy
|
import bpy
|
||||||
from .utils import get_addon_prefs
|
from .utils import get_addon_prefs, is_locked, is_hidden
|
||||||
from bpy.props import BoolProperty ,EnumProperty ,StringProperty
|
from bpy.props import BoolProperty ,EnumProperty ,StringProperty
|
||||||
|
|
||||||
class GPTB_OT_jump_gp_keyframe(bpy.types.Operator):
|
class GPTB_OT_jump_gp_keyframe(bpy.types.Operator):
|
||||||
|
@ -45,15 +45,15 @@ class GPTB_OT_jump_gp_keyframe(bpy.types.Operator):
|
||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
if self.target == 'ACTIVE':
|
if self.target == 'ACTIVE':
|
||||||
gpl = [l for l in context.object.data.layers if l.select and not l.hide]
|
gpl = [l for l in context.object.data.layers if l.select and not is_hidden(l)]
|
||||||
if not context.object.data.layers.active in gpl:
|
if not context.object.data.layers.active in gpl:
|
||||||
gpl.append(context.object.data.layers.active)
|
gpl.append(context.object.data.layers.active)
|
||||||
|
|
||||||
elif self.target == 'VISIBLE':
|
elif self.target == 'VISIBLE':
|
||||||
gpl = [l for l in context.object.data.layers if not l.hide]
|
gpl = [l for l in context.object.data.layers if not is_hidden(l)]
|
||||||
|
|
||||||
elif self.target == 'ACCESSIBLE':
|
elif self.target == 'ACCESSIBLE':
|
||||||
gpl = [l for l in context.object.data.layers if not l.hide and not l.lock]
|
gpl = [l for l in context.object.data.layers if not is_hidden(l) and not is_locked(l)]
|
||||||
|
|
||||||
if self.keyframe_type != 'NONE':
|
if self.keyframe_type != 'NONE':
|
||||||
# use shortcut choice override
|
# use shortcut choice override
|
||||||
|
|
|
@ -4,7 +4,7 @@ import mathutils
|
||||||
from mathutils import Vector, Matrix, geometry
|
from mathutils import Vector, Matrix, geometry
|
||||||
from bpy_extras import view3d_utils
|
from bpy_extras import view3d_utils
|
||||||
from time import time
|
from time import time
|
||||||
from .utils import get_gp_draw_plane, location_to_region, region_to_location
|
from .utils import get_gp_draw_plane, location_to_region, region_to_location, is_locked, is_hidden
|
||||||
|
|
||||||
class GP_OT_pick_closest_layer(Operator):
|
class GP_OT_pick_closest_layer(Operator):
|
||||||
bl_idname = "gp.pick_closest_layer"
|
bl_idname = "gp.pick_closest_layer"
|
||||||
|
@ -76,7 +76,7 @@ class GP_OT_pick_closest_layer(Operator):
|
||||||
self.point_pair = []
|
self.point_pair = []
|
||||||
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
||||||
for layer in gp.layers:
|
for layer in gp.layers:
|
||||||
if layer.hide:
|
if is_hidden(layer):
|
||||||
continue
|
continue
|
||||||
for f in layer.frames:
|
for f in layer.frames:
|
||||||
if not f.select:
|
if not f.select:
|
||||||
|
@ -89,9 +89,9 @@ class GP_OT_pick_closest_layer(Operator):
|
||||||
self.point_pair += [(Vector((*location_to_region(mat @ p.position), 0)), layer) for p in s.points]
|
self.point_pair += [(Vector((*location_to_region(mat @ p.position), 0)), layer) for p in s.points]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# [s for l in gp.layers if not l.lock and not l.hide for s in l.current_frame().stokes]
|
# [s for l in gp.layers if not is_locked(l) and not is_hidden(l) for s in l.current_frame().stokes]
|
||||||
for layer in gp.layers:
|
for layer in gp.layers:
|
||||||
if layer.hide or not layer.current_frame():
|
if is_hidden(layer) or not layer.current_frame():
|
||||||
continue
|
continue
|
||||||
for s in layer.current_frame().drawing.strokes:
|
for s in layer.current_frame().drawing.strokes:
|
||||||
if self.stroke_filter == 'STROKE' and not self.ob.data.materials[s.material_index].grease_pencil.show_stroke:
|
if self.stroke_filter == 'STROKE' and not self.ob.data.materials[s.material_index].grease_pencil.show_stroke:
|
||||||
|
|
|
@ -4,7 +4,12 @@ import mathutils
|
||||||
from mathutils import Vector, Matrix, geometry
|
from mathutils import Vector, Matrix, geometry
|
||||||
from bpy_extras import view3d_utils
|
from bpy_extras import view3d_utils
|
||||||
from time import time
|
from time import time
|
||||||
from .utils import get_gp_draw_plane, location_to_region, region_to_location
|
from .utils import (get_gp_draw_plane,
|
||||||
|
location_to_region,
|
||||||
|
region_to_location,
|
||||||
|
is_locked,
|
||||||
|
is_hidden)
|
||||||
|
|
||||||
|
|
||||||
### passing by 2D projection
|
### passing by 2D projection
|
||||||
def get_3d_coord_on_drawing_plane_from_2d(context, co):
|
def get_3d_coord_on_drawing_plane_from_2d(context, co):
|
||||||
|
@ -79,7 +84,7 @@ class GP_OT_pick_closest_material(Operator):
|
||||||
|
|
||||||
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
||||||
for l in self.gp.layers:
|
for l in self.gp.layers:
|
||||||
if l.hide:# l.lock or
|
if is_hidden(l):# is_locked(l) or
|
||||||
continue
|
continue
|
||||||
for f in l.frames:
|
for f in l.frames:
|
||||||
if not f.select:
|
if not f.select:
|
||||||
|
@ -88,9 +93,9 @@ class GP_OT_pick_closest_material(Operator):
|
||||||
self.stroke_list.append(s)
|
self.stroke_list.append(s)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# [s for l in self.gp.layers if not l.lock and not l.hide for s in l.current_frame().stokes]
|
# [s for l in self.gp.layers if not is_locked(l) and not is_hidden(l) for s in l.current_frame().stokes]
|
||||||
for l in self.gp.layers:
|
for l in self.gp.layers:
|
||||||
if l.hide or not l.current_frame():# l.lock or
|
if is_hidden(l) or not l.current_frame():# is_locked(l) or
|
||||||
continue
|
continue
|
||||||
for s in l.current_frame().drawing.strokes:
|
for s in l.current_frame().drawing.strokes:
|
||||||
self.stroke_list.append(s)
|
self.stroke_list.append(s)
|
||||||
|
@ -235,7 +240,7 @@ class GP_OT_pick_closest_material(Operator):
|
||||||
|
|
||||||
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
if context.scene.tool_settings.use_grease_pencil_multi_frame_editing:
|
||||||
for l in gp.layers:
|
for l in gp.layers:
|
||||||
if l.hide:# l.lock or
|
if is_hidden(l):# is_locked(l) or
|
||||||
continue
|
continue
|
||||||
for f in l.frames:
|
for f in l.frames:
|
||||||
if not f.select:
|
if not f.select:
|
||||||
|
@ -244,9 +249,9 @@ class GP_OT_pick_closest_material(Operator):
|
||||||
self.stroke_list.append(s)
|
self.stroke_list.append(s)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# [s for l in gp.layers if not l.lock and not l.hide for s in l.current_frame().stokes]
|
# [s for l in gp.layers if not is_locked(l) and not is_hidden(l) for s in l.current_frame().stokes]
|
||||||
for l in gp.layers:
|
for l in gp.layers:
|
||||||
if l.hide or not l.current_frame():# l.lock or
|
if is_hidden(l) or not l.current_frame():# is_locked(l) or
|
||||||
continue
|
continue
|
||||||
for s in l.current_frame().drawing.strokes:
|
for s in l.current_frame().drawing.strokes:
|
||||||
self.stroke_list.append(s)
|
self.stroke_list.append(s)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import bpy
|
import bpy
|
||||||
import mathutils
|
import mathutils
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
from mathutils import Matrix, Vector
|
from mathutils import Matrix, Vector
|
||||||
from math import pi
|
from math import pi
|
||||||
import numpy as np
|
|
||||||
from time import time
|
from time import time
|
||||||
from . import utils
|
|
||||||
from mathutils.geometry import intersect_line_plane
|
from mathutils.geometry import intersect_line_plane
|
||||||
|
from . import utils
|
||||||
|
from .utils import is_hidden, is_locked
|
||||||
|
|
||||||
def get_scale_matrix(scale):
|
def get_scale_matrix(scale):
|
||||||
# recreate a neutral mat scale
|
# recreate a neutral mat scale
|
||||||
|
@ -15,35 +17,6 @@ def get_scale_matrix(scale):
|
||||||
matscale = matscale_x @ matscale_y @ matscale_z
|
matscale = matscale_x @ matscale_y @ matscale_z
|
||||||
return matscale
|
return matscale
|
||||||
|
|
||||||
'''
|
|
||||||
## Old reproject method using Operators:
|
|
||||||
omode = bpy.context.mode
|
|
||||||
|
|
||||||
if all_strokes:
|
|
||||||
layers_state = [[l, l.hide, l.lock, l.lock_frame] for l in obj.data.layers]
|
|
||||||
for l in obj.data.layers:
|
|
||||||
l.hide = False
|
|
||||||
l.lock = False
|
|
||||||
l.lock_frame = False
|
|
||||||
bpy.ops.object.mode_set(mode='EDIT')
|
|
||||||
|
|
||||||
|
|
||||||
for fnum in frame_list:
|
|
||||||
bpy.context.scene.frame_current = fnum
|
|
||||||
bpy.ops.gpencil.select_all(action='SELECT')
|
|
||||||
bpy.ops.gpencil.reproject(type=proj_type) # 'INVOKE_DEFAULT'
|
|
||||||
bpy.ops.gpencil.select_all(action='DESELECT')
|
|
||||||
|
|
||||||
# restore
|
|
||||||
if all_strokes:
|
|
||||||
for layer, hide, lock, lock_frame in layers_state:
|
|
||||||
layer.hide = hide
|
|
||||||
layer.lock = lock
|
|
||||||
layer.lock_frame = lock_frame
|
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode=omode)
|
|
||||||
'''
|
|
||||||
|
|
||||||
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 hidden, locked layers
|
:all_stroke: affect hidden, locked layers
|
||||||
|
@ -73,7 +46,7 @@ def batch_reproject(obj, proj_type='VIEW', all_strokes=True, restore_frame=False
|
||||||
if not all_strokes:
|
if not all_strokes:
|
||||||
if not layer.select:
|
if not layer.select:
|
||||||
continue
|
continue
|
||||||
if layer.hide or layer.lock:
|
if is_hidden(layer) or is_locked(layer):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
frame = next((f for f in layer.frames if f.frame_number == i), None)
|
frame = next((f for f in layer.frames if f.frame_number == i), None)
|
||||||
|
|
|
@ -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": (4, 0, 3),
|
"version": (4, 0, 4),
|
||||||
"blender": (4, 3, 0),
|
"blender": (4, 3, 0),
|
||||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
|
Loading…
Reference in New Issue