This commit implements described in the #104573. The goal is to fix the confusion of the submodule hashes change, which are not ideal for any of the supported git-module configuration (they are either always visible causing confusion, or silently staged and committed, also causing confusion). This commit replaces submodules with a checkout of addons and addons_contrib, covered by the .gitignore, and locale and developer tools are moved to the main repository. This also changes the paths: - /release/scripts are moved to the /scripts - /source/tools are moved to the /tools - /release/datafiles/locale is moved to /locale This is done to avoid conflicts when using bisect, and also allow buildbot to automatically "recover" wgen building older or newer branches/patches. Running `make update` will initialize the local checkout to the changed repository configuration. Another aspect of the change is that the make update will support Github style of remote organization (origin remote pointing to thy fork, upstream remote pointing to the upstream blender/blender.git). Pull Request #104755
204 lines
7.0 KiB
Python
204 lines
7.0 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
"""
|
|
Module to manage overriding various parts of Blender.
|
|
|
|
Intended for use with 'app_templates', though it can be used from anywhere.
|
|
"""
|
|
|
|
|
|
# TODO, how to check these aren't from add-ons.
|
|
# templates might need to un-register while filtering.
|
|
def class_filter(cls_parent, **kw):
|
|
whitelist = kw.pop("whitelist", None)
|
|
blacklist = kw.pop("blacklist", None)
|
|
kw_items = tuple(kw.items())
|
|
for cls in cls_parent.__subclasses__():
|
|
# same as is_registered()
|
|
if "bl_rna" in cls.__dict__:
|
|
if blacklist is not None and cls.__name__ in blacklist:
|
|
continue
|
|
if ((whitelist is not None and cls.__name__ is whitelist) or
|
|
all((getattr(cls, attr) in expect) for attr, expect in kw_items)):
|
|
yield cls
|
|
|
|
|
|
def ui_draw_filter_register(
|
|
*,
|
|
ui_ignore_classes=None,
|
|
ui_ignore_operator=None,
|
|
ui_ignore_property=None,
|
|
ui_ignore_menu=None,
|
|
ui_ignore_label=None
|
|
):
|
|
import bpy
|
|
|
|
UILayout = bpy.types.UILayout
|
|
|
|
if ui_ignore_classes is None:
|
|
ui_ignore_classes = (
|
|
bpy.types.Panel,
|
|
bpy.types.Menu,
|
|
bpy.types.Header,
|
|
)
|
|
|
|
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", "operator_menu_hold"}:
|
|
if ui_ignore_operator is None:
|
|
return UILayout.__getattribute__(self, attr)
|
|
|
|
real_func = UILayout.__getattribute__(self, attr)
|
|
|
|
def dummy_func(*args, **kw):
|
|
# print("wrapped", attr)
|
|
ui_test = ui_ignore_operator(args[0])
|
|
if ui_test is False:
|
|
ret = real_func(*args, **kw)
|
|
else:
|
|
if ui_test is None:
|
|
UILayout.__getattribute__(self, "label")(text="")
|
|
else:
|
|
assert ui_test is True
|
|
# may need to be set
|
|
ret = OperatorProperties_Fake()
|
|
return ret
|
|
return dummy_func
|
|
|
|
elif attr in {"prop", "prop_enum"}:
|
|
if ui_ignore_property is None:
|
|
return UILayout.__getattribute__(self, attr)
|
|
|
|
real_func = UILayout.__getattribute__(self, attr)
|
|
|
|
def dummy_func(*args, **kw):
|
|
# print("wrapped", attr)
|
|
ui_test = ui_ignore_property(args[0].__class__.__name__, args[1])
|
|
if ui_test is False:
|
|
ret = real_func(*args, **kw)
|
|
else:
|
|
if ui_test is None:
|
|
UILayout.__getattribute__(self, "label")(text="")
|
|
else:
|
|
assert ui_test is True
|
|
ret = None
|
|
return ret
|
|
return dummy_func
|
|
|
|
elif attr == "menu":
|
|
if ui_ignore_menu is None:
|
|
return UILayout.__getattribute__(self, attr)
|
|
|
|
real_func = UILayout.__getattribute__(self, attr)
|
|
|
|
def dummy_func(*args, **kw):
|
|
# print("wrapped", attr)
|
|
ui_test = ui_ignore_menu(args[0])
|
|
if ui_test is False:
|
|
ret = real_func(*args, **kw)
|
|
else:
|
|
if ui_test is None:
|
|
UILayout.__getattribute__(self, "label")(text="")
|
|
else:
|
|
assert ui_test is True
|
|
ret = None
|
|
return ret
|
|
return dummy_func
|
|
|
|
elif attr == "label":
|
|
if ui_ignore_label is None:
|
|
return UILayout.__getattribute__(self, attr)
|
|
|
|
real_func = UILayout.__getattribute__(self, attr)
|
|
|
|
def dummy_func(*args, **kw):
|
|
# print("wrapped", attr)
|
|
ui_test = ui_ignore_label(args[0] if args else kw.get("text", ""))
|
|
if ui_test is False:
|
|
ret = real_func(*args, **kw)
|
|
else:
|
|
if ui_test is None:
|
|
real_func(text="")
|
|
else:
|
|
assert ui_test is True
|
|
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):
|
|
cls_real = self_real.__class__
|
|
if cls_real is super:
|
|
# simple, no wrapping
|
|
return func_orig(self_real, context)
|
|
|
|
class Wrapper(cls_real):
|
|
__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
|
|
try:
|
|
return getattr(cls, attr)
|
|
except AttributeError:
|
|
# for preset bl_idname access
|
|
return getattr(UILayout(self), attr)
|
|
|
|
@property
|
|
def layout(self):
|
|
# print("wrapped")
|
|
return self_real.layout
|
|
|
|
return func_orig(Wrapper(self_real), context)
|
|
|
|
ui_ignore_store = []
|
|
|
|
for cls in ui_ignore_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_ignore_store.append((subcls, "draw", subcls.draw))
|
|
|
|
replace_draw()
|
|
|
|
return ui_ignore_store
|
|
|
|
|
|
def ui_draw_filter_unregister(ui_ignore_store):
|
|
for (obj, attr, value) in ui_ignore_store:
|
|
setattr(obj, attr, value)
|