brush palette loading feature

1.4.3

- feat: load brushes from blend (behave like a Brush palette)
- ui: add load brushes within tool brush dropdown panel and in the top bar in drawmode
- pref: Set project brushes folder in addon preferences
gpv2
Pullusb 2021-06-14 17:41:41 +02:00
parent 94e3b7a7ad
commit 682048af63
3 changed files with 94 additions and 2 deletions

View File

@ -1,6 +1,12 @@
# Changelog
1.4.3
- feat: load brushes from blend
- ui: add load brushes within tool brush dropdown panel and in the top bar in drawmode
- pref: Set project brushes folder in addon preferences
1.4.2
- feat: new material cleaner in GP layer menu with 3 options

77
OP_brushes.py Normal file
View File

@ -0,0 +1,77 @@
import bpy
from bpy_extras.io_utils import ImportHelper
from pathlib import Path
from .utils import get_addon_prefs
def get_brushes(blend_fp):
'''Get all brush from passed blend that aren't already in there (can take Path object)'''
cur_brushes = [b.name for b in bpy.data.brushes]
with bpy.data.libraries.load(str(blend_fp), link=False) as (data_from, data_to):
# load brushes if not already there
data_to.brushes = [b for b in data_from.brushes if not b in cur_brushes]
## force fake user for appended the brushes
for b in data_to.brushes:
print(f'Append Brush: {b.name}')
b.use_fake_user = True
return len(data_to.brushes)
class GPTB_OT_load_brushes(bpy.types.Operator, ImportHelper):
bl_idname = "gp.load_brushes"
bl_label = "Load Brushes"
bl_description = "Load all brushes from chosen blend file in current if brushes aren't already there\nIf a replacement is needed, delete the prefious brush before"
#bl_options = {"REGISTER", "INTERNAL"}
# @classmethod
# def poll(cls, context):
# return context.object and context.object.type == 'GPENCIL'
filename_ext = '.blend'
filter_glob: bpy.props.StringProperty(default='*.blend', options={'HIDDEN'} )
filepath : bpy.props.StringProperty(
name="File Path",
description="File path used for import",
maxlen= 1024)
def execute(self, context):
print(f'Appending brushes from file : {self.filepath}')
bct = get_brushes(self.filepath)
if bct:
self.report({'INFO'}, f'{bct} brushes appended')
else:
self.report({'WARNING'}, 'Brushes are already there (if need to re-import, delete first)')
return {"FINISHED"}
### -- MENU ENTRY --
def load_brush_ui(self, context):
if context.mode == 'PAINT_GPENCIL':
self.layout.operator('gp.load_brushes', icon='SMALL_TRI_RIGHT_VEC') # KEYTYPE_JITTER_VEC
def load_brush_top_bar_ui(self, context):
if context.mode == 'PAINT_GPENCIL':
self.layout.operator('gp.load_brushes')
classes = (
GPTB_OT_load_brushes,
)
def register():
for cl in classes:
bpy.utils.register_class(cl)
bpy.types.VIEW3D_MT_brush_gpencil_context_menu.append(load_brush_ui)
bpy.types.VIEW3D_HT_tool_header.append(load_brush_top_bar_ui)
def unregister():
bpy.types.VIEW3D_HT_tool_header.remove(load_brush_top_bar_ui)
bpy.types.VIEW3D_MT_brush_gpencil_context_menu.remove(load_brush_ui)
for cl in reversed(classes):
bpy.utils.unregister_class(cl)

View File

@ -15,7 +15,7 @@ bl_info = {
"name": "GP toolbox",
"description": "Set of tools for Grease Pencil in animation production",
"author": "Samuel Bernou",
"version": (1, 4, 2),
"version": (1, 4, 3),
"blender": (2, 91, 0),
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
"warning": "",
@ -41,6 +41,7 @@ from . import OP_helpers
from . import OP_keyframe_jump
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
@ -192,6 +193,11 @@ class GPTB_prefs(bpy.types.AddonPreferences):
description="Path to palette containing palette.json files to save and load",
default="//", maxlen=0, subtype='DIR_PATH')#, update = set_palette_path
brush_path : StringProperty(
name="Brushes directory",
description="Path to brushes containing the blends holding the brushes",
default="//", maxlen=0, subtype='DIR_PATH')#, update = set_palette_path
## Playblast prefs
playblast_auto_play : BoolProperty(
name="Playblast auto play",
@ -311,8 +317,9 @@ class GPTB_prefs(bpy.types.AddonPreferences):
row.prop(self, 'render_res_x', text='Width')
row.prop(self, 'render_res_y', text='Height')
## Palette
box.label(text='Palette library folder:')
box.label(text='Project folders:')
box.prop(self, 'palette_path')
box.prop(self, 'brush_path')
## render output
box.prop(self, 'output_path')
@ -443,6 +450,7 @@ def register():
OP_playblast_bg.register()
OP_playblast.register()
OP_palettes.register()
OP_brushes.register()
OP_cursor_snap_canvas.register()
OP_render.register()
OP_copy_paste.register()
@ -478,6 +486,7 @@ def unregister():
OP_copy_paste.unregister()
OP_render.unregister()
OP_cursor_snap_canvas.unregister()
OP_brushes.unregister()
OP_palettes.unregister()
OP_file_checker.unregister()
OP_helpers.unregister()