Post

GSoC 2025 - Week 6

I made the following progress this week:

  • PR #891 (merged)
    • Updated the underlying datastore for annotations to use Blender properties instead of Geometry Nodes
    • Added tests to handle exceptions as well - based on Codecov report
  • PR #900 (merged)
    • Added custom validation support for Annotation classes
  • PR #901 (merged)
    • Added the base annotations draw handler code
    • Basic 3D and 2D text drawing with working atom info annotation for Trajectories
  • PR #903 (open)
    • Added basic line drawing support for annotations
    • Working center-of-mass and distance between center-of-masses annotation for Trajectories

Here is a video that shows the annotations progress so far:

Here are some learning from this week:

  • Dynamic properties are a great way to support extensibility in Blender
  • A CollectionProperty with a dynamic PropertyGroup can be assigned to standard types (like bpy.types.Object) at runtime. This is the key that allows extensibility. Blender converts these to ID properties when the corresponding type classes are not registered. Once the type classes are registered they become API defined properties
    • The property path has to be at the top level and not nested under another property. For example, bpy.types.Object.mn_annotations works, but bpy.types.Object.mn.annotations doesn’t. The later leads to a AttributeError: '_PropertyDeferred' object has no attribute '...' error
  • .bl_rna.properties of a PropertyGroup can be used to iterate all the properties within a PropertyGroup. The property name is available under the identifier attribute of the iterated item. The type attribute specifies the property type (like POINTER etc)
  • Changing Blender properties through API will need the viewport to be tagged for redraw to show updated values immediately in Blender’s GUI
  • with pytest.raises can be used to test exceptions in pytest tests
  • A lambda function can be used to pass the actual property name within a property group that caused the update in the update callback
  • Care should be taken when using lambda functions in a loop - a closure is needed to ensure that correct values are passed - this can be done using defaults, a custom function etc
  • bpy.types.Operator.__subclasses__() and bpy.types.PropertyGroup.__subclasses__() can be used to verify whether temporary operators and property groups are being unregistered and garbage collected. sys.getrefcount can be used on a class to get the reference counts

Next week, I plan to continue working on annotations - more shapes, other trajectory annotations and rendering support for annotations.

This post is licensed under CC BY 4.0 by the author.