.. _animations: Animating ddg Objects ======================= This guide explains how to animate ddg objects (and their visualizations in Blender) by introducing parameters that can be accessed and changed via Blender's GUI. Animations can easily be created by :ref:`adding keyframes ` to the parameters. .. contents:: Table of contents :local: :backlinks: none .. warning:: Modifying objects with Blender properties is still work in progress. If you find unexpected behaviour, try restarting Blender and/or write a mail to our :ref:`support`. Adding Parameters with a Callback Function ------------------------------------------ The most central tool for creating animations is the function :py:func:`~ddg.visualization.blender.props.add_props_with_callback`. You pass the labels and initial values of the parameters as well as a **callback function** in the function call. The callback function will be executed each time one of the parameters changes its value. The parameters, called *Blender properties*, can now be accessed via Blender's GUI. Here is a basic example: .. literalinclude:: ../../../../../examples/blender/docs/props_basic.py :language: python .. note:: The **labels** "a", "b", "c" and "s" of the parameters can be chosen freely. The callback function will be called with the parameters as arguments in given order. The type of the **initial parameters** determines the type of the parameters, e.g. "0" will result in `int`, "0.0" in `float`. The example creates the properties `a`, `b`, `c` and `s`. In Blender's 3D Viewport you can click on the little arrow to the right side of the coordinate system to open the sidebar. Alternatively you can also press 'n'. In addition to the `Item`, `Tool` and `View` tabs, you now also find a `DDG` tab that stores the Blender properties. .. image:: animations01.png If we adjust any of them, the callback function `print_props` will be executed, and will print the properties values to the console. .. image:: animations02.png .. note:: The properties need to reside on some object inside of Blender. We store them on the **scene**, which can be obtained with ``bpy.context.scene``. This is important to know if you want to access these properties via the API (e.g. ``bpy.context.scene.a``) for example when animating them. Parameter dependent ddg Objects ------------------------------- For more interesting examples involving geometric objects, we can replace `print_props` by a function that creates Blender objects. .. note:: This is the most rudimentary way and does not involve any caching. There are more sophisticated ways of creating callback functions, using a caching mechanism, explained in the next section. This section will help to understand whats going on, especially if you are just starting to work with animations. The following function creates and visualizes a quadric depending on parameters. .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [no caching 0] :end-before: [no caching 0] .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [no caching 1] :end-before: [no caching 1] We add the visualization function as a callback for the Blender properties `a`, `b`, `c` and `s`. Changing the parameters then will change the form and the type of the visualized quadric. .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [no caching 2] :end-before: [no caching 2] .. image:: animations03.png .. warning:: Be aware, that when executing the script, i.e. by pressing 'Alt + P', no output is expected. Only when changing a parameter the `visualize_quadric` function is called and executed. .. warning:: If there is no activity, even when changing the parameters, check the console you have started Blender with. Error messages will appear there without being shown in Blender. Caching Manipulated Objects --------------------------- There are two utility functions for caching manipulated objects, :py:func:`~ddg.visualization.blender.props.hide_callback` and :py:func:`~ddg.visualization.blender.props.overwrite_callback`. For both caching mechanisms we need to adapt the visualization function to return a *sequence of unlinked Blender objects*. This means that we need to pass the keyword `link=False` to :py:func:`~ddg.conversion.blender.core.to_blender_object` for each object. .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [caching] :end-before: [caching] The :py:func:`~ddg.visualization.blender.props.hide_callback` and the :py:func:`~ddg.visualization.blender.props.overwrite_callback` function expect a name of a collection and a function returning the unlinked Blender objects. Their specific usage is explained below. .. warning:: The functions :py:func:`~ddg.visualization.blender.props.hide_callback` and :py:func:`~ddg.visualization.blender.props.overwrite_callback` use custom Blender collections to store the objects. It is not compatible with user defined collections. In other words, you can not pass a `collection` argument to :py:func:`~ddg.conversion.blender.core.to_blender_object`. Hide Callback ~~~~~~~~~~~~~ The function :py:func:`~ddg.visualization.blender.props.hide_callback` creates a Blender collection with passed name. For each distinct set of parameters a child collection is appended (on demand). If a parameter is changed, the previous collection, and therefore its objects, are hidden. Then either a new child collection is created (for a new set of parameters) or a previously created child collection is un-hidden (if the set of parameters has been used before). .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [hide_callback] :end-before: [hide_callback] .. image:: animations_hide.png .. warning:: For smaller scripts using the same values of parameters (e.g. animations) hiding and un-hiding is a very fast and cheap option. For large scripts this method results in lots of objects which might be difficult to be handled by Blender. Blender might have difficulties handling many objects when rendering. Overwrite Callback ~~~~~~~~~~~~~~~~~~ If all objects to visualize will have mesh data (i.e. no curves, lights and cameras, no 1D nets for example coming from lines, conics, etc), it is also possible to overwrite the object's data in-place. This can be done using the :py:func:`~ddg.visualization.blender.props.overwrite_callback`, which also caches results. .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [overwrite_callback] :end-before: [overwrite_callback] .. image:: animations_overwrite.png Clear Callback ~~~~~~~~~~~~~~ There also exists a function :py:func:`~ddg.visualization.blender.props.clear_callback` that does not cache any data. It can be used in a similar way as the functions above. .. _advanced props: Finer Control over Properties ----------------------------- If you want to set the description, minimum or maximum value of a property and more, you'll have to define the properties yourself: .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [add props from constructors] :end-before: [add props from constructors] Consult the `Blender documentation `_ for all the options. The callback code remains the same. Saving and Reloading .blend Files --------------------------------- Since closing Blender loses all Python state, the callback will no longer exist after saving and reloading a .blend file. To fix this, run the script again. Afterwards the callback will work as expected. Creating an Animation --------------------- Like any Blender properties, DDG properties can be keyframed and interpolated. In particular, the library's tools for keyframes can be applied, with the slight catch that we store the interactive properties on Blender's **scene**, as mentioned above. To animate the parameter ``a`` we already added in the example above, we could do: .. literalinclude:: ../../../../../examples/blender/docs/props.py :language: python :start-after: [animating with callback] :end-before: [animating with callback] For a more detailed guide on setting and editing keyframes, see :ref:`keyframes`. When playing animations multiple times in Blender, the functions :py:func:`~ddg.visualization.blender.props.hide_callback` or :py:func:`~ddg.visualization.blender.props.overwrite_callback` are recommended to cache the results. When creating (and rendering) an animation from script, i.e. only playing it once, the functions :py:func:`~ddg.visualization.blender.props.clear_callback` or :py:func:`~ddg.visualization.blender.props.overwrite_callback` are recommended. To find out more about rendering animations check out our :ref:`blender_rendering` guide.