2
$\begingroup$

I'm trying to create a tool to help me manage my hierarchy. I have this operator which creates an empty object, that i will use for parenting later on. This works fine, but blender crashes when i undo this operator.

Steps to reproduce:

  • Run this script
  • Click on the "Create Empty" button
  • Undo (ctrl + z)

This crashes blender with EXCEPTION_ACCESS_VIOLATION

import bpy

class CreateEmptyOperator(bpy.types.Operator):
    bl_label = "Create Empty"
    bl_idname = "wm.create_empty"

    def execute(self, context):
        parent = bpy.data.objects.new("Empty", None)
        bpy.context.collection.objects.link(parent)
        return{'FINISHED'}

class MyPanel(bpy.types.Panel):
    bl_idname = "OBJECT_PT_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    def draw(self, context):
        self.layout.operator("wm.create_empty")

bpy.utils.register_class(CreateEmptyOperator)
bpy.utils.register_class(MyPanel)

What can I do to avoid the crash?

$\endgroup$
1
  • 2
    $\begingroup$ You need to enable undo for your operator. Not the same question but the answer is the same : blender.stackexchange.com/q/7066/86891 By the way, replace bpy.context.collection.objects.link(parent) by context.collection.objects.link(parent) (always use passed context when available) $\endgroup$
    – Gorgious
    May 19, 2021 at 11:51

1 Answer 1

2
$\begingroup$

If you want the Undo / Redo system to work with a custom operator, you need to add bl_options = {'UNDO'} when defining the class.

Your script then becomes :

import bpy

class CreateEmptyOperator(bpy.types.Operator):
    bl_label = "Create Empty"
    bl_idname = "wm.create_empty"
    bl_options = {'UNDO'}

    def execute(self, context):
        parent = bpy.data.objects.new("Empty", None)
        context.collection.objects.link(parent)  # Use the current context when available instead of bpy.context
        return {'FINISHED'}

class MyPanel(bpy.types.Panel):
    bl_idname = "OBJECT_PT_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    def draw(self, context):
        self.layout.operator("wm.create_empty")

bpy.utils.register_class(CreateEmptyOperator)
bpy.utils.register_class(MyPanel)
$\endgroup$

You must log in to answer this question.

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