[Bf-blender-cvs] [d9bc297c23] app-templates: Add filtering for UI elements

Campbell Barton noreply at git.blender.org
Tue Mar 21 03:26:43 CET 2017


Commit: d9bc297c23d5841c7c05926352cf00ea1fc20817
Author: Campbell Barton
Date:   Tue Mar 21 13:22:53 2017 +1100
Branches: app-templates
https://developer.blender.org/rBd9bc297c23d5841c7c05926352cf00ea1fc20817

Add filtering for UI elements

There is a remaining preset drawing issue that needs resolving.

===================================================================

M	release/datafiles/app_templates/101/template/__init__.py
M	release/scripts/modules/bl_app_override.py

===================================================================

diff --git a/release/datafiles/app_templates/101/template/__init__.py b/release/datafiles/app_templates/101/template/__init__.py
index 7c1a0f5365..5cdde52263 100644
--- a/release/datafiles/app_templates/101/template/__init__.py
+++ b/release/datafiles/app_templates/101/template/__init__.py
@@ -25,8 +25,12 @@ import bl_app_override
 class AppStateStore:
     # Utility class to encapsulate application state, backup and restore.
     __slots__ = (
+        # setup_classes
         "class_store",
+        # setup_addons
         "sys_path",
+        # setup_ui_filter
+        "ui_filter_store"
     )
 
     _template_addons = (
@@ -36,6 +40,7 @@ class AppStateStore:
     def __init__(self):
         self.class_store = []
         self.sys_path = []
+        self.ui_filter_store = []
 
     def setup_classes(self):
         assert(len(self.class_store) == 0)
@@ -69,6 +74,41 @@ class AppStateStore:
             register(cls)
         self.class_store.clear()
 
+    def setup_ui_filter(self):
+        import bl_app_override
+        self.ui_filter_store = bl_app_override.ui_draw_filter_register(
+            operator_blacklist={
+                # "render.render",
+                "transform.mirror",
+                "sound.mixdown",
+                "object.modifier_add",
+                "object.forcefield_toggle",
+            },
+            property_blacklist={
+                ("Object", "location"),
+                ("Object", "scale"),
+                ("Object", "rotation_euler"),
+                ("RenderSettings", "use_placeholder"),
+                ("RenderSettings", "use_render_cache"),
+                ("RenderSettings", "pixel_filter_type"),
+                ("RenderSettings", "filter_size"),
+                ("RenderSettings", "frame_map_old"),
+                ("RenderSettings", "frame_map_new"),
+                ("RenderSettings", "use_border"),
+                ("RenderSettings", "use_crop_to_border"),
+                ("RenderSettings", "pixel_aspect_x"),
+                ("RenderSettings", "pixel_aspect_y"),
+            },
+        )
+
+    def teardown_ui_filter(self):
+        import bl_app_override
+        bl_app_override.ui_draw_filter_unregister(
+            self.ui_filter_store
+        )
+        self.ui_filter_store = None
+
+
     def setup_addons(self):
         import sys
         import os
@@ -102,8 +142,9 @@ from . import ui
 
 def register():
     print("Template Register", __file__)
-    app_state.setup_classes()
+    # app_state.setup_classes()
     app_state.setup_addons()
+    app_state.setup_ui_filter()
 
     ui.register()
 
@@ -112,5 +153,6 @@ def unregister():
 
     ui.unregister()
 
-    app_state.teardown_classes()
+    # app_state.teardown_classes()
     app_state.teardown_addons()
+    app_state.teardown_ui_filter()
diff --git a/release/scripts/modules/bl_app_override.py b/release/scripts/modules/bl_app_override.py
index b9c83fefcc..5ea6045e83 100644
--- a/release/scripts/modules/bl_app_override.py
+++ b/release/scripts/modules/bl_app_override.py
@@ -40,3 +40,124 @@ def class_filter(cls_parent, **kw):
             if ((white_list is not None and cls.__name__ is white_list) or
                     all((getattr(cls, attr) in expect) for attr, expect in kw_items)):
                 yield cls
+
+
+def ui_draw_filter_register(
+    *,
+    classes=None,
+    property_blacklist=None,
+    operator_blacklist=None,
+):
+    import bpy
+
+    UILayout = bpy.types.UILayout
+
+    if classes is None:
+        classes = (
+            bpy.types.Panel,
+            bpy.types.Menu,
+            bpy.types.Header,
+        )
+
+    def filter_operator(op_id):
+        return op_id not in operator_blacklist
+
+    def filter_prop(data, prop):
+        return (data.__class__.__name__, prop) not in property_blacklist
+
+    class OperatorProperties_Fake:
+        pass
+
+    class UILayout_Fake(bpy.types.UILayout):
+        __slots__ = ()
+
+        def __getattribute__(self, attr):
+            # ensure we always pass down UILayout_Fake instances
+            if attr in {"row", "split", "column", "box", "column_flow"}:
+                real_func = UILayout.__getattribute__(self, attr)
+
+                def dummy_func(*args, **kw):
+                    # print("wrapped", attr)
+                    ret = real_func(*args, **kw)
+                    return UILayout_Fake(ret)
+                return dummy_func
+
+            elif attr in {"operator", "operator_menu_enum", "operator_enum"}:
+                real_func = UILayout.__getattribute__(self, attr)
+
+                def dummy_func(*args, **kw):
+                    # print("wrapped", attr)
+                    if filter_operator(args[0]):
+                        ret = real_func(*args, **kw)
+                    else:
+                        # UILayout.__getattribute__(self, "label")()
+                        # may need to be set
+                        ret = OperatorProperties_Fake()
+                    return ret
+                return dummy_func
+            elif attr in {"prop", "prop_enum"}:
+                real_func = UILayout.__getattribute__(self, attr)
+
+                def dummy_func(*args, **kw):
+                    # print("wrapped", attr)
+                    if filter_prop(args[0], args[1]):
+                        ret = real_func(*args, **kw)
+                    else:
+                        ret = None
+                    return ret
+                return dummy_func
+            else:
+                return UILayout.__getattribute__(self, attr)
+            # print(self, attr)
+
+        def operator(*args, **kw):
+            return super().operator(*args, **kw)
+
+    def draw_override(func_orig, self_real, context):
+        # simple, no wrapping
+        # return func_orig(self_wrap, context)
+
+        class Wrapper(self_real.__class__):
+            __slots__ = ()
+            def __getattribute__(self, attr):
+                if attr == "layout":
+                    return UILayout_Fake(self_real.layout)
+                else:
+                    cls = super()
+                    try:
+                        return cls.__getattr__(self, attr)
+                    except AttributeError:
+                        # class variable
+                        return getattr(cls, attr)
+
+            @property
+            def layout(self):
+                # print("wrapped")
+                return self_real.layout
+
+        return func_orig(Wrapper(self_real), context)
+
+    ui_filter_store = []
+
+    for cls in classes:
+        for subcls in list(cls.__subclasses__()):
+            if "draw" in subcls.__dict__:  # don't want to get parents draw()
+
+                def replace_draw():
+                    # function also serves to hold draw_old in a local name-space
+                    draw_orig = subcls.draw
+
+                    def draw(self, context):
+                        return draw_override(draw_orig, self, context)
+                    subcls.draw = draw
+
+                ui_filter_store.append((subcls, "draw", subcls.draw))
+
+                replace_draw()
+
+    return ui_filter_store
+
+
+def ui_draw_filter_unregister(ui_filter_store):
+    for (obj, attr, value) in ui_filter_store:
+        setattr(obj, attr, value)




More information about the Bf-blender-cvs mailing list