Brushstroke Tools: Initial Version #328
@ -46,6 +46,8 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
|
||||
|
||||
# attach surface object pointer
|
||||
brushstrokes_object['BSBST_surface_object'] = surface_object
|
||||
brushstrokes_object['BSBST_active'] = True
|
||||
brushstrokes_object['BSBST_method'] = settings.brushstroke_method
|
||||
|
||||
if surface_object:
|
||||
surface_object.add_rest_position_attribute = True # TODO report if library data
|
||||
|
@ -1,4 +1,39 @@
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
@persistent
|
||||
def find_context_brushstrokes(dummy):
|
||||
context = bpy.context
|
||||
settings = context.scene.BSBST_settings
|
||||
# identify context brushstrokes
|
||||
for el in range(len(settings.context_brushstrokes)):
|
||||
settings.context_brushstrokes.remove(0)
|
||||
context_object = context.object
|
||||
if 'BSBST_surface_object' in context_object.keys():
|
||||
ob = context_object['BSBST_surface_object']
|
||||
if ob:
|
||||
context_object = ob
|
||||
for ob in bpy.data.objects:
|
||||
if not ('BSBST_surface_object' in ob.keys()):
|
||||
continue
|
||||
if not ob['BSBST_surface_object']:
|
||||
continue
|
||||
if not ob['BSBST_surface_object'] == context_object:
|
||||
continue
|
||||
bs = settings.context_brushstrokes.add()
|
||||
bs.name = ob.name
|
||||
bs.method = ob['BSBST_method']
|
||||
settings.active_context_brushstrokes_index = max(min(settings.active_context_brushstrokes_index, len(settings.context_brushstrokes)-1), 0)
|
||||
return
|
||||
|
||||
def update_active_brushstrokes(self, context):
|
||||
settings = context.scene.BSBST_settings
|
||||
for i, el in enumerate(settings.context_brushstrokes):
|
||||
ob = bpy.data.objects.get(el.name)
|
||||
if not ob:
|
||||
continue
|
||||
ob['BSBST_active'] = i == settings.active_context_brushstrokes_index
|
||||
return
|
||||
|
||||
def update_brushstroke_method(self, context):
|
||||
SimonThommes marked this conversation as resolved
Outdated
|
||||
settings = context.scene.BSBST_settings
|
||||
@ -14,6 +49,10 @@ class BSBST_socket_info(bpy.types.PropertyGroup):
|
||||
name: bpy.props.StringProperty(default='')
|
||||
socket_info: bpy.props.CollectionProperty(type=BSBST_link_context_setting)
|
||||
|
||||
class BSBST_context_brushstrokes(bpy.types.PropertyGroup):
|
||||
name: bpy.props.StringProperty(default='')
|
||||
method: bpy.props.StringProperty(default='')
|
||||
|
||||
class BSBST_Settings(bpy.types.PropertyGroup):
|
||||
attach_to_active_selection: bpy.props.BoolProperty(default=True)
|
||||
preset_object: bpy.props.PointerProperty(type=bpy.types.Object, name="Preset Object")
|
||||
@ -42,11 +81,13 @@ class BSBST_Settings(bpy.types.PropertyGroup):
|
||||
[('CURVE', 'Legacy', 'Use legacy curve type (Limited Support)', 'CURVE_DATA', 0),\
|
||||
('CURVES', 'Curves', 'Use hair curves (Full Support)', 'CURVES_DATA', 1),
|
||||
])
|
||||
#preset_mode
|
||||
context_brushstrokes: bpy.props.CollectionProperty(type=BSBST_context_brushstrokes)
|
||||
active_context_brushstrokes_index: bpy.props.IntProperty(default = 0, update=update_active_brushstrokes)
|
||||
|
||||
classes = [
|
||||
BSBST_link_context_setting,
|
||||
BSBST_socket_info,
|
||||
BSBST_context_brushstrokes,
|
||||
BSBST_Settings,
|
||||
]
|
||||
|
||||
@ -56,6 +97,8 @@ def register():
|
||||
bpy.types.Scene.BSBST_settings = bpy.props.PointerProperty(type=BSBST_Settings)
|
||||
bpy.types.Object.modifier_info = bpy.props.CollectionProperty(type=BSBST_socket_info)
|
||||
|
||||
bpy.app.handlers.depsgraph_update_post.append(find_context_brushstrokes)
|
||||
|
||||
def unregister():
|
||||
for c in classes:
|
||||
bpy.utils.unregister_class(c)
|
||||
|
@ -53,6 +53,26 @@ def draw_panel_ui_recursive(panel, panel_name, mod, items):
|
||||
row.prop(s, 'link_context', text='', icon=icon)
|
||||
return
|
||||
|
||||
class BSBST_UL_brushstroke_objects(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
settings = data
|
||||
context_brushstroke = item
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
if context_brushstroke:
|
||||
method_icon = 'BRUSH_DATA'
|
||||
if context_brushstroke.method == 'SURFACE_FILL':
|
||||
method_icon = 'OUTLINER_OB_FORCE_FIELD'
|
||||
elif context_brushstroke.method == 'SURFACE_DRAW':
|
||||
method_icon = 'OUTLINER_DATA_GP_LAYER'
|
||||
layout.label(text=context_brushstroke.name, icon=method_icon)
|
||||
else:
|
||||
layout.label(text="", translate=False, icon_value=icon)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
def draw_filter(self, context, layout):
|
||||
return
|
||||
|
||||
class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'UI'
|
||||
@ -88,10 +108,17 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
||||
|
||||
# identify style context
|
||||
style_object = context.object if settings.style_context=='BRUSHSTROKES' else settings.preset_object
|
||||
|
||||
if context.object and settings.style_context=='AUTO':
|
||||
if 'BSBST_surface_object' in context.object.keys():
|
||||
if settings.style_context=='PRESET':
|
||||
style_object = settings.preset_object
|
||||
else:
|
||||
if 'BSBST_active' in context.object.keys():
|
||||
style_object = context.object
|
||||
else:
|
||||
if settings.context_brushstrokes:
|
||||
bs_name = settings.context_brushstrokes[settings.active_context_brushstrokes_index].name
|
||||
context_bs = bpy.data.objects.get(bs_name)
|
||||
if context_bs:
|
||||
style_object = context_bs
|
||||
|
||||
is_preset = style_object == settings.preset_object
|
||||
|
||||
@ -105,6 +132,12 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
||||
style_header.row().prop(settings, 'style_context', icon_only=True, expand=True)
|
||||
|
||||
if style_panel:
|
||||
if settings.style_context=='BRUSHSTROKES' and not 'BSBST_active' in style_object.keys():
|
||||
style_panel.label(text='No Brushstroke Context Found', icon='ERROR')
|
||||
return
|
||||
if not is_preset and len(settings.context_brushstrokes)>0:
|
||||
style_panel.template_list("BSBST_UL_brushstroke_objects", "", settings, "context_brushstrokes",
|
||||
settings, "active_context_brushstrokes_index", rows=1, maxrows=5, sort_lock=True)
|
||||
style_panel.prop(settings, 'preset_material', icon='MATERIAL')
|
||||
if not settings.preset_object:
|
||||
style_panel.operator("brushstroke_tools.init_preset", icon='MODIFIER')
|
||||
@ -143,6 +176,7 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
|
||||
return
|
||||
|
||||
classes = [
|
||||
BSBST_UL_brushstroke_objects,
|
||||
BSBST_PT_brushstroke_tools_panel,
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
Generally, the code would be easier to read if line lengths were more limited. E.g. for Blender we have a 120 line length limit. That also makes it easier to have two files open next to each other. Such limits can be enforced automatically with auto-formatters like
autopep8
(what we currently use in Blender) or e.g.black
.