Getting Property groups as dictionaries
I recently reworked Mirage’s live mode to be more efficient. One of the things I wanted to improve was detecting changes in terrain settings. I figured the best way to do it was getting a dictionary of the settings and finding what changed in it.
So I wrote a little function to get all the properties inside a PropertyGroup
as a dictionary. I figure this could be useful for everyone, so here it is.
# Don't forget:
from typing import Dict
from bpy.types import PropertyGroup
def group_as_dict(group: PropertyGroup) -> Dict:
"""Get values from a property group as a dict."""
EXCLUDE = {'a_prop_I_dont_want', 'another'}
prop_dict = {}
for key in group.__annotations__.keys():
# Avoid properties we don't want
if key in EXCLUDE:
continue
# Each item in __annotations__ is a tuple
# containing the type and a dictionary
prop_type = group.__annotations__[key][0]
# Pointers to other property groups
if prop_type == PointerProperty:
prop_dict[key] = group_as_dict(getattr(settings, key))
# Store collection properties as lists
elif prop_type == CollectionProperty:
prop_dict[key] = [group_as_dict(i)
for i in getattr(settings, key)]
# BUG? IntVectorProperties don't return the Vector value on
# getattr(). Looks like we have to get it ourselves for now.
elif prop_type == IntVectorProperty:
prop_dict[key] = [i for i in getattr(settings, key)]
# Get everything else as a value
else:
prop_dict[key] = getattr(settings, key)
return prop_dict
This function is recursive. It will take nested PropertyGroups
as well as CollectionProperties
, which are returned as lists. I also added a fix for IntVectorProperties
, where getattr()
returns the pointer instead of the actual values. You could also copy that line and extend it to the other vector properties. Depending on what you would like to do with this dict, you might want a tuple or list of values instead of a Vector
object.
You can also exclude properties by adding their names to the exclude set. This is great for “UI” properties that you don’t want to store, like using enums
for tabs.
Did you find it useful? Let me know in the comments!