0
$\begingroup$

I am trying to code an addon that does the same thing as knife project but

  • duplicates the target object that will be cut
  • operates on the duplicate
  • separates the two cut pieces
  • deletes the one that isn't hidden by the piece used for cutting

I get as far as duplicating with this code

import bpy

class DuplicateAndKnifeProjectOperator(bpy.types.Operator):
    bl_idname = "object.knife_project_patch"
    bl_label = "Knife Project and Create Patch"
    bl_description = "Perform knife project and create a new patch mesh"
    
    @classmethod
    def poll(cls, context):
        return context.object is not None and context.object.type == 'MESH'


    
    def execute(self, context):
        if len(bpy.context.selected_objects) > 1:
            # Select the target object to be cut
            target_obj = bpy.context.object

            # Select the cutting object
            cutting_obj = bpy.context.selected_objects[0]

            # Duplicate the target object
            duplicate_obj = target_obj.copy()
            duplicate_obj.data = duplicate_obj.data.copy()
            bpy.context.collection.objects.link(duplicate_obj)

            # Apply any transformations to the duplicate object
            duplicate_obj.matrix_world = target_obj.matrix_world

            # Set the duplicate object as the active object
            bpy.context.view_layer.objects.active = duplicate_obj

            # Enter Edit Mode for the duplicate object
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.knife_project(cut_through=True)

            return {'FINISHED'}
        else:
            self.report({'WARNING'}, "Active object is not a mesh.")
            return {'CANCELLED'}


def menu_func(self, context):
    self.layout.operator(KnifeProjectOperator.bl_idname)


def register():
    bpy.utils.register_class(KnifeProjectOperator)
    bpy.types.VIEW3D_MT_edit_mesh_context_menu.append(menu_func)


def unregister():
    bpy.utils.unregister_class(KnifeProjectOperator)
    bpy.types.VIEW3D_MT_edit_mesh_context_menu.remove(menu_func)


if __name__ == "__main__":
    register()

But the cutting generates an error that says

RuntimeError: Error: No other selected objects have wire or boundary edges to use for projection 

and the outliner look like this:

enter image description here

What should I do instead?

$\endgroup$

1 Answer 1

0
$\begingroup$

I would try the following code for the interior portion of your "execute" function:

# Select the target object to be cut
target_obj = bpy.context.object

# Select the cutting object
cutting_obj = bpy.context.selected_objects[1]

# Duplicate the target object
duplicate_obj = target_obj.copy()
duplicate_obj.data = duplicate_obj.data.copy()
bpy.context.collection.objects.link(duplicate_obj)

# Apply any transformations to the duplicate object
duplicate_obj.matrix_world = target_obj.matrix_world

# Set duplicate object as the active object
bpy.context.view_layer.objects.active = duplicate_obj

# Select only the cutting object in edit mode
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode = "EDIT")
cutting_obj.select_set(True)
  
# Cut the duplicate object
bpy.ops.mesh.knife_project(cut_through=True)

For me, selected_objects[0] would always return the cube, no matter the selection order between the circle and cube, so using index 1 fixed that issue when selecting circle first then cube. I also select only the circle cutting object within edit mode. I believe you're getting that error because Blender thinks the cube is the cutting object.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .