parent
86fb848e4a
commit
f9e7c9cc3b
|
@ -1,5 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
4.0.1
|
||||||
|
|
||||||
|
- fixed: layer nav operator on page up/down
|
||||||
|
|
||||||
|
4.0.0
|
||||||
|
|
||||||
|
- changed: version for Blender 4.3 - Breaking retrocompatibility with previous.
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -5,6 +5,7 @@ from bpy.props import (FloatProperty,
|
||||||
EnumProperty,
|
EnumProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
IntProperty)
|
IntProperty)
|
||||||
|
from .. import utils
|
||||||
|
|
||||||
## copied from OP_key_duplicate_send
|
## copied from OP_key_duplicate_send
|
||||||
def get_layer_list(self, context):
|
def get_layer_list(self, context):
|
||||||
|
@ -14,12 +15,6 @@ def get_layer_list(self, context):
|
||||||
def get_group_list(self, context):
|
def get_group_list(self, context):
|
||||||
return [(g.name, g.name, '') for g in context.object.data.layer_groups]
|
return [(g.name, g.name, '') for g in context.object.data.layer_groups]
|
||||||
|
|
||||||
def get_top_layer_from_group(gp, group):
|
|
||||||
upper_layer = None
|
|
||||||
for layer in gp.layers:
|
|
||||||
if layer.parent_group == group:
|
|
||||||
upper_layer = layer
|
|
||||||
return upper_layer
|
|
||||||
|
|
||||||
class GP_OT_create_empty_frames(bpy.types.Operator):
|
class GP_OT_create_empty_frames(bpy.types.Operator):
|
||||||
bl_idname = "gp.create_empty_frames"
|
bl_idname = "gp.create_empty_frames"
|
||||||
|
@ -84,7 +79,8 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
||||||
gp = context.grease_pencil
|
gp = context.grease_pencil
|
||||||
layer_from_group = None
|
layer_from_group = None
|
||||||
if gp.layer_groups.active:
|
if gp.layer_groups.active:
|
||||||
layer_from_group = get_top_layer_from_group(gp, gp.layer_groups.active)
|
layer_from_group = utils.get_top_layer_from_group(gp, gp.layer_groups.active)
|
||||||
|
## Can just do if not utils.get_closest_active_layer(context.grease_pencil):
|
||||||
if not gp.layers.active and not layer_from_group:
|
if not gp.layers.active and not layer_from_group:
|
||||||
self.report({'ERROR'}, 'No active layer or active group containing layer on GP object')
|
self.report({'ERROR'}, 'No active layer or active group containing layer on GP object')
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
|
@ -126,7 +122,7 @@ class GP_OT_create_empty_frames(bpy.types.Operator):
|
||||||
gpl = gp.layers
|
gpl = gp.layers
|
||||||
|
|
||||||
if gp.layer_groups.active:
|
if gp.layer_groups.active:
|
||||||
reference_layer = get_top_layer_from_group(gp, gp.layer_groups.active)
|
reference_layer = utils.get_top_layer_from_group(gp, gp.layer_groups.active)
|
||||||
else:
|
else:
|
||||||
reference_layer = gpl.active
|
reference_layer = gpl.active
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,11 @@ class GPT_OT_layer_nav(bpy.types.Operator):
|
||||||
prefs = utils.get_addon_prefs()
|
prefs = utils.get_addon_prefs()
|
||||||
if not prefs.nav_use_fade:
|
if not prefs.nav_use_fade:
|
||||||
if self.direction == 'DOWN':
|
if self.direction == 'DOWN':
|
||||||
utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'name')
|
utils.iterate_active_layer(context.grease_pencil, -1)
|
||||||
|
# utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'name') # gpv2
|
||||||
|
|
||||||
if self.direction == 'UP':
|
if self.direction == 'UP':
|
||||||
utils.iterate_selector(context.object.data.layers, 'active_index', 1, info_attr = 'name')
|
utils.iterate_active_layer(context.grease_pencil, 1)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
## get up and down keys for use in modal
|
## get up and down keys for use in modal
|
||||||
|
@ -91,12 +92,11 @@ class GPT_OT_layer_nav(bpy.types.Operator):
|
||||||
context.space_data.overlay.gpencil_fade_layer = fade
|
context.space_data.overlay.gpencil_fade_layer = fade
|
||||||
|
|
||||||
if self.direction == 'DOWN' or ((event.type in self.down_keys) and event.value == 'PRESS'):
|
if self.direction == 'DOWN' or ((event.type in self.down_keys) and event.value == 'PRESS'):
|
||||||
_val = utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'name')
|
_val = utils.iterate_active_layer(context.grease_pencil, -1)
|
||||||
trigger = True
|
trigger = True
|
||||||
|
|
||||||
if self.direction == 'UP' or ((event.type in self.up_keys) and event.value == 'PRESS'):
|
if self.direction == 'UP' or ((event.type in self.up_keys) and event.value == 'PRESS'):
|
||||||
_val = utils.iterate_selector(context.object.data.layers, 'active_index', 1, info_attr = 'name')
|
_val = utils.iterate_active_layer(context.grease_pencil, 1)
|
||||||
# utils.iterate_selector(bpy.context.scene.grease_pencil.layers, 'active_index', 1, info_attr = 'name')#layers
|
|
||||||
trigger = True
|
trigger = True
|
||||||
|
|
||||||
if trigger:
|
if trigger:
|
||||||
|
|
|
@ -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, 0),
|
"version": (4, 0, 1),
|
||||||
"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": "",
|
||||||
|
@ -336,7 +336,7 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
||||||
nav_fade_val : FloatProperty(
|
nav_fade_val : FloatProperty(
|
||||||
name='Fade Value',
|
name='Fade Value',
|
||||||
description='Fade value for other layers when navigating (0=invisible)',
|
description='Fade value for other layers when navigating (0=invisible)',
|
||||||
default=0.35, min=0.0, max=0.95, step=1, precision=2)
|
default=0.1, min=0.0, max=0.95, step=1, precision=2)
|
||||||
|
|
||||||
nav_limit : FloatProperty(
|
nav_limit : FloatProperty(
|
||||||
name='Fade Duration',
|
name='Fade Duration',
|
||||||
|
|
59
utils.py
59
utils.py
|
@ -162,6 +162,33 @@ def layer_active_index(gpl):
|
||||||
'''
|
'''
|
||||||
return next((i for i, l in enumerate(gpl) if l == gpl.active), None)
|
return next((i for i, l in enumerate(gpl) if l == gpl.active), None)
|
||||||
|
|
||||||
|
def get_top_layer_from_group(gp, group):
|
||||||
|
upper_layer = None
|
||||||
|
for layer in gp.layers:
|
||||||
|
if layer.parent_group == group:
|
||||||
|
upper_layer = layer
|
||||||
|
return upper_layer
|
||||||
|
|
||||||
|
def get_closest_active_layer(gp):
|
||||||
|
'''Get active layer from GP object, getting upper layer if in group
|
||||||
|
if a group is active, return the top layer of this group
|
||||||
|
if group is active but no layer in it, return None
|
||||||
|
'''
|
||||||
|
|
||||||
|
if gp.layers.active:
|
||||||
|
return gp.layers.active
|
||||||
|
## No active layer, return active from group (can be None !)
|
||||||
|
return get_top_layer_from_group(gp, gp.layer_groups.active)
|
||||||
|
|
||||||
|
def closest_layer_active_index(gp, fallback_index=0):
|
||||||
|
'''Get active layer index from GP object, getting upper layer if in group
|
||||||
|
if a group is active, return index at the top layer of this group
|
||||||
|
if group is active but no layer in it, return fallback_index (0 by default, stack bottom)'''
|
||||||
|
closest_active_layer = get_closest_active_layer(gp)
|
||||||
|
if closest_active_layer:
|
||||||
|
return next((i for i, l in enumerate(gp.layers) if l == closest_active_layer), fallback_index)
|
||||||
|
return fallback_index
|
||||||
|
|
||||||
## Check for nested lock
|
## Check for nested lock
|
||||||
def is_locked(stack_item):
|
def is_locked(stack_item):
|
||||||
'''Check if passed stack item (layer or group) is locked
|
'''Check if passed stack item (layer or group) is locked
|
||||||
|
@ -1200,6 +1227,38 @@ def iterate_selector(zone, attr, state, info_attr = None, active_access='active'
|
||||||
|
|
||||||
return info, bottom
|
return info, bottom
|
||||||
|
|
||||||
|
def iterate_active_layer(gpd, state):
|
||||||
|
'''Iterate active GP layer in stack
|
||||||
|
gpd: Grease Pencil Data
|
||||||
|
'''
|
||||||
|
layers = gpd.layers
|
||||||
|
l_count = len(layers)
|
||||||
|
|
||||||
|
if state: # swap
|
||||||
|
# info = None
|
||||||
|
# bottom = None
|
||||||
|
|
||||||
|
## Get active layer index
|
||||||
|
active_index = closest_layer_active_index(gpd, fallback_index=None)
|
||||||
|
if active_index == None:
|
||||||
|
## fallback to first layer if nothing found
|
||||||
|
gpd.layers.active = layers[0]
|
||||||
|
return
|
||||||
|
|
||||||
|
target_index = active_index + state
|
||||||
|
new_index = target_index % l_count
|
||||||
|
|
||||||
|
## set active layer
|
||||||
|
gpd.layers.active = layers[new_index]
|
||||||
|
|
||||||
|
if target_index == l_count:
|
||||||
|
bottom = 1 # bottom reached, cycle to first
|
||||||
|
elif target_index < 0:
|
||||||
|
bottom = -1 # up reached, cycle to last
|
||||||
|
|
||||||
|
# info = gpd.layers.active.name
|
||||||
|
# return info, bottom
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
### Curve handle
|
### Curve handle
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
Loading…
Reference in New Issue