Brushstroke Tools: Initial Version #328

Merged
Simon Thommes merged 229 commits from SimonThommes/blender-studio-tools:brushstroke_tools-initial-version into main 2024-11-06 15:03:47 +01:00
4 changed files with 76 additions and 6 deletions
Showing only changes of commit 64bd04e517 - Show all commits

View File

@ -111,12 +111,16 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
flow_object.parent = surface_object flow_object.parent = surface_object
# assign preset material # assign preset material
if settings.preset_material: preset_material = getattr(settings.preset_object, '["BSBST_material"]', None)
if preset_material:
override = context.copy() override = context.copy()
override['object'] = brushstrokes_object override['object'] = brushstrokes_object
with context.temp_override(**override): with context.temp_override(**override):
bpy.ops.object.material_slot_add() bpy.ops.object.material_slot_add()
brushstrokes_object.material_slots[0].material = settings.preset_material brushstrokes_object.material_slots[0].material = preset_material
settings.context_material = preset_material
brushstrokes_object['BSBST_material'] = preset_material
if not settings.preset_object: if not settings.preset_object:
bpy.ops.brushstroke_tools.init_preset() bpy.ops.brushstroke_tools.init_preset()
@ -137,7 +141,7 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
elif link_context_type=='FLOW_OBJECT': elif link_context_type=='FLOW_OBJECT':
brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = flow_object brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = flow_object
elif link_context_type=='MATERIAL': elif link_context_type=='MATERIAL':
brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = settings.preset_material brushstrokes_object.modifiers[mod.name][f'{v.identifier}'] = settings.context_material
elif link_context_type=='UVMAP': elif link_context_type=='UVMAP':
brushstrokes_object.modifiers[mod.name][f'{v.identifier}_use_attribute'] = True brushstrokes_object.modifiers[mod.name][f'{v.identifier}_use_attribute'] = True
brushstrokes_object.modifiers[mod.name][f'{v.identifier}_attribute_name'] = surface_object.data.uv_layers.active.name brushstrokes_object.modifiers[mod.name][f'{v.identifier}_attribute_name'] = surface_object.data.uv_layers.active.name
@ -368,7 +372,8 @@ class BSBST_OT_init_preset(bpy.types.Operator):
self.init_draw(context) self.init_draw(context)
# select preset material # select preset material
settings.preset_material = bpy.data.materials['Brushstrokes'] settings.context_material = bpy.data.materials['Brushstrokes']
preset_object['BSBST_material'] = settings.context_material
return {"FINISHED"} return {"FINISHED"}

View File

@ -59,10 +59,33 @@ def update_active_brushstrokes(self, context):
def update_brushstroke_method(self, context): def update_brushstroke_method(self, context):
settings = context.scene.BSBST_settings settings = context.scene.BSBST_settings
preset_name = f'BSBST-PRESET_{settings.brushstroke_method}' preset_name = f'BSBST-PRESET_{settings.brushstroke_method}'
preset_object = bpy.data.objects.get(preset_name) preset_object = bpy.data.objects.get(preset_name)
settings.preset_object = preset_object settings.preset_object = preset_object
style_object = utils.get_active_context_brushstrokes_object(context)
if not style_object:
style_object = preset_object
if not style_object:
settings.context_material = None
return
if 'BSBST_material' in style_object.keys():
settings.context_material = style_object['BSBST_material']
else:
settings.context_material = None
def update_context_material(self, context):
settings = context.scene.BSBST_settings
style_object = utils.get_active_context_brushstrokes_object(context)
if not style_object:
style_object = settings.preset_object
if not style_object:
return
utils.set_brushstroke_material(style_object, self.context_material)
def update_link_context_type(self, context): def update_link_context_type(self, context):
self.link_context = True self.link_context = True
@ -102,6 +125,11 @@ def get_active_context_brushstrokes_index(self):
def set_active_context_brushstrokes_index(self, value): def set_active_context_brushstrokes_index(self, value):
settings = bpy.context.scene.BSBST_settings settings = bpy.context.scene.BSBST_settings
if not settings.context_brushstrokes:
if not settings.preset_object:
return
if 'BSBST_material' in settings.preset_object.keys():
settings.context_material = settings.preset_object['BSBST_material']
prev = self.get('active_context_brushstrokes_index') prev = self.get('active_context_brushstrokes_index')
self["active_context_brushstrokes_index"] = value self["active_context_brushstrokes_index"] = value
if prev == value: if prev == value:
@ -119,6 +147,8 @@ def set_active_context_brushstrokes_index(self, value):
bs_ob['BSBST_active'] = True bs_ob['BSBST_active'] = True
if settings.edit_toggle: if settings.edit_toggle:
utils.edit_active_brushstrokes(bpy.context) utils.edit_active_brushstrokes(bpy.context)
if 'BSBST_material' in bs_ob.keys():
settings.context_material = bs_ob['BSBST_material']
def link_context_type_items(self, context): def link_context_type_items(self, context):
items = [ items = [
@ -160,7 +190,6 @@ class BSBST_context_brushstrokes(bpy.types.PropertyGroup):
class BSBST_Settings(bpy.types.PropertyGroup): class BSBST_Settings(bpy.types.PropertyGroup):
attach_to_active_selection: bpy.props.BoolProperty(default=True) attach_to_active_selection: bpy.props.BoolProperty(default=True)
preset_object: bpy.props.PointerProperty(type=bpy.types.Object, name="Default/Preset Object") preset_object: bpy.props.PointerProperty(type=bpy.types.Object, name="Default/Preset Object")
preset_material: bpy.props.PointerProperty(type=bpy.types.Material, name="Preset Material")
assign_materials: bpy.props.BoolProperty(name='Assign Modifier Materials', default=True) assign_materials: bpy.props.BoolProperty(name='Assign Modifier Materials', default=True)
brushstroke_method: bpy.props.EnumProperty(default='SURFACE_FILL', update=update_brushstroke_method, brushstroke_method: bpy.props.EnumProperty(default='SURFACE_FILL', update=update_brushstroke_method,
items= [('SURFACE_FILL', 'Fill', 'Use surface fill method for new brushstroke object', 'OUTLINER_OB_FORCE_FIELD', 0),\ items= [('SURFACE_FILL', 'Fill', 'Use surface fill method for new brushstroke object', 'OUTLINER_OB_FORCE_FIELD', 0),\
@ -188,6 +217,7 @@ class BSBST_Settings(bpy.types.PropertyGroup):
('CURVES', 'Curves', 'Use hair curves (Full Support)', 'CURVES_DATA', 1), ('CURVES', 'Curves', 'Use hair curves (Full Support)', 'CURVES_DATA', 1),
]) ])
context_brushstrokes: bpy.props.CollectionProperty(type=BSBST_context_brushstrokes) context_brushstrokes: bpy.props.CollectionProperty(type=BSBST_context_brushstrokes)
context_material: bpy.props.PointerProperty(type=bpy.types.Material, name="Material", update=update_context_material)
active_context_brushstrokes_index: bpy.props.IntProperty( default = 0, active_context_brushstrokes_index: bpy.props.IntProperty( default = 0,
update=update_active_brushstrokes, update=update_active_brushstrokes,
get=get_active_context_brushstrokes_index, get=get_active_context_brushstrokes_index,

View File

@ -230,9 +230,11 @@ class BSBST_PT_brushstroke_tools_panel(bpy.types.Panel):
row.operator('brushstroke_tools.delete_brushstrokes', text='', icon='TRASH') row.operator('brushstroke_tools.delete_brushstrokes', text='', icon='TRASH')
style_panel.template_list("BSBST_UL_brushstroke_objects", "", settings, "context_brushstrokes", style_panel.template_list("BSBST_UL_brushstroke_objects", "", settings, "context_brushstrokes",
settings, "active_context_brushstrokes_index", rows=1, maxrows=5, sort_lock=True) 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 and is_preset: if not settings.preset_object and is_preset:
style_panel.operator("brushstroke_tools.init_preset", icon='MODIFIER') style_panel.operator("brushstroke_tools.init_preset", icon='MODIFIER')
else:
style_panel.prop(settings, 'context_material', icon='MATERIAL')
if style_object: if style_object:
for mod in style_object.modifiers: for mod in style_object.modifiers:

View File

@ -81,6 +81,39 @@ def mark_panel_hidden(mod_info, panel_name, hide=True):
socket_info.name = v_id socket_info.name = v_id
socket_info.hide_ui = hide socket_info.hide_ui = hide
def set_brushstroke_material(ob, material):
prev_mat = None
if 'BSBST_material' in ob.keys():
if ob['BSBST_material'] == material:
return
else:
prev_mat = ob['BSBST_material']
ob['BSBST_material'] = material
for mod in ob.modifiers:
mod_info = ob.modifier_info.get(mod.name)
if not mod_info:
continue
for s in mod_info.socket_info:
if not s.link_context:
continue
if not s.link_context_type == 'MATERIAL':
continue
mod[s.name] = material
ob.update_tag()
if ob.type == 'EMPTY':
return
if not ob.material_slots:
override = bpy.context.copy()
override['object'] = ob
with bpy.context.temp_override(**override):
bpy.ops.object.material_slot_add()
ob.material_slots[0].material = material
else:
for m_slot in ob.material_slots:
if m_slot.material == prev_mat:
m_slot.material = material
def deep_copy_mod_info(source_object, target_object): def deep_copy_mod_info(source_object, target_object):
for mod_info in source_object.modifier_info: for mod_info in source_object.modifier_info:
mod_info_tgt = target_object.modifier_info.add() mod_info_tgt = target_object.modifier_info.add()