2026-03-16

This commit is contained in:
2026-03-17 15:39:39 -06:00
parent 67782275d5
commit 330fed4231
29 changed files with 532 additions and 199 deletions
+52 -45
View File
@@ -30,21 +30,18 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
settings.brushstroke_method = self.method
if settings.curve_mode == 'GP':
bpy.ops.object.grease_pencil_add(type='EMPTY')
context.object.name = name
context.object.data.name = name
brushstrokes_object = context.object
context.collection.objects.unlink(brushstrokes_object)
else:
if settings.curve_mode == 'CURVE':
brushstrokes_data = bpy.data.curves.new(name, type='CURVE')
brushstrokes_data.dimensions = '3D'
elif settings.curve_mode == 'CURVES':
brushstrokes_data = bpy.data.hair_curves.new(name)
brushstrokes_object = bpy.data.objects.new(name, brushstrokes_data)
brushstrokes_data = bpy.data.grease_pencils.new(name)
bs_layer = brushstrokes_data.layers.new('Brushstrokes')
bs_layer.frames.new(1)
elif settings.curve_mode == 'CURVE':
brushstrokes_data = bpy.data.curves.new(name, type='CURVE')
brushstrokes_data.dimensions = '3D'
elif settings.curve_mode == 'CURVES':
brushstrokes_data = bpy.data.hair_curves.new(name)
brushstrokes_object = bpy.data.objects.new(name, brushstrokes_data)
# link to surface object's collections (fall back to active collection if all are linked data)
utils.link_to_collections_by_ref(brushstrokes_object, surface_object)
utils.link_to_collections_by_ref(brushstrokes_object, surface_object, unlink=False)
brushstrokes_object.visible_shadow = False
brushstrokes_object['BSBST_version'] = utils.addon_version
@@ -55,21 +52,18 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
def new_flow_object(self, context, name, surface_object):
settings = context.scene.BSBST_settings
if settings.curve_mode == 'GP':
bpy.ops.object.grease_pencil_add(type='EMPTY')
context.object.name = name
context.object.data.name = name
flow_object = context.object
context.collection.objects.unlink(flow_object)
else:
if settings.curve_mode == 'CURVE':
flow_data = bpy.data.curves.new(name, type='CURVE')
flow_data.dimensions = '3D'
elif settings.curve_mode == 'CURVES':
flow_data = bpy.data.hair_curves.new(name)
flow_object = bpy.data.objects.new(name, flow_data)
flow_data = bpy.data.grease_pencils.new(name)
fl_layer = flow_data.layers.new('Flow')
fl_layer.frames.new(1)
elif settings.curve_mode == 'CURVE':
flow_data = bpy.data.curves.new(name, type='CURVE')
flow_data.dimensions = '3D'
elif settings.curve_mode == 'CURVES':
flow_data = bpy.data.hair_curves.new(name)
flow_object = bpy.data.objects.new(name, flow_data)
# link to surface object's collections (fall back to active collection if all are linked data)
utils.link_to_collections_by_ref(flow_object, surface_object)
utils.link_to_collections_by_ref(flow_object, surface_object, unlink=False)
visibility_options = [
'visible_camera',
@@ -112,7 +106,7 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
self.report({"ERROR"}, "Surface Object needs an available UV Map")
return {"CANCELLED"}
name = f'{surface_object.name} - Brushstrokes'
name = utils.bs_name(surface_object.name)
brushstrokes_object = self.new_brushstrokes_object(context, name, surface_object)
flow_is_required = settings.brushstroke_method == 'SURFACE_FILL'
if flow_is_required:
@@ -151,7 +145,9 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
with context.temp_override(**override):
bpy.ops.object.material_slot_add()
brushstrokes_object.material_slots[0].material = preset_material
settings.silent_switch = True
settings.context_material = preset_material
settings.silent_switch = False
brushstrokes_object['BSBST_material'] = settings.context_material
# transfer preset modifiers to new brushstrokes TODO: refactor to deduplicate
@@ -238,7 +234,7 @@ class BSBST_OT_new_brushstrokes(bpy.types.Operator):
mod.show_group_selector = False
# update brushstroke context
utils.find_context_brushstrokes(None)
utils.find_context_brushstrokes(context.scene, context.view_layer.depsgraph)
for i, name in enumerate([bs.name for bs in settings.context_brushstrokes]):
if name == brushstrokes_object.name:
settings.active_context_brushstrokes_index = i
@@ -297,7 +293,7 @@ class BSBST_OT_delete_brushstrokes(bpy.types.Operator):
edit_toggle = settings.edit_toggle
settings.edit_toggle = False
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
settings.edit_toggle = edit_toggle
return {"CANCELLED"}
@@ -313,7 +309,7 @@ class BSBST_OT_delete_brushstrokes(bpy.types.Operator):
if surface_object:
context.view_layer.objects.active = surface_object
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if bs_ob:
context.view_layer.objects.active = bs_ob
bs_ob.select_set(True)
@@ -346,7 +342,7 @@ class BSBST_OT_duplicate_brushstrokes(bpy.types.Operator):
def execute(self, context):
settings = context.scene.BSBST_settings
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
return {"CANCELLED"}
@@ -410,7 +406,7 @@ class BSBST_OT_copy_brushstrokes(bpy.types.Operator):
def execute(self, context):
settings = context.scene.BSBST_settings
active_surface_object = utils.get_surface_object(utils.get_active_context_brushstrokes_object(context))
active_surface_object = utils.get_surface_object(utils.get_active_context_brushstrokes_object(context.scene))
surface_objects = [ob for ob in context.selected_objects
if ob.type=='MESH'
@@ -423,7 +419,7 @@ class BSBST_OT_copy_brushstrokes(bpy.types.Operator):
bs_objects = [bpy.data.objects.get(bs.name) for bs in settings.context_brushstrokes]
bs_objects = [bs for bs in bs_objects if bs]
else:
bs_objects = [utils.get_active_context_brushstrokes_object(context)]
bs_objects = [utils.get_active_context_brushstrokes_object(context.scene)]
if not bs_objects:
return {"CANCELLED"}
@@ -450,6 +446,17 @@ class BSBST_OT_copy_brushstrokes(bpy.types.Operator):
# remap surface pointers and context linked data TODO: refactor to deduplicate
for ob in new_bs:
utils.link_to_collections_by_ref(ob, surface_object)
# if it's still using the default name initialize names again
if utils.split_id_name(ob.name)[0] == utils.bs_name(active_surface_object.name):
if utils.is_flow_object(ob):
ob.name = utils.flow_name(utils.bs_name(surface_object.name))
else:
ob.name = utils.bs_name(surface_object.name)
elif ob.name.startswith(active_surface_object.name):
ob.name = f"{surface_object.name}{ob.name[len(active_surface_object.name):]}"
ob.parent = surface_object
utils.set_surface_object(ob, surface_object)
@@ -504,16 +511,16 @@ class BSBST_OT_select_surface(bpy.types.Operator):
return bool(settings.context_brushstrokes)
def execute(self, context):
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
return {"CANCELLED"}
surface_object = getattr(bs_ob, '["BSBST_surface_object"]', None)
if not surface_object:
return {"CANCELLED"}
bpy.context.view_layer.objects.active = surface_object
if not context.mode == 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.view_layer.objects.active = surface_object
for ob in bpy.data.objects:
ob.select_set(False)
surface_object.select_set(True)
@@ -537,7 +544,7 @@ class BSBST_OT_assign_surface(bpy.types.Operator):
return bool(settings.context_brushstrokes)
def execute(self, context):
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
return {"CANCELLED"}
@@ -555,7 +562,7 @@ class BSBST_OT_assign_surface(bpy.types.Operator):
layout.prop_search(self, 'surface_object', bpy.data, 'objects')
def invoke(self, context, event):
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
surf_ob = utils.get_surface_object(bs_ob)
if surf_ob:
self.surface_object = surf_ob.name
@@ -632,7 +639,7 @@ class BSBST_OT_copy_flow(bpy.types.Operator):
return bool(settings.context_brushstrokes)
def execute(self, context):
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
flow_ob_old = utils.get_flow_object(bs_ob)
if not bs_ob:
return {"CANCELLED"}
@@ -670,7 +677,7 @@ class BSBST_OT_copy_flow(bpy.types.Operator):
def invoke(self, context, event):
settings = context.scene.BSBST_settings
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
for i in range(len(self.bs_list)):
self.bs_list.remove(0)
@@ -721,7 +728,7 @@ class BSBST_OT_switch_deformable(bpy.types.Operator):
bs_objects = [bpy.data.objects.get(bs.name) for bs in settings.context_brushstrokes]
bs_objects = [bs for bs in bs_objects if bs]
else:
bs_objects = [utils.get_active_context_brushstrokes_object(context)]
bs_objects = [utils.get_active_context_brushstrokes_object(context.scene)]
if not bs_objects:
return {"CANCELLED"}
@@ -762,7 +769,7 @@ class BSBST_OT_switch_animated(bpy.types.Operator):
bs_objects = [bpy.data.objects.get(bs.name) for bs in settings.context_brushstrokes]
bs_objects = [bs for bs in bs_objects if bs]
else:
bs_objects = [utils.get_active_context_brushstrokes_object(context)]
bs_objects = [utils.get_active_context_brushstrokes_object(context.scene)]
if not bs_objects:
return {"CANCELLED"}
@@ -963,7 +970,7 @@ class BSBST_OT_make_preset(bpy.types.Operator):
@classmethod
def poll(cls, context):
return bool(utils.get_active_context_brushstrokes_object(context))
return bool(utils.get_active_context_brushstrokes_object(context.scene))
def execute(self, context):
@@ -977,7 +984,7 @@ class BSBST_OT_make_preset(bpy.types.Operator):
settings.preset_object.modifiers.remove(mod)
# transfer brushstrokes modifiers to preset
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
return {"CANCELLED"}
for mod in bs_ob.modifiers:
@@ -1098,7 +1105,7 @@ class BSBST_OT_brushstrokes_toggle_attribute(bpy.types.Operator):
edit_toggle = settings.edit_toggle
settings.edit_toggle = False
bs_ob = utils.get_active_context_brushstrokes_object(context)
bs_ob = utils.get_active_context_brushstrokes_object(context.scene)
if not bs_ob:
settings.edit_toggle = edit_toggle
return {"CANCELLED"}