"""Compatibility functions to support Blender 2.79 and 2.80+ in one code base.""" import functools import bpy if bpy.app.version < (2, 80): SYNC_SELECT_VERSION_ICON = "DOTSDOWN" else: SYNC_SELECT_VERSION_ICON = "DOWNARROW_HLT" # Get references to all property definition functions in bpy.props, # so that they can be used to replace 'x = IntProperty()' to 'x: IntProperty()' # dynamically when working on Blender 2.80+ __all_prop_funcs = { getattr(bpy.props, propname) for propname in dir(bpy.props) if propname.endswith("Property") } def convert_properties(class_): """Class decorator to avoid warnings in Blender 2.80+ This decorator replaces property definitions like this: someprop = bpy.props.IntProperty() to annotations, as introduced in Blender 2.80: someprop: bpy.props.IntProperty() No-op if running on Blender 2.79 or older. """ if bpy.app.version < (2, 80): return class_ if not hasattr(class_, "__annotations__"): class_.__annotations__ = {} attrs_to_delete = [] for name, value in class_.__dict__.items(): if not isinstance(value, tuple) or len(value) != 2: continue prop_func, kwargs = value if prop_func not in __all_prop_funcs: continue # This is a property definition, replace it with annotation. attrs_to_delete.append(name) class_.__annotations__[name] = value for attr_name in attrs_to_delete: delattr(class_, attr_name) return class_ @functools.lru_cache() def factor(factor: float) -> dict: """Construct keyword argument for UILayout.split(). On Blender 2.8 this returns {'factor': factor}, and on earlier Blenders it returns {'percentage': factor}. """ if bpy.app.version < (2, 80, 0): return {"percentage": factor} return {"factor": factor}