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 preferencesgpv2
parent
94e3b7a7ad
commit
682048af63
|
@ -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
|
||||
|
|
|
@ -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)
|
13
__init__.py
13
__init__.py
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue