Layer actions and navigations features
1.9.0 - feat: New shortcuts: - `F2` in Paint and Edit to rename active layer - `Insert` add a new layer (same as Krita) - `Shift + Insert` add a new layer and immediately pop-up a rename box - `page up / page down` change active layer up/down with a temporary fade (settings in addon prefs) - fix: error when tweaking `gp.duplicate_send_to_layer` shortcutgpv2
parent
3c7477c442
commit
97b09444ab
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,5 +1,15 @@
|
|||
# Changelog
|
||||
|
||||
|
||||
1.9.0
|
||||
|
||||
- feat: New shortcuts:
|
||||
- `F2` in Paint and Edit to rename active layer
|
||||
- `Insert` add a new layer (same as Krita)
|
||||
- `Shift + Insert` add a new layer and immediately pop-up a rename box
|
||||
- `page up / page down` change active layer up/down with a temporary fade (settings in addon prefs)
|
||||
- fix: error when tweaking `gp.duplicate_send_to_layer` shortcut
|
||||
|
||||
1.8.1
|
||||
|
||||
- fix: Gp clipboard paste `Paste layers` don't skip empty frames anymore
|
||||
|
@ -13,7 +23,6 @@
|
|||
1.7.8
|
||||
|
||||
- fix: reset rotation in draw cam mode keep view in the same place (counter camera rotation)
|
||||
- code: initial enhancement for palette linking
|
||||
|
||||
1.7.7
|
||||
|
||||
|
|
|
@ -302,7 +302,7 @@ class OBJ_OT_breakdown_obj_anim(bpy.types.Operator):
|
|||
|
||||
### --- KEYMAP ---
|
||||
|
||||
breakdowner_addon_keymaps = []
|
||||
addon_keymaps = []
|
||||
def register_keymaps():
|
||||
if bpy.app.background:
|
||||
return
|
||||
|
@ -322,16 +322,15 @@ def register_keymaps():
|
|||
if ops_id not in km.keymap_items:
|
||||
km = addon.keymaps.new(name='3D View', space_type='VIEW_3D')#EMPTY
|
||||
kmi = km.keymap_items.new(ops_id, type="E", value="PRESS", shift=True)
|
||||
breakdowner_addon_keymaps.append((km, kmi))
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
def unregister_keymaps():
|
||||
if bpy.app.background:
|
||||
return
|
||||
for km, kmi in breakdowner_addon_keymaps:
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
|
||||
breakdowner_addon_keymaps.clear()
|
||||
# del breakdowner_addon_keymaps[:]
|
||||
addon_keymaps.clear()
|
||||
|
||||
### --- REGISTER ---
|
||||
|
||||
|
|
|
@ -4,8 +4,10 @@ from bpy.types import Operator
|
|||
|
||||
def get_layer_list(self, context):
|
||||
'''return (identifier, name, description) of enum content'''
|
||||
if not context:
|
||||
return [('None', 'None','None')]
|
||||
if not context.object:
|
||||
return
|
||||
return [('None', 'None','None')]
|
||||
return [(l.info, l.info, '') for l in context.object.data.layers if l != context.object.data.layers.active]
|
||||
# try:
|
||||
# except:
|
||||
|
@ -23,7 +25,8 @@ class GPTB_OT_duplicate_send_to_layer(Operator) :
|
|||
layers_enum : bpy.props.EnumProperty(
|
||||
name="Duplicate to layers",
|
||||
description="Duplicate selected keys in active layer and send them to choosen layer",
|
||||
items=get_layer_list
|
||||
items=get_layer_list,
|
||||
options={'HIDDEN'},
|
||||
)
|
||||
|
||||
delete_source : bpy.props.BoolProperty(default=False, options={'SKIP_SAVE'})
|
||||
|
@ -110,12 +113,10 @@ def register_keymaps():
|
|||
# if not pref.kfj_use_shortcut:
|
||||
# return
|
||||
addon = bpy.context.window_manager.keyconfigs.addon
|
||||
# km = addon.keymaps.new(name = "Screen", space_type = "EMPTY")
|
||||
km = addon.keymaps.new(name = "Dopesheet", space_type = "DOPESHEET_EDITOR")
|
||||
kmi = km.keymap_items.new('gp.duplicate_send_to_layer', type='D', value="PRESS", ctrl=True, shift=True)
|
||||
addon_keymaps.append((km,kmi))
|
||||
|
||||
|
||||
# km = addon.keymaps.new(name = "Dopesheet", space_type = "DOPESHEET_EDITOR") # try duplicating km (seem to be error at unregsiter)
|
||||
kmi = km.keymap_items.new('gp.duplicate_send_to_layer', type='X', value="PRESS", ctrl=True, shift=True)
|
||||
kmi.properties.delete_source = True
|
||||
|
|
|
@ -633,6 +633,107 @@ def subscribe_handler(dummy):
|
|||
)
|
||||
|
||||
|
||||
##--- Add layers
|
||||
|
||||
class GPTB_PT_layer_name_ui(bpy.types.Panel):
|
||||
bl_space_type = 'TOPBAR' # dummy
|
||||
bl_region_type = 'HEADER'
|
||||
bl_options = {'INSTANCED'}
|
||||
bl_label = 'Layer Rename'
|
||||
bl_ui_units_x = 14
|
||||
|
||||
def invoke(self, context, event):
|
||||
# all_addons_l = get_modifier_list()
|
||||
wm = context.window_manager
|
||||
wm.invoke_props_dialog(self) # , width=600
|
||||
return {'FINISHED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
# def row_with_icon(layout, icon):
|
||||
# # Edit first editable button in popup
|
||||
# row = layout.row()
|
||||
# row.activate_init = True
|
||||
# row.label(icon=icon)
|
||||
# return row
|
||||
# row = row_with_icon(layout, 'OUTLINER_DATA_GP_LAYER')
|
||||
|
||||
row = layout.row()
|
||||
row.activate_init = True
|
||||
row.label(icon='OUTLINER_DATA_GP_LAYER')
|
||||
row.prop(context.object.data.layers.active, 'info', text='')
|
||||
|
||||
def add_layer(context):
|
||||
bpy.ops.gpencil.layer_add()
|
||||
context.object.data.layers.active.use_lights = False
|
||||
|
||||
class GPTB_OT_add_gp_layer_with_rename(Operator):
|
||||
bl_idname = "gp.add_layer_rename"
|
||||
bl_label = "Add Rename GPencil Layer"
|
||||
bl_description = "Create a new gp layer with use light toggled off and popup a rename box"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GPENCIL'
|
||||
|
||||
def execute(self, context):
|
||||
add_layer(context)
|
||||
bpy.ops.wm.call_panel(name="GPTB_PT_layer_name_ui", keep_open = False)
|
||||
return {"FINISHED"}
|
||||
|
||||
class GPTB_OT_add_gp_layer(Operator):
|
||||
bl_idname = "gp.add_layer"
|
||||
bl_label = "Add GPencil Layer"
|
||||
bl_description = "Create a new gp layer with use light toggled off"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object and context.object.type == 'GPENCIL'
|
||||
|
||||
def execute(self, context):
|
||||
add_layer(context)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
addon_keymaps = []
|
||||
def register_keymaps():
|
||||
addon = bpy.context.window_manager.keyconfigs.addon
|
||||
|
||||
##---# Insert Layers
|
||||
## Insert new gp layer (with no use_light)
|
||||
km = addon.keymaps.new(name = "Grease Pencil", space_type = "EMPTY") # global (only paint ?)
|
||||
kmi = km.keymap_items.new('gp.add_layer', type='INSERT', value='PRESS')
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
## Insert new gp layer (with no use_light and immediately pop up a box to rename)
|
||||
# km = addon.keymaps.new(name = "Grease Pencil", space_type = "EMPTY") # global (only paint ?)
|
||||
kmi = km.keymap_items.new('gp.add_layer_rename', type='INSERT', value='PRESS', shift=True)
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
##---# F2 rename calls
|
||||
## Direct rename active layer in Paint mode
|
||||
km = addon.keymaps.new(name = "Grease Pencil Stroke Paint Mode", space_type = "EMPTY")
|
||||
kmi = km.keymap_items.new('wm.call_panel', type='F2', value='PRESS')
|
||||
kmi.properties.name = 'GPTB_PT_layer_name_ui'
|
||||
kmi.properties.keep_open = False
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
## Same in edit mode
|
||||
km = addon.keymaps.new(name = "Grease Pencil Stroke Edit Mode", space_type = "EMPTY")
|
||||
kmi = km.keymap_items.new('wm.call_panel', type='F2', value='PRESS')
|
||||
kmi.properties.name = 'GPTB_PT_layer_name_ui'
|
||||
kmi.properties.keep_open = False
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
|
||||
def unregister_keymaps():
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
addon_keymaps.clear()
|
||||
|
||||
|
||||
|
||||
classes=(
|
||||
GPTB_OT_rename_gp_layer,
|
||||
GPTB_OT_layer_name_build,
|
||||
|
@ -640,6 +741,11 @@ classes=(
|
|||
GPTB_OT_layer_new_group,
|
||||
GPTB_OT_select_set_same_prefix,
|
||||
GPTB_OT_select_set_same_color,
|
||||
|
||||
## Layer add and pop-up rename
|
||||
GPTB_PT_layer_name_ui, # pop-up
|
||||
GPTB_OT_add_gp_layer_with_rename, # shift+Ins
|
||||
GPTB_OT_add_gp_layer, # Ins
|
||||
)
|
||||
|
||||
def register():
|
||||
|
@ -650,8 +756,10 @@ def register():
|
|||
bpy.types.DOPESHEET_HT_header.append(gpencil_dopesheet_header)
|
||||
bpy.types.GPENCIL_MT_layer_context_menu.append(gpencil_layer_dropdown_menu)
|
||||
bpy.app.handlers.load_post.append(subscribe_handler) # need to restart after first activation
|
||||
register_keymaps()
|
||||
|
||||
def unregister():
|
||||
unregister_keymaps()
|
||||
bpy.app.handlers.load_post.remove(subscribe_handler)
|
||||
bpy.types.GPENCIL_MT_layer_context_menu.remove(gpencil_layer_dropdown_menu)
|
||||
bpy.types.DOPESHEET_HT_header.remove(gpencil_dopesheet_header)
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
import bpy
|
||||
from . import utils
|
||||
|
||||
class GPT_OT_layer_nav(bpy.types.Operator):
|
||||
bl_idname = "gp.layer_nav"
|
||||
bl_label = "GP Layer Navigator"
|
||||
bl_description = "Change active GP layer and highlight active for a moment"
|
||||
bl_options = {'REGISTER', 'INTERNAL', 'UNDO'}
|
||||
|
||||
direction : bpy.props.EnumProperty(
|
||||
name='direction',
|
||||
items=(('NONE', 'None', ''),('UP', 'Up', ''),('DOWN', 'Down', '')),
|
||||
default='NONE',
|
||||
description='Direction to change layer in active GPencil stack',
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
## hardcoded values
|
||||
# interval = 0.04 # 0.1
|
||||
# limit = 1.8
|
||||
# fade_val = 0.35
|
||||
# use_fade_in = True
|
||||
# fade_in_time = 0.5
|
||||
|
||||
def invoke(self, context, event):
|
||||
## initialise vvalue from prefs
|
||||
prefs = utils.get_addon_prefs()
|
||||
|
||||
if not prefs.nav_use_fade:
|
||||
if self.direction == 'DOWN' or (event.type == 'PAGE_DOWN' and event.value == 'PRESS'):
|
||||
utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'info')
|
||||
|
||||
if self.direction == 'UP' or (event.type == 'PAGE_UP' and event.value == 'PRESS'):
|
||||
utils.iterate_selector(context.object.data.layers, 'active_index', 1, info_attr = 'info')
|
||||
return {'FINISHED'}
|
||||
|
||||
self.interval = prefs.nav_interval
|
||||
self.limit = prefs.nav_limit
|
||||
self.fade_val = prefs.nav_fade_val
|
||||
self.use_fade_in = prefs.nav_use_fade_in
|
||||
self.fade_in_time = prefs.nav_fade_in_time
|
||||
|
||||
self.lapse = 0
|
||||
wm = context.window_manager
|
||||
args = (self, context)
|
||||
|
||||
if context.space_data.overlay.use_gpencil_fade_layers:
|
||||
self.fade_target = context.space_data.overlay.gpencil_fade_layer
|
||||
else:
|
||||
self.fade_target = 1.0
|
||||
|
||||
self.fade_start = self.limit - self.fade_in_time
|
||||
|
||||
self.first = True
|
||||
self._timer = wm.event_timer_add(self.interval, window=context.window) # 0.1
|
||||
wm.modal_handler_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def store_settings(self, context):
|
||||
self.org_use_gpencil_fade_layers = context.space_data.overlay.use_gpencil_fade_layers
|
||||
self.org_gpencil_fade_layer = context.space_data.overlay.gpencil_fade_layer
|
||||
context.space_data.overlay.use_gpencil_fade_layers = True
|
||||
context.space_data.overlay.gpencil_fade_layer = self.fade_val
|
||||
|
||||
def modal(self, context, event):
|
||||
trigger = False
|
||||
if event.type in {'RIGHTMOUSE', 'ESC', 'LEFTMOUSE'}:
|
||||
self.stop_mod(context)
|
||||
return {'CANCELLED'}
|
||||
|
||||
if event.type == 'TIMER':
|
||||
self.lapse += self.interval
|
||||
|
||||
if self.lapse >= self.limit:
|
||||
self.stop_mod(context)
|
||||
return {'FINISHED'}
|
||||
|
||||
## Fade
|
||||
if self.use_fade_in and (self.lapse > self.fade_start):
|
||||
fade = utils.transfer_value(self.lapse, self.fade_start, self.limit, self.fade_val, self.fade_target)
|
||||
# print(f'lapse {self.lapse} - fade {fade}')
|
||||
context.space_data.overlay.gpencil_fade_layer = fade
|
||||
|
||||
if self.direction == 'DOWN' or (event.type == 'PAGE_DOWN' and event.value == 'PRESS'):
|
||||
_val = utils.iterate_selector(context.object.data.layers, 'active_index', -1, info_attr = 'info')
|
||||
trigger = True
|
||||
|
||||
if self.direction == 'UP' or (event.type == 'PAGE_UP' and event.value == 'PRESS'):
|
||||
_val = utils.iterate_selector(context.object.data.layers, 'active_index', 1, info_attr = 'info')
|
||||
# utils.iterate_selector(bpy.context.scene.grease_pencil.layers, 'active_index', 1, info_attr = 'info')#layers
|
||||
trigger = True
|
||||
|
||||
if trigger:
|
||||
self.direction = 'NONE'
|
||||
if self.first:
|
||||
self.store_settings(context)
|
||||
self.first=False
|
||||
|
||||
if self.use_fade_in:
|
||||
# reset fade to wanted value
|
||||
context.space_data.overlay.gpencil_fade_layer = self.fade_val
|
||||
|
||||
self.lapse = 0 # reset counter
|
||||
return {'RUNNING_MODAL'}#running modal prevent original usage to be triggered (capture keys)
|
||||
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
def stop_mod(self, context):
|
||||
# restore fade
|
||||
context.space_data.overlay.use_gpencil_fade_layers = self.org_use_gpencil_fade_layers
|
||||
context.space_data.overlay.gpencil_fade_layer = self.org_gpencil_fade_layer
|
||||
wm = context.window_manager
|
||||
wm.event_timer_remove(self._timer)
|
||||
|
||||
|
||||
addon_keymaps = []
|
||||
|
||||
def register_keymap():
|
||||
addon = bpy.context.window_manager.keyconfigs.addon
|
||||
|
||||
km = addon.keymaps.new(name = "Grease Pencil Stroke Paint Mode", space_type = "EMPTY")
|
||||
|
||||
kmi = km.keymap_items.new('gp.layer_nav', type='PAGE_UP', value='PRESS')
|
||||
kmi.properties.direction = 'UP'
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
kmi = km.keymap_items.new('gp.layer_nav', type='PAGE_DOWN', value='PRESS')
|
||||
kmi.properties.direction = 'DOWN'
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
def unregister_keymap():
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
|
||||
addon_keymaps.clear()
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(GPT_OT_layer_nav)
|
||||
register_keymap()
|
||||
|
||||
def unregister():
|
||||
unregister_keymap()
|
||||
bpy.utils.unregister_class(GPT_OT_layer_nav)
|
57
__init__.py
57
__init__.py
|
@ -15,7 +15,7 @@ bl_info = {
|
|||
"name": "GP toolbox",
|
||||
"description": "Tool set for Grease Pencil in animation production",
|
||||
"author": "Samuel Bernou, Christophe Seux",
|
||||
"version": (1, 8, 1),
|
||||
"version": (1, 9, 0),
|
||||
"blender": (2, 91, 0),
|
||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||
"warning": "",
|
||||
|
@ -51,6 +51,7 @@ from . import OP_depth_move
|
|||
from . import OP_key_duplicate_send
|
||||
from . import OP_layer_manager
|
||||
from . import OP_layer_picker
|
||||
from . import OP_layer_nav
|
||||
from . import OP_material_picker
|
||||
from . import OP_eraser_brush
|
||||
from . import TOOL_eraser_brush
|
||||
|
@ -310,6 +311,38 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
|
||||
fixprops: bpy.props.PointerProperty(type = GP_PG_FixSettings)
|
||||
|
||||
## GP Layer navigator
|
||||
|
||||
nav_use_fade : BoolProperty(
|
||||
name='Fade Inactive Layers',
|
||||
description='Fade Inactive layers to determine active layer in a glimpse',
|
||||
default=True)
|
||||
|
||||
nav_fade_val : FloatProperty(
|
||||
name='Fade Value',
|
||||
description='Fade value for other layers when navigating (0=invisible)',
|
||||
default=0.35, min=0.0, max=0.95, step=1, precision=2)
|
||||
|
||||
nav_limit : FloatProperty(
|
||||
name='Fade Duration',
|
||||
description='Time of other layer faded when using layer navigation',
|
||||
default=1.4, min=0.1, max=5, step=2, precision=1, subtype='TIME', unit='TIME')
|
||||
|
||||
nav_use_fade_in : BoolProperty(
|
||||
name='Progressive Fade Back',
|
||||
description='Use a fade on other layer when navigating',
|
||||
default=True)
|
||||
|
||||
nav_fade_in_time : FloatProperty(
|
||||
name='Fade-In Time',
|
||||
description='Duration of the fade',
|
||||
default=0.5, min=0.1, max=5, step=2, precision=2, subtype='TIME', unit='TIME')
|
||||
|
||||
nav_interval : FloatProperty(
|
||||
name='Refresh Rate',
|
||||
description='Refresh rate for fade updating (upper value means stepped fade)',
|
||||
default=0.04, min=0.01, max=0.5, step=3, precision=2, subtype='TIME', unit='TIME')
|
||||
|
||||
## Temp cutter
|
||||
# temp_cutter_use_shortcut: BoolProperty(
|
||||
# name = "Use temp cutter Shortcut",
|
||||
|
@ -415,6 +448,21 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
|
||||
box = layout.box()
|
||||
box.label(text='Tools options:')
|
||||
|
||||
subbox= box.box()
|
||||
subbox.label(text='Layer Navigation')
|
||||
col = subbox.column()
|
||||
col.prop(self, 'nav_use_fade')
|
||||
if self.nav_use_fade:
|
||||
row = col.row()
|
||||
row.prop(self, 'nav_fade_val')
|
||||
row.prop(self, 'nav_limit')
|
||||
row = subbox.row(align=False)
|
||||
row.prop(self, 'nav_use_fade_in')
|
||||
if self.nav_use_fade_in:
|
||||
row.prop(self, 'nav_fade_in_time', text='Fade Back Time')
|
||||
# row.prop(self, 'nav_interval') # Do not expose refresh rate for now, not usefull to user...
|
||||
|
||||
box.prop(self, 'use_precise_eraser')
|
||||
|
||||
if self.pref_tabs == 'KEYS':
|
||||
|
@ -427,14 +475,15 @@ class GPTB_prefs(bpy.types.AddonPreferences):
|
|||
## TOOL_eraser_brush.addon_keymaps # has a checkbox in
|
||||
|
||||
prev_key_category = ''
|
||||
kmi_see_list = []
|
||||
for kms in [
|
||||
OP_keyframe_jump.addon_keymaps,
|
||||
OP_copy_paste.addon_keymaps,
|
||||
OP_breakdowner.breakdowner_addon_keymaps,
|
||||
OP_breakdowner.addon_keymaps,
|
||||
OP_key_duplicate_send.addon_keymaps,
|
||||
OP_layer_picker.addon_keymaps,
|
||||
OP_material_picker.addon_keymaps,
|
||||
OP_layer_nav.addon_keymaps,
|
||||
# OP_layer_manager.addon_keymaps, # Do not display, wm.call_panel call panel ops mixed with natives shortcut (F2)
|
||||
]:
|
||||
|
||||
ct = 0
|
||||
|
@ -644,6 +693,7 @@ def register():
|
|||
OP_eraser_brush.register()
|
||||
OP_material_picker.register()
|
||||
OP_layer_picker.register()
|
||||
OP_layer_nav.register()
|
||||
TOOL_eraser_brush.register()
|
||||
handler_draw_cam.register()
|
||||
UI_tools.register()
|
||||
|
@ -670,6 +720,7 @@ def unregister():
|
|||
UI_tools.unregister()
|
||||
handler_draw_cam.unregister()
|
||||
TOOL_eraser_brush.unregister()
|
||||
OP_layer_nav.unregister()
|
||||
OP_layer_picker.unregister()
|
||||
OP_material_picker.unregister()
|
||||
OP_eraser_brush.unregister()
|
||||
|
|
|
@ -8,6 +8,8 @@ def register_keymaps():
|
|||
# km = addon.keymaps.new(name = "3D View", space_type = "VIEW_3D")# in 3D context
|
||||
# km = addon.keymaps.new(name = "Window", space_type = "EMPTY")# from everywhere
|
||||
|
||||
|
||||
## Sculpt mode toggles
|
||||
km = addon.keymaps.new(name = "Grease Pencil Stroke Sculpt Mode", space_type = "EMPTY", region_type='WINDOW')
|
||||
|
||||
kmi = km.keymap_items.new('wm.context_toggle', type='ONE', value='PRESS')
|
||||
|
@ -22,6 +24,12 @@ def register_keymaps():
|
|||
kmi.properties.data_path='scene.tool_settings.use_gpencil_select_mask_segment'
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
## T temp cutter (need disabling of native T shortcut, maybe expose a button to set the shortcut as user ?)
|
||||
# km = addon.keymaps.new(name = "Grease Pencil", space_type = "EMPTY")
|
||||
# kmi = km.keymap_items.new('gpencil.stroke_cutter', type='LEFTMOUSE', value='PRESS', key_modifier='T')
|
||||
# kmi.properties.flat_caps=False
|
||||
# addon_keymaps.append((km, kmi))
|
||||
|
||||
def unregister_keymaps():
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
|
|
63
utils.py
63
utils.py
|
@ -30,19 +30,14 @@ def set_matrix(gp_frame,mat):
|
|||
|
||||
# get view vector location (the 2 methods work fine)
|
||||
def get_view_origin_position():
|
||||
#method 1
|
||||
## method 1
|
||||
# from bpy_extras import view3d_utils
|
||||
# region = bpy.context.region
|
||||
# rv3d = bpy.context.region_data
|
||||
# view_loc = view3d_utils.region_2d_to_origin_3d(region, rv3d, (region.width/2.0, region.height/2.0))
|
||||
# print("view_loc1", view_loc)#Dbg
|
||||
|
||||
#method 2
|
||||
## method 2
|
||||
r3d = bpy.context.space_data.region_3d
|
||||
view_loc2 = r3d.view_matrix.inverted().translation
|
||||
# print("view_loc2", view_loc2)#Dbg
|
||||
# if view_loc != view_loc2: print('Might be an error when finding view coordinate')
|
||||
|
||||
return view_loc2
|
||||
|
||||
def location_to_region(worldcoords):
|
||||
|
@ -76,6 +71,10 @@ def object_derived_get(ob, scene):
|
|||
return ob_matrix_pairs
|
||||
|
||||
|
||||
# -----------------
|
||||
### Bmesh
|
||||
# -----------------
|
||||
|
||||
def link_vert(v,ordered_vert) :
|
||||
for e in v.link_edges :
|
||||
other_vert = e.other_vert(v)
|
||||
|
@ -147,7 +146,11 @@ def gp_stroke_to_bmesh(strokes):
|
|||
return strokes_info
|
||||
|
||||
|
||||
def simple_draw_gp_stroke(pts,frame,width = 2, mat_id = 0):
|
||||
# -----------------
|
||||
### GP Drawing
|
||||
# -----------------
|
||||
|
||||
def simple_draw_gp_stroke(pts, frame, width = 2, mat_id = 0):
|
||||
'''
|
||||
draw basic stroke by passing list of point 3D coordinate
|
||||
the frame to draw on and optional width parameter (default = 2)
|
||||
|
@ -169,11 +172,11 @@ def simple_draw_gp_stroke(pts,frame,width = 2, mat_id = 0):
|
|||
return stroke
|
||||
|
||||
## OLD - need update
|
||||
def draw_gp_stroke(loop_info,frame,palette,width = 2) :
|
||||
def draw_gp_stroke(loop_info, frame, palette, width = 2) :
|
||||
stroke = frame.strokes.new(palette)
|
||||
|
||||
stroke.line_width = width
|
||||
stroke.display_mode = '3DSPACE'# old->draw_mode
|
||||
stroke.display_mode = '3DSPACE'# old -> draw_mode
|
||||
|
||||
for i,info in enumerate(loop_info) :
|
||||
stroke.points.add()
|
||||
|
@ -894,13 +897,6 @@ def draw_kmi(km, kmi, layout):
|
|||
### linking utility
|
||||
# -----------------
|
||||
|
||||
"""
|
||||
def link_objects_in_blend(filepath, obj_name, link=True):
|
||||
'''Link an object by name from a file, if link is False, append instead of linking'''
|
||||
with bpy.data.libraries.load(filepath, link=link) as (data_from, data_to):
|
||||
data_to.objects = [o for o in data_from.objects if o == obj_name] # c.startswith(obj_name)
|
||||
return data_to.objects
|
||||
"""
|
||||
def link_objects_in_blend(filepath, obj_name_list, link=True):
|
||||
'''Link an object by name from a file, if link is False, append instead of linking'''
|
||||
if isinstance(obj_name_list, str):
|
||||
|
@ -923,3 +919,36 @@ def check_objects_in_blend(filepath, avoid_camera=True):
|
|||
else:
|
||||
l = [o for o in data_from.objects]
|
||||
return l
|
||||
|
||||
|
||||
# -----------------
|
||||
### props handling
|
||||
# -----------------
|
||||
|
||||
def iterate_selector(zone, attr, state, info_attr = None, active_access='active'):
|
||||
'''Iterate with given attribute'''
|
||||
item_number = len(zone)
|
||||
if item_number <= 1:
|
||||
return
|
||||
|
||||
if getattr(zone, attr) == None:
|
||||
print('no', attr, 'in', zone)
|
||||
return
|
||||
|
||||
if state: # swap
|
||||
info = None
|
||||
bottom = None
|
||||
new_index = getattr(zone, attr) + state
|
||||
setattr(zone, attr, new_index % item_number)
|
||||
|
||||
if new_index == item_number:
|
||||
bottom = 1 # bottom reached, cycle to first
|
||||
elif new_index < 0:
|
||||
bottom = -1 # up reached, cycle to last
|
||||
|
||||
if info_attr:
|
||||
active_item = getattr(zone, active_access) # active by default
|
||||
if active_item:
|
||||
info = getattr(active_item, info_attr)
|
||||
|
||||
return info, bottom
|
||||
|
|
Loading…
Reference in New Issue