diff options
author | Martin Poirier <theeth@yahoo.com> | 2010-08-02 06:55:12 +0400 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2010-08-02 06:55:12 +0400 |
commit | 5b345524ea4aed30aa2fc9ef735ccae82bdffeae (patch) | |
tree | 8d8e9ffbe5a0254ea78c4f4e56ba27f3f1b2db1c /release/scripts/modules | |
parent | 9f575e5446924770d8a0d118a14100dcd7366ead (diff) |
RNA Types metaclass registration
See mailing list posts for details [1][2][3]
Addons still need to be fixed; Campbell said he'd do it today.
See any of the py files (outside netrender) in this commit for how to do it (it's rather simple).
[1] http://lists.blender.org/pipermail/bf-committers/2010-February/026328.html
[2] http://lists.blender.org/pipermail/bf-committers/2010-August/028311.html
[3] http://lists.blender.org/pipermail/bf-committers/2010-August/028321.html
Diffstat (limited to 'release/scripts/modules')
-rw-r--r-- | release/scripts/modules/bpy/utils.py | 22 | ||||
-rw-r--r-- | release/scripts/modules/bpy_types.py | 71 | ||||
-rw-r--r-- | release/scripts/modules/rna_prop_ui.py | 129 |
3 files changed, 81 insertions, 141 deletions
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 06dbe8fd4cc..f09c5872ab1 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -29,6 +29,7 @@ import sys as _sys from _bpy import blend_paths from _bpy import script_paths as _bpy_script_paths +from _bpy import LoadModule, UnloadModule def _test_import(module_name, loaded_modules): @@ -84,7 +85,7 @@ def modules_from_path(path, loaded_modules): modules.append(mod) return modules - + _loaded = [] # store loaded modules for reloading. _bpy_types = __import__("bpy_types") # keep for comparisons, never ever reload this. @@ -108,6 +109,15 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): if refresh_scripts: original_modules = _sys.modules.values() + def unload_module(mod): + UnloadModule(mod.__name__) + unregister = getattr(mod, "unregister", None) + if unregister: + try: + unregister() + except: + traceback.print_exc() + def sys_path_ensure(path): if path not in _sys.path: # reloading would add twice _sys.path.insert(0, path) @@ -134,6 +144,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): mod = test_reload(mod) if mod: + LoadModule(mod.__name__, reload_scripts) register = getattr(mod, "register", None) if register: try: @@ -165,12 +176,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): # loop over and unload all scripts _loaded.reverse() for mod in _loaded: - unregister = getattr(mod, "unregister", None) - if unregister: - try: - unregister() - except: - traceback.print_exc() + unload_module(mod) for mod in _loaded: reload(mod) @@ -336,7 +342,7 @@ _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths def preset_paths(subdir): ''' - Returns a list of paths for a spesific preset. + Returns a list of paths for a specific preset. ''' return (_os.path.join(_presets, subdir), ) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 8cbb2bf4e80..7e7b7f128ab 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -19,6 +19,7 @@ # <pep8 compliant> from _bpy import types as bpy_types +import _bpy from mathutils import Vector StructRNA = bpy_types.Struct.__bases__[0] @@ -539,8 +540,64 @@ class Text(bpy_types.ID): import collections +TypeMap = {} +# Properties (IDPropertyGroup) are different from types because they need to be registered +# before adding sub properties to them, so they are registered on definition +# and unregistered on unload +PropertiesMap = {} + +def UnloadModule(module): + global TypeMap, PropertiesMap + for t in TypeMap.get(module, []): + bpy_types.unregister(t) + + TypeMap = {} + + for t in PropertiesMap.get(module, []): + bpy_types.unregister(t) + + PropertiesMap = {} + +def LoadModule(module, force=False): + for t in TypeMap.get(module, []): + bpy_types.register(t) + +_bpy.LoadModule = LoadModule +_bpy.UnloadModule = UnloadModule + +class RNAMeta(type): + @classmethod + def _immediate(cls): + return bpy_types.immediate(); + + def __new__(cls, name, bases, classdict, **args): + result = type.__new__(cls, name, bases, classdict) + if bases and bases[0] != StructRNA: + module = result.__module__ + + ClassMap = TypeMap + + # Register right away if needed + if cls._immediate(): + bpy_types.register(result) + ClassMap = PropertiesMap + + # first part of packages only + if "." in module: + module = module[:module.index(".")] + + if not module in ClassMap: + ClassMap[module] = [] + + ClassMap[module].append(result) + return result + +class RNAMetaRegister(RNAMeta): + @classmethod + def _immediate(cls): + return True; -class OrderedMeta(type): +class OrderedMeta(RNAMeta): def __init__(cls, name, bases, attributes): super(OrderedMeta, cls).__init__(name, bases, attributes) @@ -549,7 +606,6 @@ class OrderedMeta(type): def __prepare__(name, bases, **kwargs): return collections.OrderedDict() - # Only defined so operators members can be used by accessing self.order class Operator(StructRNA, metaclass=OrderedMeta): __slots__ = () @@ -564,7 +620,12 @@ class Macro(StructRNA, metaclass=OrderedMeta): def define(self, opname): from _bpy import ops return ops.macro_define(self, opname) + +class IDPropertyGroup(StructRNA, metaclass=RNAMetaRegister): + __slots__ = () +class RenderEngine(StructRNA, metaclass=RNAMeta): + __slots__ = () class _GenericUI: __slots__ = () @@ -606,15 +667,15 @@ class _GenericUI: pass -class Panel(StructRNA, _GenericUI): +class Panel(StructRNA, _GenericUI, metaclass=RNAMeta): __slots__ = () -class Header(StructRNA, _GenericUI): +class Header(StructRNA, _GenericUI, metaclass=RNAMeta): __slots__ = () -class Menu(StructRNA, _GenericUI): +class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): __slots__ = () def path_menu(self, searchpaths, operator, props_default={}): diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index 3e8662c275f..eda27240fb5 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -124,7 +124,7 @@ def draw(layout, context, context_member, use_edit=True): assign_props(prop, val_draw, key) -class PropertyPanel(bpy.types.Panel): +class PropertyPanel(): """ The subclass should have its own poll function and the variable '_context_path' MUST be set. @@ -135,130 +135,3 @@ class PropertyPanel(bpy.types.Panel): def draw(self, context): draw(self.layout, context, self._context_path) - -from bpy.props import * - - -rna_path = StringProperty(name="Property Edit", - description="Property data_path edit", maxlen=1024, default="", options={'HIDDEN'}) - -rna_value = StringProperty(name="Property Value", - description="Property value edit", maxlen=1024, default="") - -rna_property = StringProperty(name="Property Name", - description="Property name edit", maxlen=1024, default="") - -rna_min = FloatProperty(name="Min", default=0.0, precision=3) -rna_max = FloatProperty(name="Max", default=1.0, precision=3) - - -class WM_OT_properties_edit(bpy.types.Operator): - '''Internal use (edit a property data_path)''' - bl_idname = "wm.properties_edit" - bl_label = "Edit Property" - - data_path = rna_path - property = rna_property - value = rna_value - min = rna_min - max = rna_max - description = StringProperty(name="Tip", default="") - - def execute(self, context): - data_path = self.properties.data_path - value = self.properties.value - prop = self.properties.property - prop_old = self._last_prop[0] - - try: - value_eval = eval(value) - except: - value_eval = value - - # First remove - item = eval("context.%s" % data_path) - - rna_idprop_ui_prop_clear(item, prop_old) - exec_str = "del item['%s']" % prop_old - # print(exec_str) - exec(exec_str) - - - # Reassign - exec_str = "item['%s'] = %s" % (prop, repr(value_eval)) - # print(exec_str) - exec(exec_str) - self._last_prop[:] = [prop] - - prop_type = type(item[prop]) - - prop_ui = rna_idprop_ui_prop_get(item, prop) - - if prop_type in (float, int): - - prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.properties.min) - prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.properties.max) - - prop_ui['description'] = self.properties.description - - return {'FINISHED'} - - def invoke(self, context, event): - - self._last_prop = [self.properties.property] - - item = eval("context.%s" % self.properties.data_path) - - # setup defaults - prop_ui = rna_idprop_ui_prop_get(item, self.properties.property, False) # dont create - if prop_ui: - self.properties.min = prop_ui.get("min", -1000000000) - self.properties.max = prop_ui.get("max", 1000000000) - self.properties.description = prop_ui.get("description", "") - - wm = context.manager - # This crashes, TODO - fix - #return wm.invoke_props_popup(self, event) - - wm.invoke_props_popup(self, event) - return {'RUNNING_MODAL'} - - -class WM_OT_properties_add(bpy.types.Operator): - '''Internal use (edit a property data_path)''' - bl_idname = "wm.properties_add" - bl_label = "Add Property" - - data_path = rna_path - - def execute(self, context): - item = eval("context.%s" % self.properties.data_path) - - def unique_name(names): - prop = 'prop' - prop_new = prop - i = 1 - while prop_new in names: - prop_new = prop + str(i) - i += 1 - - return prop_new - - property = unique_name(item.keys()) - - item[property] = 1.0 - return {'FINISHED'} - - -class WM_OT_properties_remove(bpy.types.Operator): - '''Internal use (edit a property data_path)''' - bl_idname = "wm.properties_remove" - bl_label = "Remove Property" - - data_path = rna_path - property = rna_property - - def execute(self, context): - item = eval("context.%s" % self.properties.data_path) - del item[self.properties.property] - return {'FINISHED'} |