Проектируя новые операторы в Blender, мы можем делать их отменяемыми и не отменяемыми, указывая значение “UNDO” в параметре bl_options оператора. Но как быть, если нам нужно исключить из очереди отмены какой-либо уже существующий, например, системный оператор? Это очень просто сделать, переопределив оператор на собственный, без указания “UNDO” в его параметрах.
Для примера переопределим простейший оператор, добавляющий в сцену куб “mesh.primitive_cube_add”.
Определим переопределяющий класс-обертку, в функции execute которого мы будем просто вызывать системный оператор создания куба.
1 2 3 4 5 6 7 8 |
class TEST_OT_add_cube_no_undo(bpy.types.Operator): bl_idname = 'test.add_cube_no_undo' bl_label = 'CUBE NO UNDO' bl_options = {'REGISTER'} def execute(self, context): bpy.ops.mesh.primitive_cube_add() return {'FINISHED'} |
В параметре “bl_options” мы не указываем “UNDO” среди значений сета, чтобы наш оператор-обертка был неотменяемым и не реагировал на нажатие комбинации клавиш “Ctrl + z”.
Чтобы проверить, как будет работать наш оператор, создадим в N-панели пользовательскую панель TEST с двумя кнопками. На первую привяжем тот самый стандартный оператор “mesh.primitive_cube_add”, а на вторую – наш переопределяющий оператор.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class TEST_PT_panel(bpy.types.Panel): bl_idname = 'TEST_PT_panel' bl_label = 'UNDO TEST' bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'TEST' def draw(self, context): self.layout.operator( operator='mesh.primitive_cube_add' ) self.layout.operator( operator='test.add_cube_no_undo' ) |
Зарегистрируем оба класса в Blender Python API.
1 2 |
bpy.utils.register_class(TEST_OT_add_cube_no_undo) bpy.utils.register_class(TEST_PT_panel) |
Выполним скрипт, нажав на кнопку со стрелочкой “Run Script”.
Теперь в нашей тестовой панели нажмем несколько раз на кнопку “Add Cube”, на которую привязан стандартный системный оператор создания куба в сцене. После чего попробуем отменить эти действия, нажимая Ctrl +z. Мы видим, как при каждом нажатии отменяется создание одного куба.
Теперь нажмем несколько раз на кнопку “CUBE NO UNDO”, которая исполняет наш переопределяющий оператор, а после этого так же попробуем отменить наши действия. В этом случае мы видим, что при одном нажатии Ctrl + z со сцены убираются сразу все кубы, созданные через наш оператор.
Так происходит потому, что наш оператор блокирует отмену действия, даже несмотря на то, что по сути он просто вызывает системный оператор, у которого отмена действия имеется. Так как у каждого отдельного выполнения нашего переопределяющего оператора отмены нет, “откат” производится сразу к состоянию до первого нажатия неотменяемого оператора.