I wrote a simple add-on to enable canvas flipping in Blender (for Grease Pencil) with a hotkey, as well as a menu button. All it does is multiply the camera's local X scale by -1:
current_scene = bpy.context.scene;
active_camera = current_scene.camera;
active_camera.scale.x *= -1;
This basically works. However, if I:
- flip the canvas
- draw a Grease Pencil stroke
- undo with Ctrl+Z
the last stroke disappears as expected, but the canvas also flips back. Somehow both actions are interpreted as one single operation.
(This code is based on a brief description of a similar functionality in the GP Toolbox add-on, which has the same problem.)
Why are the actions combined? Did I miss a step in the code?
Full add-on code below.
bl_info = {
"name": "Flip Canvas",
"author": "Latin1",
"version": (1, 0),
"blender": (4, 1, 1),
"location": "Scene",
"description": "Inverts the camera's x axis",
"warning": "",
"doc_url": "",
"category": "Scene",
}
import bpy;
def flip_canvas_btn(context):
current_scene = bpy.context.scene;
active_camera = current_scene.camera;
active_camera.scale.x *= -1;
class Flip_Canvas(bpy.types.Operator):
"""Tooltip"""
bl_idname = "latin1.flip_canvas";
bl_label = "Flip canvas";
def execute(self, context):
flip_canvas_btn(context);
return {'FINISHED'};
def menu_func(self, context):
self.layout.operator(SimpleOperator.bl_idname, text=SimpleOperator.bl_label);
# ----------------------------------------------------------------------------------------
class LayoutDemoPanel(bpy.types.Panel):
"""Creates a Panel in the scene context of the properties editor"""
bl_label = "Flip the canvas"
bl_idname = "SCENE_PT_layout"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout;
scene = context.scene;
# Interface button
row = layout.row();
row.scale_y = 1.0;
row.operator("latin1.flip_canvas");
def register():
bpy.utils.register_class(Flip_Canvas);
bpy.types.VIEW3D_MT_object.append(menu_func);
bpy.utils.register_class(LayoutDemoPanel);
def unregister():
bpy.utils.unregister_class(Flip_Canvas);
bpy.types.VIEW3D_MT_object.remove(menu_func);
bpy.utils.unregister_class(LayoutDemoPanel);
if __name__ == "__main__":
register();