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
|
# 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
|
1.4.2
|
||||||
|
|
||||||
- feat: new material cleaner in GP layer menu with 3 options
|
- 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",
|
"name": "GP toolbox",
|
||||||
"description": "Set of tools for Grease Pencil in animation production",
|
"description": "Set of tools for Grease Pencil in animation production",
|
||||||
"author": "Samuel Bernou",
|
"author": "Samuel Bernou",
|
||||||
"version": (1, 4, 2),
|
"version": (1, 4, 3),
|
||||||
"blender": (2, 91, 0),
|
"blender": (2, 91, 0),
|
||||||
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
|
||||||
"warning": "",
|
"warning": "",
|
||||||
|
@ -41,6 +41,7 @@ from . import OP_helpers
|
||||||
from . import OP_keyframe_jump
|
from . import OP_keyframe_jump
|
||||||
from . import OP_cursor_snap_canvas
|
from . import OP_cursor_snap_canvas
|
||||||
from . import OP_palettes
|
from . import OP_palettes
|
||||||
|
from . import OP_brushes
|
||||||
from . import OP_file_checker
|
from . import OP_file_checker
|
||||||
from . import OP_render
|
from . import OP_render
|
||||||
from . import OP_copy_paste
|
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",
|
description="Path to palette containing palette.json files to save and load",
|
||||||
default="//", maxlen=0, subtype='DIR_PATH')#, update = set_palette_path
|
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 prefs
|
||||||
playblast_auto_play : BoolProperty(
|
playblast_auto_play : BoolProperty(
|
||||||
name="Playblast auto play",
|
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_x', text='Width')
|
||||||
row.prop(self, 'render_res_y', text='Height')
|
row.prop(self, 'render_res_y', text='Height')
|
||||||
## Palette
|
## Palette
|
||||||
box.label(text='Palette library folder:')
|
box.label(text='Project folders:')
|
||||||
box.prop(self, 'palette_path')
|
box.prop(self, 'palette_path')
|
||||||
|
box.prop(self, 'brush_path')
|
||||||
|
|
||||||
## render output
|
## render output
|
||||||
box.prop(self, 'output_path')
|
box.prop(self, 'output_path')
|
||||||
|
@ -443,6 +450,7 @@ def register():
|
||||||
OP_playblast_bg.register()
|
OP_playblast_bg.register()
|
||||||
OP_playblast.register()
|
OP_playblast.register()
|
||||||
OP_palettes.register()
|
OP_palettes.register()
|
||||||
|
OP_brushes.register()
|
||||||
OP_cursor_snap_canvas.register()
|
OP_cursor_snap_canvas.register()
|
||||||
OP_render.register()
|
OP_render.register()
|
||||||
OP_copy_paste.register()
|
OP_copy_paste.register()
|
||||||
|
@ -478,6 +486,7 @@ def unregister():
|
||||||
OP_copy_paste.unregister()
|
OP_copy_paste.unregister()
|
||||||
OP_render.unregister()
|
OP_render.unregister()
|
||||||
OP_cursor_snap_canvas.unregister()
|
OP_cursor_snap_canvas.unregister()
|
||||||
|
OP_brushes.unregister()
|
||||||
OP_palettes.unregister()
|
OP_palettes.unregister()
|
||||||
OP_file_checker.unregister()
|
OP_file_checker.unregister()
|
||||||
OP_helpers.unregister()
|
OP_helpers.unregister()
|
||||||
|
|
Loading…
Reference in New Issue