stripped obsolete features and compacted UI

1.7.0

- remove: Obsolete operators and panels
  - Remove "line closer" panel as it's been a native tool for a while in 2.9x (stop register of `GP_guided_colorize > OP_line_closer`)
  - Remove "Render" subpanel, obsolete and not adapted to production
- ui: clean and refactor
  - Gp clipboard panel and aimation Manager subpanel layout to aligned columns (gain space)
  - add `GP` on each panel name for wuick eye search
  - follow cursor now in animation manager subpanel (should be in an extra menu or removed in the end)
gpv2
Pullusb 2021-10-20 13:56:01 +02:00
parent 8b838b52ca
commit f7e8dce0ff
7 changed files with 147 additions and 614 deletions

View File

@ -1,5 +1,16 @@
# Changelog
1.7.0
- removed: Obsolete operators and panels
- Remove "line closer" panel as it's been a native tool for a while in 2.9x (stop register of `GP_guided_colorize > OP_line_closer`)
- Remove "Render" subpanel, obsolete and not adapted to production
- ui: clean and refactor
- Gp clipboard panel and aimation Manager subpanel layout to aligned columns (gain space)
- add `GP` on each panel name for wuick eye search
- follow cursor now in animation manager subpanel (should be in an extra menu or removed in the end)
1.6.9
- change: material picker (`S` and `Alt+S`) quick trigger, cahnge is only triggered if ley is pressed less than 200ms
@ -139,29 +150,29 @@
- feat: show main cam frame when in draw_cam
1.3.2:
1.3.2
- change: disable manip cam name drawing
- code: add initial support for main cam frame draw within camera view
1.3.1:
1.3.1
- fix: native refresh error that rarely happen that doesn't completely refresh the scene on keyframe jump.
- Use a double frame change to ensure refresh.
1.3.0:
1.3.0
- feat: new duplicate send to layer feaure - `ctrl + shift + D` in GP dopesheet
1.2.2:
1.2.2
- fix: realign anim return error
1.2.1:
1.2.1
- fix: Breakdowner initial error check
1.2.0:
1.2.0
- feat: New depth move operator that handle both perspective and orthographic cam
- feat: Realign, added drawing plane checkbox to autoset to Front after realign
@ -170,67 +181,67 @@
- doc: Added changelog file (moved list from readme)
- doc: relative link to changelog and FR_readme in main readme
1.1.0:
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
1.0.8:
1.0.8
- feat: Keyframe jump filter added in UI to change general behavior. Keymap own jump filter can override this new global settings if specified
1.0.7:
1.0.7
- feat: Keyframe jump filter by type. User can now choose if the shortcut should jump on a specific keyframe type (All by default)
1.0.5:
1.0.5
- GP copy-paste : Pasted stroke are now selected (allow to use it to quickly rip/split strokes with cut/paste on the same layer)
1.0.4:
1.0.4
- UI: Better cam ref exposition in Toolbox panel
- Access to opacity
- merge activation bool with source type icon
- feat: Added a clear active frame operator (`gp.clear_active_frame` to add manually in keymaps)
1.0.3:
1.0.3
- feat: add "Append Materials To Selected" to material submenu. Append materials to other selected GP objects if there aren't there.
1.0.2:
1.0.2
- pref: Added option to disable always remap relative on save in addon-preference
1.0.1:
1.0.1
- fix: copy paste problems
- Get points uv_properties (used for brushed points)
- Trigger an update on each pasted strokes, recalculate badly drawn uv and fills (works in 2.93+)
1.0.0:
1.0.0
- Compatible with official grease pencil tools
- removed box deform and rotate canvas that existed in other
0.9.3:
0.9.3
- feat: keyframe jump keys are now auto-binded
- UI: added keyframe jump customisation in addon pref
- code: split keyframe jump in a separate file with his new key updater
0.9.2:
0.9.2
- doc: Correct download link (important, bugged the addon install) + update
- code: added tracker url
- updater: remove updater temp file, reset minimum version, turn off verbose mode
0.9.1:
0.9.1
- Public release
- prefs: added fps as part of project settings
@ -240,38 +251,38 @@
- doc: Added fully-detailed french readme
0.8.0:
0.8.0
- feat: Added background_rendering playblast, derivating from Tonton's playblaster
- stripped associated properties from properties.py and passed as wm props.
0.7.2:
0.7.2
- fix: Palette importer bug
0.7.0:
0.7.0
- feat: auto create empty frame on color layer
0.6.3:
0.6.3
- shortcut: added 1,2,3 to change sculpt mask mode (like native edit mode shortcut)
0.6.2:
0.6.2
- feat: colorisation, Option to change stop lines length
- Change behavior of `cursor_snap` ops when a non-GP object is selected to mode: `surface project`
- Minor refactor for submodule register
0.6.1:
0.6.1
- feat: render objects grouped, one anim render with all ticked object using manual output name
0.6.0:
0.6.0
- feat: Include GP clipoard's "In place" custom cut/copy/paste using OS clipboard
0.5.9:
0.5.9
- feat: render exporter
- Render a selection of GP object isolated from the rest
@ -281,21 +292,21 @@
- check file: set onion skin keyframe filter to 'All_type' on all GP datablock
- check file: set scene resolution to settings in prefs (default 2048x1080)
0.5.8:
0.5.8
- feat: GP material append on active object from single blend file
0.5.7:
0.5.7
- Added warning message for cursor snapping
0.5.5 - 0.5.6:
0.5.6
- check file: added check for placement an projection mode for Gpencil.
- add a slider to change edit_lines_opacity globally for all GP data at once
- check file: auto-check additive drawing (to avoid empty frame with "only selected channel" in Dopesheet)
0.5.4:
0.5.4
- feat: anim manager in his own GP_toolbox submenu:
- button to list disabled anim (allow to quickly check state of the scene)
@ -303,19 +314,19 @@
- shift clic to target selection only
- check file: added disabled fcurved counter alert with detail in console
0.5.3:
0.5.3
- fix: broken obj cam (add custom prop on objcam to track wich was main cam)
- check file option: change select active tool (choice added in addon preferences)
0.5.2:
0.5.2
- Revert back obj_cam operator for following object (native lock view follow only translation)
- Changed method for canvas rotation to more robust rotate axis.
- Add operators on link checker to open containing folder/file of link
- Refactor: file checkers in their own file
0.5.1:
0.5.1
- fix: error when empty material slot on GP object.
- fix: cursor snap on GP canvas when GP is parented
@ -330,11 +341,11 @@
- set show slider and sync range
- set fps to 24
0.4.6:
0.4.6
- feat: basic Palette manager with base material check and warning
0.4.5:
0.4.5
- open blender config folder from addon preference
- fix: obj cam parent on selected object
@ -343,29 +354,29 @@
- camview: potential bug when cam is parented with some specific angle (could not reproduce)
0.4.4:
0.4.4
- feat: added cursor follow handlers and UI toggle
0.4.3:
0.4.3
- change playblast out to 'images' and add playblast as name prefix
0.4.2:
0.4.2
- feat: GP canvas cursor snap wiht new `view3d.cusor_snap` operator
- fix: canvas rotate works with parented camera !
- wip: added an attmpt to replicate camera rotate modal with view matrix but no luck.
0.4.1:
0.4.1
- feat: Alternative cameras: parent to main cam (roll without affecting main cam), parent to active object at current view (follow current Grease pencil object)
0.4.0:
0.4.0
- Added a standalone working version of box_deform (stripped preferences keeping only best configuration with autoswap)
0.3.8:
0.3.8
- UI: expose onion skin in interface
- UI: expose autolock in interface
@ -373,47 +384,47 @@
- code: refactor, pushed most of class register in their owner file
- tool: tool to rename current or all grease pencil datablock with different name than container object
0.3.7:
0.3.7
- UI: new interface with tabs for addon preferences
- UI: possible to disable color panel from preference (might be deleted if unusable)
- docs: change readme changelog format and correct doc
0.3.6:
0.3.6
- UI: Stoplines : add a button for quickly set stoplines visibility.
0.3.5:
0.3.5
- Fix : No more camera rotation undo when ctrl+Z on next stroke (canvas rotate push and undo)
- Fix: Enter key added to valid object-breakdown modal.
0.3.3:
0.3.3
- version 1 beta (stable) of line gap closing tools for better bucket fill tool performance with UI
0.3.3:
0.3.3
- version 1 beta of gmic colorize
- variant of `screen.gp_keyframe_jump` through keymap seetings
0.3.0:
0.3.0
- new homemade [breakdowner operator for object](https://blenderartists.org/t/pose-mode-animation-tools-for-object-mode/1221322) mode with auto keymap : Shift + E
- GP cutter shortcut ops to map with `wm.temp_cutter` (with "Any" as press mode) or `wm.sticky_cutter` (Modal sticky-key version)
0.2.3:
0.2.3
- add operator to `screen.gp_keyframe_jump`
- add shortcut to rotate canvas
- fix duplicate class
0.2.2:
0.2.2
- separated props resolution_percentage parameter
- playblast options for launching folder and opening folder
0.2.1:
0.2.1
- playblast feature
- Button to go zoom 100% or fit screen
@ -421,22 +432,22 @@
- Fix reference panel : works with video and display in a box layout.
- close pseudo-color panel by default (plan to move it to Gpencil tab)
0.2.0:
0.2.0
- UI: Toggle camera background images from Toolbox panel
- UI: quick access to passepartout
- Feature: option to use namespace for pseudo color
0.1.5:
0.1.5
- added CGC-auto-updater
0.1.3:
0.1.3
- flip cam x
- inital stage of overlay toggle (need pref/multiple pref)
0.1.2:
0.1.2
- subpanel of GP data (instead of direct append)
- initial commit with GP pseudo color

View File

@ -13,7 +13,7 @@
import bpy
from . import OP_line_closer
# from . import OP_line_closer
from . import OP_create_empty_frames
@ -45,11 +45,11 @@ def register():
for cls in classes:
bpy.utils.register_class(cls)
OP_create_empty_frames.register()
OP_line_closer.register()
# OP_line_closer.register()
bpy.types.Scene.gpcolor_props = bpy.props.PointerProperty(type = GPCOLOR_PG_settings)
def unregister():
OP_line_closer.unregister()
# OP_line_closer.unregister()
OP_create_empty_frames.unregister()
for cls in reversed(classes):
bpy.utils.unregister_class(cls)

View File

@ -637,13 +637,16 @@ class GPCLIP_PT_clipboard_ui(bpy.types.Panel):
def draw(self, context):
layout = self.layout
row = layout.row(align=True)
col = layout.column(align=True)
row = col.row(align=True)
row.operator('gp.copy_strokes', text='Copy strokes', icon='COPYDOWN')
row.operator('gp.cut_strokes', text='Cut strokes', icon='PASTEFLIPUP')
layout.operator('gp.paste_strokes', text='Paste strokes', icon='PASTEDOWN')
layout.separator()
layout.operator('gp.copy_multi_strokes', text='Copy layers', icon='COPYDOWN')
layout.operator('gp.paste_multi_strokes', text='Paste layers', icon='PASTEDOWN')
col.operator('gp.paste_strokes', text='Paste strokes', icon='PASTEDOWN')
# layout.separator()
col = layout.column(align=True)
col.operator('gp.copy_multi_strokes', text='Copy layers', icon='COPYDOWN')
col.operator('gp.paste_multi_strokes', text='Paste layers', icon='PASTEDOWN')
###---TEST zone

View File

@ -1,482 +0,0 @@
import bpy
import os
from os import listdir, scandir
from os.path import join, dirname, basename, exists, isfile, isdir, splitext
import re, fnmatch, glob
from pathlib import Path
from time import strftime
C = bpy.context
D = bpy.data
from .utils import open_file, open_folder, get_addon_prefs
### render the png sequences
def initial_render_checks(context=None):
if not context:
context=bpy.context
if not bpy.data.is_saved:
return "File is not saved, render cancelled"
cam = context.scene.camera
if not cam:
return "No active Camera"
if cam.name == 'draw_cam':
if not cam.parent:
return "Camera is draw_cam but has no parent cam to render from..."
context.scene.camera = cam.parent
if cam.name == 'obj_cam':
if not cam.get('maincam_name'):
return "Cannot found main camera from obj_cam. Set main camera manually"
main_cam = context.scene.objects.get(cam['maincam_name'])
if not main_cam:
return f"Main camera not found with name: {cam['main_cam']}"
context.scene.camera = main_cam
return
exclude = (
### add lines here to exclude specific attribute
'bl_rna', 'identifier','name_property','rna_type','properties', 'compare', 'to_string',#basic
)
"""
rd_keep = [
"resolution_percentage",
"resolution_x",
"resolution_y",
"filepath",
"use_stamp",
"stamp_font_size",
]
im_keep = [
'file_format',
'color_mode',
'quality',
'compression',
]
ff_keep = [
'codec',
'format',
'constant_rate_factor',
'ffmpeg_preset',
'gopsize',
'audio_codec',
'audio_bitrate',
]
"""
def render_with_restore():
class RenderFileRestorer:
rd = bpy.context.scene.render
im = rd.image_settings
ff = rd.ffmpeg
# ffmpeg (ff) need to be before image_settings(im) in list
# otherwise __exit__ may try to restore settings of image mode in video mode !
# ex : "RGBA" not found in ('BW', 'RGB') (will still not stop thx to try block)
zones = [rd, ff, im]
obviz = {}
# layviz = []
# matviz = []
closeline = False
val_dic = {}
cam = bpy.context.scene.camera
enter_context = None
def __enter__(self):
self.enter_context = bpy.context
## store attribute of data_path in self.zones list.
for data_path in self.zones:
self.val_dic[data_path] = {}
for attr in dir(data_path):#iterate in attribute of given datapath
if attr not in exclude and not attr.startswith('__') and not callable(getattr(data_path, attr)) and not data_path.is_property_readonly(attr):
self.val_dic[data_path][attr] = getattr(data_path, attr)
# cam
if self.cam and self.cam.name == 'draw_cam':
if self.cam.parent:
bpy.context.scene.camera = self.cam.parent
#case of obj cam
if self.cam.name == 'obj_cam':
bpy.context.scene.camera = bpy.context.scene.objects.get(self.cam['main_cam'])
for ob in bpy.context.scene.objects:
self.obviz[ob.name] = ob.hide_render
close_mat = bpy.data.materials.get('closeline')
if close_mat and not close_mat.grease_pencil.hide:
close_mat.grease_pencil.hide = True
self.closeline = True
# for gpo in bpy.context.scene.objects:
# if gpo.type != 'GPENCIL':
# continue
# if not gpo.materials.get('closeline'):
# continue
# self.closelines[gpo] = gpo.materials['closeline'].hide_render
def __exit__(self, type, value, traceback):
## reset header text
# self.enter_context.area.header_text_set(None)
### maybe keep render settings for custom output with right mode
"""
## restore attribute from self.zones list
for data_path, prop_dic in self.val_dic.items():
for attr, val in prop_dic.ietms():
try:
setattr(data_path, attr, val)
except Exception as e:
print(f"/!\ Impossible to re-assign: {attr} = {val}")
print(e)
"""
if self.cam:
bpy.context.scene.camera = self.cam
for obname, val in self.obviz.items():
bpy.context.scene.objects[obname].hide_render = val
if self.closeline:
close_mat = bpy.data.materials.get('closeline')
if close_mat:
close_mat.grease_pencil.hide = False
return RenderFileRestorer()
def set_render_settings():
prefs = get_addon_prefs()
rd = bpy.context.scene.render
rd.use_sequencer = False
rd.use_compositing = False
rd.use_overwrite = True
rd.image_settings.file_format = 'PNG'
rd.image_settings.color_mode = 'RGBA'
rd.image_settings.color_depth = '16'
rd.image_settings.compression = 80 #maybe up the compression a bit...
rd.resolution_percentage = 100
rd.resolution_x, rd.resolution_y = prefs.render_res_x, prefs.render_res_y
rd.use_stamp = False
rd.film_transparent = True
def render_invididually(context, render_list):
'''Receive a list of object to render individually isolated'''
prefs = get_addon_prefs()
scn = context.scene
rd = scn.render
error_list = []
with render_with_restore():
set_render_settings()
# rd.filepath = join(dirname(bpy.data.filepath), basename(bpy.data.filepath))
# rd.frame_path(frame=0, preview=0, view="_sauce")## give absolute render filepath with some suffix
## set filepath
blend = Path(bpy.data.filepath)
### render by object in list
for obname in render_list:
the_obj = scn.objects.get(obname)
if not the_obj:
error_list.append(f'! Could not found {obname} in scene, skipped !')
continue
## Kill renderability of all
for o in scn.objects:
o.hide_render = True
the_obj.hide_render = False
# f'{blend.stem}_'
# fp = blend.parents[1] / "compo" / "base" / obname / (obname+'_')
fp = (blend.parent / prefs.output_path.lstrip(r'\/')).resolve() / obname / (obname+'_')
rd.filepath = str(fp)
# Freeze so impossible to display advance
# context.area.header_text_set(f'rendering > {obname} ...')
### render
# bpy.ops.render.render_wrap(use_view=viewport)
bpy.ops.render.render(animation=True)
# print("render Done :", fp)#Dbg
return error_list
def render_grouped(context, render_list):
'''Receive a list of object to render grouped'''
scn = context.scene
rd = scn.render
error_list = []
with render_with_restore():
set_render_settings()
## Kill renderability of all
for o in scn.objects:
o.hide_render = True
### show all object of the list
for obname in render_list:
the_obj = scn.objects.get(obname)
if not the_obj:
error_list.append(f'! Could not found {obname} in scene, skipped !')
continue
the_obj.hide_render = False
## Use current file path of setup output path else following :
blend = Path(bpy.data.filepath)
outname = context.scene.gptoolprops.name_for_current_render
# fp = blend.parents[1] / "compo" / "base" / outname / (outname+'_')
fp = (blend.parent / prefs.output_path.lstrip(r'\/')).resolve() / outname / (outname+'_')
rd.filepath = str(fp)
### render
# bpy.ops.render.render_wrap(use_view=viewport)
bpy.ops.render.render(animation=True)
# print("render Done :", fp)#Dbg
return error_list
class GPTRD_OT_render_anim(bpy.types.Operator):
bl_idname = "render.render_anim"
bl_label = "render anim"
bl_description = "Launch animation render"
bl_options = {"REGISTER"}
# use_view : bpy.props.BoolProperty(name='use_view', default=False)
to_render = []
mode : bpy.props.StringProperty(name="render mode",
description="change render mode for list rendering", default="INDIVIDUAL")
render_bool : bpy.props.BoolVectorProperty(name="render bools",
description="", default=tuple([True]*32), size=32, subtype='NONE')
def invoke(self, context, event):
# prefs = get_addons_prefs_and_set()
# if not prefs.local_folder:
# self.report({'ERROR'}, f'Project local folder is not specified in addon preferences')
# return {'CANCELLED'}
if self.mode == 'GROUP' and not context.scene.gptoolprops.name_for_current_render:
self.report({'ERROR'}, 'Need to set ouput name')
return {'CANCELLED'}
prefs = get_addon_prefs()
print('exclusions list ->', prefs.render_obj_exclusion)
exclusion_obj = [name.strip() for name in prefs.render_obj_exclusion.split(',')]
print('object exclusion list: ', exclusion_obj)
print('initial self.to_render: ', self.to_render)
self.to_render = []#reset
## check object to render with basic filter
for ob in context.scene.objects:
if ob.type != 'GPENCIL':
continue
if any(x in ob.name.lower() for x in exclusion_obj): #('old', 'rough', 'trash', 'test')
print('Skip', ob.name)
continue
self.to_render.append(ob.name)
if not self.to_render:
self.report({'ERROR'}, 'No GP to render')
return {'CANCELLED'}
## Reset at each render
# self.render_bool = tuple([True]*32)# reset all True
## disable for some name (ex: BG)
wm = context.window_manager
return wm.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
layout.label(text='Tick objects to render')
for i, name in enumerate(self.to_render):
row = layout.row()
row.prop(self, 'render_bool', index = i, text = name)
# for i, set in enumerate(SETS):
# column.row().prop(context.scene.spritesheet, 'sets', index=i, text=set)
def execute(self, context):
prefs = get_addon_prefs()
err = initial_render_checks(context)
if err:
self.report({'ERROR'}, err)
return {"CANCELLED"}
render_list = []
for i, name in enumerate(self.to_render):
if self.render_bool[i]:
render_list.append(name)
if not render_list:
self.report({'ERROR'}, 'Nothing to render')
return {"CANCELLED"}
# self.report({'INFO'}, f'rendering {render_list}')#Dgb
# return {"FINISHED"}#Dgb
if self.mode == 'INDIVIDUAL':
errlist = render_invididually(context, render_list)
elif self.mode == 'GROUP':
errlist = render_grouped(context, render_list)
blend = Path(bpy.data.filepath)
# out = blend.parents[1] / "compo" / "base"
out = (blend.parent / prefs.output_path.lstrip(r'\/')).resolve()
if out.exists():
open_folder(str(out))
else:
errlist.append('No compo/base folder created')
if errlist:
self.report({'ERROR'}, '\n'.join(errlist))
return {"FINISHED"}
### ---- Setup render path
class GPTRD_OT_setup_render_path(bpy.types.Operator):
bl_idname = "render.setup_render_path"
bl_label = "Setup render"
bl_description = "Setup render settings for normal render of the current state\nHint: F12 to check one frame, ctrl+F12 to render animation"
bl_options = {"REGISTER"}
def execute(self, context):
#get name and check
prefs = get_addon_prefs()
outname = context.scene.gptoolprops.name_for_current_render
if not outname:
self.report({'ERROR'}, 'No output name has been set')
return {"CANCELLED"}
err = initial_render_checks(context)
if err:
self.report({'ERROR'}, err)
return {"CANCELLED"}
set_render_settings()
blend = Path(bpy.data.filepath)
# out = blend.parents[1] / "compo" / "base"
out = (blend.parent / prefs.output_path.lstrip(r'\/')).resolve()
fp = out / outname / (outname+'_')
context.scene.render.filepath = str(fp)
self.report({'INFO'}, f'output setup for "{outname}"')
return {"FINISHED"}
class GPTRD_OT_use_active_object_infos(bpy.types.Operator):
bl_idname = "render.use_active_object_name"
bl_label = "Use object Name"
bl_description = "Write active object name (active layer name with shift click on the button)"
bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return context.object
def invoke(self, context, event):
# wm = context.window_manager
# return wm.invoke_props_dialog(self)
self.shift = event.shift
return self.execute(context)
def execute(self, context):
ob = context.object
#get name and check
if self.shift:
if ob.type != "GPENCIL":
self.report({'ERROR'}, 'Not a GP, no access to layers')
return {"CANCELLED"}
lay = ob.data.layers.active
if not lay:
self.report({'ERROR'}, 'No active layer found')
return {"CANCELLED"}
context.scene.gptoolprops.name_for_current_render = lay.info
else:
context.scene.gptoolprops.name_for_current_render = ob.name
# self.report({'INFO'}, 'Output Name changed')
return {"FINISHED"}
""" class GPTRD_OT_render_as_is(bpy.types.Operator):
bl_idname = "render.render_as_is"
bl_label = "render current"
bl_description = "Launch animation render with current setup"
bl_options = {"REGISTER"}
def execute(self, context):
err = initial_render_checks(context)
if err:
self.report({'ERROR'}, err)
return {"CANCELLED"}
return {"FINISHED"} """
### --- REGISTER
classes = (
GPTRD_OT_render_anim,
GPTRD_OT_setup_render_path,
GPTRD_OT_use_active_object_infos,
)
def register():
for cl in classes:
bpy.utils.register_class(cl)
def unregister():
for cl in classes:
bpy.utils.unregister_class(cl)
'''
## Potential cancelling method for image sequence rendering.
for cfra in range(start, end+1):
print("Baking frame " + str(cfra))
# update scene to new frame and bake to template image
scene.frame_set(cfra)
ret = bpy.ops.object.bake_image()
if 'CANCELLED' in ret:
return {'CANCELLED'}
'''
"""
class PBLAST_OT_render_wrap(bpy.types.Operator):
bl_idname = "render.render_wrap"
bl_label = "Render wraped"
bl_description = "render"
bl_options = {"REGISTER"}## need hide
use_view : bpy.props.BoolProperty(name='use_view', default=False)
def execute(self, context):
if self.use_view:## openGL
ret = bpy.ops.render.opengl('INVOKE_DEFAULT', animation=True, view_context=True)
else:## normal render
ret = bpy.ops.render.render('INVOKE_DEFAULT', animation=True)
return {"FINISHED"}
"""
""" if __name__ == "__main__":
register() """

View File

@ -36,7 +36,7 @@ class GPTB_PT_dataprop_panel(bpy.types.Panel):
## UI in Gpencil sidebar menu
class GPTB_PT_sidebar_panel(bpy.types.Panel):
bl_label = "Toolbox"
bl_label = "GP Toolbox"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
@ -50,18 +50,18 @@ class GPTB_PT_sidebar_panel(bpy.types.Panel):
# addon_updater_ops.check_for_update_background()
# layout.label(text='View options:')
col = layout.column()
## flip X cam
if context.scene.camera and context.scene.camera.scale.x < 0:
# layout.label(text='! Flipped !')
row = layout.row(align=True)
row = col.row(align=True)
row.operator('gp.mirror_flipx', text = 'Mirror flip', icon = 'MOD_MIRROR')# ARROW_LEFTRIGHT
row.label(text='',icon='LOOP_BACK')
else:
layout.operator('gp.mirror_flipx', text = 'Mirror flip', icon = 'MOD_MIRROR')# ARROW_LEFTRIGHT
col.operator('gp.mirror_flipx', text = 'Mirror flip', icon = 'MOD_MIRROR')# ARROW_LEFTRIGHT
## draw/manipulation camera
col = layout.column()
if context.scene.camera and context.scene.camera.name.startswith(('draw', 'obj')):
row = col.row(align=True)
row.operator('gp.draw_cam_switch', text = 'Main cam', icon = 'OUTLINER_OB_CAMERA')
@ -126,13 +126,11 @@ class GPTB_PT_sidebar_panel(bpy.types.Panel):
layout.operator('gp.straight_stroke', icon ="CURVE_PATH")
## Options
layout.separator()
layout.label(text = 'Options:')
col = layout.column()
col.label(text = 'Options:')
## Kf Jump filter
layout.prop(context.scene.gptoolprops, 'keyframe_type', text='Jump On') # Keyframe Jump
col = layout.column()
col.prop(context.scene.gptoolprops, 'keyframe_type', text='Jump On') # Keyframe Jump
# col.prop(context.space_data.overlay, 'use_gpencil_onion_skin') # not often used
if context.object and context.object.type == 'GPENCIL':
@ -157,41 +155,18 @@ class GPTB_PT_sidebar_panel(bpy.types.Panel):
else:
col.label(text='No GP object selected')
col.prop(context.scene.gptoolprops, 'edit_lines_opacity')
row = col.row(align=True)
## realign / reproject
row.operator('gp.realign', icon='AXIS_FRONT')
## move in depth
row.operator('object.depth_proportional_move', text='Depth move', icon='TRANSFORM_ORIGINS')
## col.operator('gp.batch_reproject_all_frames') # text=Batch Reproject # added to context menu
## check drawing alignement
col.operator('gp.check_canvas_alignement', icon='DRIVER_ROTATIONAL_DIFFERENCE')
## Create empty frame on layer (ops stored under GP_colorize... might be best to separate in another panel )
col.operator('gp.create_empty_frames', icon='DECORATE_KEYFRAME')
## File checker
row = col.row(align=True)
row.operator('gp.file_checker', text = 'Check file', icon = 'SCENE_DATA')
row.operator('gp.links_checker', text = 'Check links', icon = 'UNLINKED')
text, icon = ('Cursor Follow On', 'PIVOT_CURSOR') if context.scene.gptoolprops.cursor_follow else ('Cursor Follow Off', 'CURSOR')
col.prop(context.scene.gptoolprops, 'cursor_follow', text=text, icon=icon)
# Mention update as notice
# addon_updater_ops.update_notice_box_ui(self, context)
# row = layout.row(align=False)
# row.label(text='arrow choice')
# row.operator("my_operator.multi_op", text='', icon='TRIA_LEFT').left = 1
# row.operator("my_operator.multi_op", text='', icon='TRIA_RIGHT').left = 0
class GPTB_PT_anim_manager(bpy.types.Panel):
bl_label = "Animation manager"
bl_label = "Animation Manager"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
@ -204,11 +179,12 @@ class GPTB_PT_anim_manager(bpy.types.Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
col = layout.column()
## Animation enable disable anim (shift click to select) OP_helpers.GPTB_OT_toggle_mute_animation
layout.operator('gp.list_disabled_anims')
col.operator('gp.list_disabled_anims')
## Objs ()
row = layout.row(align=True)
row = col.row(align=True)
row.label(text='Obj anims:')
ops = row.operator('gp.toggle_mute_animation', text = 'ON')#, icon = 'GRAPH'
ops.skip_gp = True
@ -220,7 +196,7 @@ class GPTB_PT_anim_manager(bpy.types.Panel):
ops.skip_obj = False
ops.mute = True
## Gps
row = layout.row(align=True)
row = col.row(align=True)
row.label(text='Gp anims:')
ops = row.operator('gp.toggle_mute_animation', text = 'ON')#, icon = 'GRAPH'
ops.skip_gp = False
@ -232,6 +208,12 @@ class GPTB_PT_anim_manager(bpy.types.Panel):
ops.skip_obj = True
ops.mute = True
## This can go in an extra category...
col = layout.column()
col.use_property_split = False
text, icon = ('Cursor Follow On', 'PIVOT_CURSOR') if context.scene.gptoolprops.cursor_follow else ('Cursor Follow Off', 'CURSOR')
col.prop(context.scene.gptoolprops, 'cursor_follow', text=text, icon=icon)
class GPTB_PT_toolbox_playblast(bpy.types.Panel):
bl_label = "Playblast"
bl_space_type = "VIEW_3D"
@ -255,17 +237,13 @@ class GPTB_PT_toolbox_playblast(bpy.types.Panel):
row.operator('render.playblast_anim', text = 'Viewport').use_view = True
class GPTB_PT_tint_layers(bpy.types.Panel):
bl_label = "Tint layers"
bl_label = "Tint Layers"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
bl_parent_id = "GPTB_PT_sidebar_panel"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.scene.camera
# def draw_header(self,context):
# self.layout.prop(context.scene.camera.data, "show_background_images", text="")
@ -282,40 +260,65 @@ class GPTB_PT_tint_layers(bpy.types.Panel):
col.operator("gp.auto_tint_gp_layers", icon = "COLOR").reset = False
col.operator("gp.auto_tint_gp_layers", text = "Reset tint", icon = "COLOR").reset = True
class GPTB_PT_render(bpy.types.Panel):
bl_label = "Render"
class GPTB_PT_checker(bpy.types.Panel):
bl_label = "Checker"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
bl_parent_id = "GPTB_PT_sidebar_panel"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.scene.camera
# def draw_header(self,context):
# self.layout.prop(context.scene.camera.data, "show_background_images", text="")
def draw(self, context):
layout = self.layout
layout.operator('render.render_anim', text = 'Render invividually', icon = 'RENDERLAYERS').mode = 'INDIVIDUAL'#RENDER_STILL #RESTRICT_RENDER_OFF
layout.operator('render.render_anim', text = 'Render grouped', icon = 'IMAGE_RGB').mode = 'GROUP'
col = layout.column()
row = col.row(align=True)
## realign / reproject
row.operator('gp.realign', icon='AXIS_FRONT')
## move in depth
row.operator('object.depth_proportional_move', text='Depth move', icon='TRANSFORM_ORIGINS')
layout.separator()
row = layout.row()
row.prop(context.scene.gptoolprops, 'name_for_current_render', text = 'Output name')#icon = 'OUTPUT'
row.operator('render.use_active_object_name', text = '', icon='OUTLINER_DATA_GP_LAYER')#icon = 'OUTPUT'
## col.operator('gp.batch_reproject_all_frames') # text=Batch Reproject # added to context menu
## check drawing alignement
col.operator('gp.check_canvas_alignement', icon='DRIVER_ROTATIONAL_DIFFERENCE')
layout.operator('render.setup_render_path', text = 'Setup output', icon = 'TOOL_SETTINGS')#SETTINGS
blend = bpy.data.filepath
if blend:
blend = Path(blend)
out = blend.parents[1] / "compo" / "base"
layout.operator("wm.path_open", text='Open render folder', icon='FILE_FOLDER').filepath = str(out)
## File checker
row = col.row(align=True)
row.operator('gp.file_checker', text = 'Check file', icon = 'SCENE_DATA')
row.operator('gp.links_checker', text = 'Check links', icon = 'UNLINKED')
class GPTB_PT_color(bpy.types.Panel):
bl_label = "Color"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
bl_parent_id = "GPTB_PT_sidebar_panel"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
## Create empty frame on layer
layout.operator('gp.create_empty_frames', icon='DECORATE_KEYFRAME')
""" # unused : added in Animation Manager
class GPTB_PT_extra(bpy.types.Panel):
bl_label = "Extra"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Gpencil"
bl_parent_id = "GPTB_PT_sidebar_panel"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
col = layout.column()
text, icon = ('Cursor Follow On', 'PIVOT_CURSOR') if context.scene.gptoolprops.cursor_follow else ('Cursor Follow Off', 'CURSOR')
col.prop(context.scene.gptoolprops, 'cursor_follow', text=text, icon=icon)
"""
"""
## unused -- (integrated in sidebar_panel)
@ -363,11 +366,12 @@ def palette_manager_menu(self, context):
classes = (
GPTB_PT_sidebar_panel,
GPTB_PT_checker,
GPTB_PT_anim_manager,
GPTB_PT_toolbox_playblast,
GPTB_PT_color,
GPTB_PT_tint_layers,
GPTB_PT_render,
## GPTB_PT_cam_ref_panel,
GPTB_PT_toolbox_playblast,
# GPTB_PT_extra,
)
def register():

View File

@ -15,7 +15,7 @@ bl_info = {
"name": "GP toolbox",
"description": "Set of tools for Grease Pencil in animation production",
"author": "Samuel Bernou, Christophe Seux",
"version": (1, 6, 9),
"version": (1, 7, 0),
"blender": (2, 91, 0),
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
"warning": "",
@ -43,7 +43,6 @@ from . import OP_cursor_snap_canvas
from . import OP_palettes
from . import OP_brushes
from . import OP_file_checker
from . import OP_render
from . import OP_copy_paste
from . import OP_realign
from . import OP_depth_move
@ -571,7 +570,6 @@ def register():
OP_palettes.register()
OP_brushes.register()
OP_cursor_snap_canvas.register()
OP_render.register()
OP_copy_paste.register()
OP_realign.register()
OP_depth_move.register()
@ -612,7 +610,6 @@ def unregister():
OP_depth_move.unregister()
OP_realign.unregister()
OP_copy_paste.unregister()
OP_render.unregister()
OP_cursor_snap_canvas.unregister()
OP_brushes.unregister()
OP_palettes.unregister()

View File

@ -157,7 +157,7 @@ class GP_PG_ToolsSettings(bpy.types.PropertyGroup):
default=False, update=cursor_follow_update)
edit_lines_opacity : FloatProperty(
name="edit lines Opacity", description="Change edit lines opacity for all grease pencils",
name="Edit Lines Opacity", description="Change edit lines opacity for all grease pencils",
default=0.5, min=0.0, max=1.0, step=3, precision=2, update=change_edit_lines_opacity)
## render