Examples

Undo Macros

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 window object:

# 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")

        # ...

Document Visitor

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 ReplaceColor plugin.

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 visit function:

    # 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 Document.render_image.

Without any arguments it will return the image with the current frame (ie: what is being displayed in the GUI).

document.render_image()

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))

Creating shapes

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.status("Message")

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.

window.warning("Message")

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")