Every time you change a property in python, a new undo command will be created.
This means that from Glaxnimate you can undo/redo every single operation by itself.
# After the following two lines you'll see "Update width" and "Update height" # in the Undo History view. Each can be undone individually document.main.width = 100 document.main.height = 100
For plugins it makes more sense if all changes are grouped under a single command. To achieve this you can create macros:
# This will create a single undo command called "Resize". # Undoing it will revert both width and height to their respective values. with document.macro("Resize"): document.main.width = 100 document.main.height = 100
Showing a Dialog
Sometimes a plugin might need to show a dialog to the user.
To do so, you can create a UI file using Qt Designer.
You can then load that file and display the dialog through the
# Assume this is the function being invoked by the plugin def plugin_main(window, document, settings): # Load the dialog from myform.ui dialog = window.create_dialog("myform.ui") # Check if the dialog has been loaded correctly if not dialog: return # Sets the `text` property of the widget called `my_label`. # The widget names are the ones you have in the UI file, # for the available properties refer to the Qt documentation dialog.set_value("my_label", "text", "Hello world") # It might be useful to set the values for some of the widget based on the # window or selection dialog.set_value("color_selector", "color", window.current_color) # `exec()` will show the dialog and block until the user accepts it or closes it. # It returns 1 if the dialog was accepted, 0 if it was canceled by the user if dialog.exec(): # `get_value()` is analogous to `set_value()` value = dialog.get_value("color_selector", "color") # ...
This example shows how to have a plugin inspect all objects in the document and change some that match a given condition.
The code is taken from the
import glaxnimate # Subclass the Visitor class, it will automatically go through all # the visual elements of the document class Replacer(glaxnimate.model.Visitor): def __init__(self, color_search, color_replace): # Always call the parent constructor super().__init__() self.color_search = color_search self.color_replace = color_replace # This gets called on every node of the document def on_visit_node(self, node): if ( # Here we want to change colors, so we are only interested in Styler objects # (These are Fill and Stroke) isinstance(node, glaxnimate.model.shapes.Styler) and # Also check that the current color matches the one we are looking for node.color.value == self.color_search ): # Update the color node.color.value = self.color_replace
You can invoke the visitor using the
# With the visitor is always useful to have a macro active, # so whole operation will be seen as a single undoable operation with document.macro("Replace color"): # The second parameter to `visit` is True because we want to skip # locked objects. Replacer(search_color, replace_color).visit(document, True)
Rendering still images
You can render still frames as PIL/Pillow Image objects using
Without any arguments it will return the image with the current frame (ie: what is being displayed in the GUI).
It has two optional arguments: the first selects the time to render (in frames, can also be fractional), the second is the size of the image you want.
# These two are equivalent document.render_image(10) document.render_image(10, document.size()) # Custom size, everything will be scaled to fit document.render_image(10, glaxnimate.utils.IntSize(10, 10))
You can use
add_shape in Groups, Layers, and Compositions to create new shapes.
You'll have to create the shape first and then populate its property.
You specify the type of the shape or element you want to create by its name (without module).
# Create a new group group = document.main.add_shape("Group") # Add a rect at the end rect = group.add_shape("Rect") rect.size.value = glaxnimate.utils.Size(100, 50) rect.position.value = document.size.to_point() / 2 # Create a fill color at index 0 group.add_shape("Fill", 0).color.value = "#0000ff" # Select the created group window.current_item = group
Showing messages to the user
There are several ways of displaying messages, depending on what you need:
window.status Will show a temporary message on the status bar, this is to show progress and such
window.warning Will show a large warning message, this is for user-facing error reporting.
It will also show a warning in the Logs view.
glaxnimate.log Will log messages in the Logs view. Use this for internal reporting.
glaxnimate.log.warning("Message") glaxnimate.log.info("Message") glaxnimate.log.error("Message")