GSoC 2025 - Week 5
This week, I continued with the Annotations discussion in #889 and created PR #891 with the base framework needed for Annotations support.
This base framework allows user defined custom annotations. Even the default entity annotations part of MN will use the same framework. With this, any new annotation type will get the API interface and GUI support for free, which makes this very extensible. Blender’s Geometry Nodes are used as the underlying data store. They provide a lot more flexibility compared to regular Blender properties, especially when things are dynamic in nature.
Here is a video that shows this framework in action:
Here are some additional learnings this week:
- Derived classes that don’t implement the abstract methods defined in the base class (using
@abstractmethod
) will still pass thehasattr
check for that method. The abstract method cannot be executed error only shows up when the class is instantiated. To check if the derived class has the implementation of the method, the__qualname__
attribute of the method can be used to check which class provides the implementation - The
mro()
method (or the__mro__
attribute) can be used to get the ‘Method Resolution Order’ of a class’s methods or attributes. This is needed if we need to get all the python annotations of a class which includes ones defined in base classes as well __getattr___
is only called when the normal mechanisms to locate the attribute fail.__getattribute__
is called all the the time and could have performance implications- The
inspect
module provides complete control to define parameters (usinginspect.Parameter
), their ordering etc to create a dynamic method signature (usinginspect.Signature
) - Dynamic classes can be created using the
type()
function by passing the name, any base classes and attribute / methods dictionary - we use this to return the dynamic annotation interface. MN also uses this mechanism to return the style interface property()
is a way to define managed attributes at a class level. Properties defined usingproperty()
cannot be assigned directly to instances. They can only be assigned to classes and will apply to all current and future instances. They work well with dynamic classes. The alternative to this would be to use__getattr__
and__setattr__
to handle all dynamic propety management- Panel placeholders in a Blender’s Geometry Node provide a way to add inputs so that when inputs are iterated, they are iterated in a required order. Dynamically adding a new socket at a specific position isn’t straightforward
- Blender does not allow dynamic properties in an operator. To achieve dynamic properties in an operator (to show in the
invoke
UI for example), a temporary operator has to be created, registered with Blender and invoked. A dynamicPropertyGroup
with dynamic properties can be created using the sametype()
method learnt above. This dynamic type can be used within aPointerProperty
of the temporary operator for dynamic inputs - Similar to
EXEC_DEFAULT
learnt in the past for operators,EXEC_INVOKE
can be used to directly call the operator and run it’sinvoke
method - Blender allows panels in the UI layout drawn by users (using
layout.panel(...)
). This allows better organization in what we display
Next week, I plan to work on the actual drawing of annotations using the gpu
and blf
Blender modules and create generic methods that can be used by all annotations.