Contribute
This project has grown large enough that external contributors would be fairly welcome. Just get in contact with Demeter before you start coding. You can also open an issue to discuss design and functionality before you start coding.
Adding a new Component/Parameter
The implementation of CloudRig's Component Types are found in the rig_components folder of the repository. Here, you will also find external_components/minimal_component.py, which is a template for you to create your own component types. Simply un-comment the last line of this file and Reload Scripts in Blender, to see it show up as a component type option. Generating it will create a bone and a constraint.
To start making your own component types, just copy this folder, and rename some things:
- The file name should be unique, as it defines the namespace for the parameters in Blender's RNA. So it might be a good idea to prefix all your files with some identifier.
- Change the class's
ui_nameproperty to something unique to show in the UI. Preferably stick to Title Case. - See the template code and comments for further details.
Conventions
- Functions inside rig components should be "non-public", ie. start with
__OR, if they are overridden or called by child classes, use a prefix separated by__that signifies the root class. Eg.,def fk_chain__make_root_bone()signifies that this function was originally defined in the fk_chain component, and is overridden by at least one child class. (Starting with Blender 5.1, we may want to start using Python 3.13's @override with strict mode, though I'm quite bothered by the fact that it doesn't allow specifying a base class.) - Avoid code comments that instruct linters and auto-formatters.
- Use PEP 585 or even more modern type annotations. Avoid older styles like Generics.
- Don't abbreviate too much. Avoid one-letter variable names completely.
- Use
self.add_log()to create entries in the Generation Log interface to warn riggers about any suspiciously mis-configured things. - Functions should be defined top to bottom in roughly the order they run.
- Follow CloudRig's bone naming style
- Bone names should be derived from adding prefixes to metarig bone names, to ensure uniqueness.
- As few prefixes as possible, but as many as needed. For animator-facing controls, I really advise limiting to 1 short prefix.
- Avoid using the same prefix for different purposes; search the codebase before adding new ones.
- Do not hard-code some bone to be called "Torso" or anything else, because then you can't have more than 1 instance of this component in the rig.
- Avoid .001 suffixes by using
increment_name()function for nice clean name increments.
Automated Tests
CloudRig uses PyTest as its regression testing framework of choice. Tests are implemented in the tests folder, which is where you can also find information about how to run them yourself. If you want to contribute, it is vital that you know how to execute automated tests locally, since a PR won't be approved if it's failing tests.
Translations
CloudRig supports localization, which comes with a lot of requirements for how Strings are handled inside the codebase. For example, f-strings are largely forbidden, because they cannot be translated. To alleviate this mental overhead, there is one particularly useful test, which when ran, should give you very clear instructions on what you need to do in order to make all strings inside the codebase translatable. So to make your code translatable, just code as you normally would, run the test, and follow the test's failure messages until your code passes!
Modules
Below are descriptions of each python module in CloudRig.
Repo root
__init__.py
Where CloudRig registers itself into Blender. We use a pattern where each sub-folder's __init__.py should import its contents and put them in a modules list. The listed modules will be traversed recursively, and any registerable classes they contain in a registry list will be registered, and their register() and unregister() functions will be called as appropriate.
manual_mapping.py
Makes sure right clicking on CloudRig properties and then clicking on Open Manual goes to the relevant page on this wiki.
prefs.py
The add-on preferences properties and root UI code. Saving preferences to file is inherited from bs_utils, as is hotkey drawing.
properties.py
Registration and definition of main generation-related PropertyGroups, ie. Object.cloudrig and PoseBone.cloudrig_component.
bs_utils
This is a git sub-module of code shared with some of our other tools; Saving preferences to disk, hotkey registration, some UI utilities, custom property management, etc.
generation
actions_component.py
The Actions generator feature is implemented here. UI is implemented in ui/actions_ui.py.
cloud_generator.py
The Generate Rig operator, and the top level of the generation process.
cloudrig.py
This is the file that gets loaded with all generated rigs and implements the Rig UI. This script is not procedurally generated. Instead, a nested dictionary is written to a custom property during generation, called ui_data. This is mostly created by calls to utils/ui.py/add_ui_data(), and then used by cloudrig.py to draw the sidebar for animators, containing settings like IK/FK switching, parent switching, snapping and baking, and custom properties.
generate_test_animation.py
Implements "Generate Action" feature. Drawn in the Generation tab of a metarig.
naming.py
String utility functions used in creating and mirroring bone names.
troubleshooting.py
- The drawing, storage and functionality of the Generation Log UI seen on metarigs.
- The
CloudLogManagerclass which is instantiated by the generator (self.logger). Components have wrapper functions to auto-fill some parameters, those beingself.add_log()andself.raise_generation_error(). These functions add entries to the log UI. - Implements all "Quick Fix" operators that help riggers deal with minor problems quickly.
- Implements bug reporting and stack tracing functions.
metarigs
__init__.py implements the UI for adding Metarigs and Component Samples via the Object->Add->Armature Menu. Metarigs and Samples are technically the same thing, and both are loaded from MetaRigs.blend.
versioning.py
Metarig versioning.
All metarigs store a version number, and this module adds an app handler that runs on .blend file load, to check for metarigs whose version is lower than the currently installed CloudRig's metarig version. If it finds any, it will automatically do its best to upgrade the metarig's component types and parameters to the latest correct names and values.
For example, the cloud_copy and cloud_tweak bone types used to be a single component type with an enum to switch between the two behaviours. When that split was implemented, the old enum value was still accessible, and was used to assign the new correct component type, so users didn't have to do anything.
Be careful that versioning multiple changes to a single property should be done with care, or not at all, since if the versioning code is trying to write to a property that no longer exists, it will fail.
operators
Operators to help with authoring metarigs and speed up workflow. Each entry here links to the documentation of the functionality it implements.rig_component_features
widgets/widgets.py
Implements loading custom shapes, either from the Widgets.blend file, or a file provided by the user via the preferences, or the currently opened .blend file. Also some other custom shape-related utilities.
widgets/widgets_pre_save.py
Used by Widgets.blend to do automatic housekeeping: Sorting widget geometry topology, which is required for dashed overlay drawing.
bone_gizmos.py
Bone Gizmos is/was an experimental/abandoned add-on of mine, and this module allows components to interface with it. Currently dead code, but might make a return one day.
bone_info.py
Abstraction layer for bones, constraints and drivers, which are used all over CloudRig. These avoid a lot of headaches that come with interacting with real Blender data directly (in exchange for other, smaller headaches!).
Existing bones are loaded into BoneInfo instances in load_metarig_bone_infos(), which are then turned back into real bones in write_edit_data() and write_pose_data().
bone_set.py
CloudRig's bone organization system that takes care of creating sets of parameters to customize the collection and color assignment of bones. All BoneInfo instances created during generation should be created with my_bone_set.new(), to ensure that every bone can be organized by the rigger.
custom_props.py
Implements the shared parameters for to storing and displaying custom properties in the rig UI.
generate_animation.py
Functions used by cloud_fk_chain and the Generate Action feature.
mechanism.py
Houses the CloudMechanismMixin mix-in class which is inherited by all component types and provides generic utilities to manipulate bones, constraints and drivers.
object.py
Houses CloudObjectUtilitiesMixin which is inherited by all component types and provides generic utilities to control actual Blender objects, such as making things visible, assigning things to collections, transform locks, etc.
overlay_painter.py
Manages overlay drawing for component types, useful for getting live feedback on certain properties without having to re-generate the entire rig. Any component type can implement a very simple draw_overlay function, which will receive an instance of OverlayPainter, which abstracts away a lot of boilerplate code so that component types can focus on high level implementation and object-space transformations.
params_ui_utils.py
Implements UI drawing utilities for drawing parameters of Component Types.
parenting.py
UI for the Parent Switching shared parameters. This just means creating certain UI data, drivers and constraints, which cloudrig.py will use for displaying parent switching sliders and operators. Those operators are implemented in cloudrig.py.
properties_ui.py
Implements the UI Editor.
rig_components
All the component types in CloudRig.
All component types inherit from cloud_base.py/Component_Base. Entry points are of course __init__() and create_bone_infos().
external_components
Example code of how you can implement your own components, showing both an ultra-minimal case, and one showing off some of CloudRig's features.
ui
- actions_ui: UI for the Action system.
- cloudrig_main_panel: The "CloudRig" panel and "General" sub-panel in
Properties->Armature->CloudRig. - component_list: The "Component List" sub-panel in
Properties->Armature->CloudRig. - component_param_panels: The parameter sub-panels in
Properties->Bone->CloudRig Component. - menu_3dview: The "CloudRig" header menu in the 3D Viewport while in Armature Pose/Edit mode.
utils
- curve.py: Utility functions used by curve-based components, particularly to help with curve symmetry.
- lattice.py: Some utilities used by the
cloud_latticecomponent, taken from my Lattice Magic add-on. - maths.py: Any pure math, even if it is only used in one place, goes here. That means this module should never import anything from any other part of CloudRig.
- misc.py: Code that hasn't been organized yet. Ideally this module shouldn't exist, since it's not clear what is in it.
- post_gen.py: Code that could be useful to run from post-generation scripts. Not actually used anywhere in CloudRig's code.
- rig.py: Armature related maths.