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
This commit is contained in:
		
							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 | ||||
|  | ||||
							
								
								
									
										77
									
								
								OP_brushes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								OP_brushes.py
									
									
									
									
									
										Normal 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) | ||||
							
								
								
									
										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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user