Merge branch 'master' into blender2.8
This commit is contained in:
200
release/scripts/modules/bl_app_override/__init__.py
Normal file
200
release/scripts/modules/bl_app_override/__init__.py
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# <pep8-80 compliant>
|
||||||
|
|
||||||
|
"""
|
||||||
|
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"}:
|
||||||
|
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)
|
||||||
|
if not ui_ignore_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"}:
|
||||||
|
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)
|
||||||
|
if not ui_ignore_property(args[0].__class__.__name__, args[1]):
|
||||||
|
ret = real_func(*args, **kw)
|
||||||
|
else:
|
||||||
|
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)
|
||||||
|
if not ui_ignore_menu(args[0]):
|
||||||
|
ret = real_func(*args, **kw)
|
||||||
|
else:
|
||||||
|
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)
|
||||||
|
if not ui_ignore_label(args[0] if args else kw.get("text", "")):
|
||||||
|
ret = real_func(*args, **kw)
|
||||||
|
else:
|
||||||
|
# ret = real_func()
|
||||||
|
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
|
||||||
|
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)
|
||||||
167
release/scripts/modules/bl_app_override/helpers.py
Normal file
167
release/scripts/modules/bl_app_override/helpers.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# <pep8-80 compliant>
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# AppOverrideState
|
||||||
|
|
||||||
|
|
||||||
|
class AppOverrideState:
|
||||||
|
"""
|
||||||
|
Utility class to encapsulate overriding the application state
|
||||||
|
so that settings can be restored afterwards.
|
||||||
|
"""
|
||||||
|
__slots__ = (
|
||||||
|
# setup_classes
|
||||||
|
"_class_store",
|
||||||
|
# setup_ui_ignore
|
||||||
|
"_ui_ignore_store",
|
||||||
|
# setup_addons
|
||||||
|
"_addon_store",
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------
|
||||||
|
# Callbacks
|
||||||
|
#
|
||||||
|
# Set as None, to make it simple to check if they're being overridden.
|
||||||
|
|
||||||
|
# setup/teardown classes
|
||||||
|
class_ignore = None
|
||||||
|
|
||||||
|
# setup/teardown ui_ignore
|
||||||
|
ui_ignore_classes = None
|
||||||
|
ui_ignore_operator = None
|
||||||
|
ui_ignore_property = None
|
||||||
|
ui_ignore_menu = None
|
||||||
|
ui_ignore_label = None
|
||||||
|
|
||||||
|
addon_paths = None
|
||||||
|
addons = None
|
||||||
|
|
||||||
|
# End callbacks
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._class_store = None
|
||||||
|
self._addon_store = None
|
||||||
|
self._ui_ignore_store = None
|
||||||
|
|
||||||
|
def _setup_classes(self):
|
||||||
|
import bpy
|
||||||
|
assert(self._class_store is None)
|
||||||
|
self._class_store = self.class_ignore()
|
||||||
|
from bpy.utils import unregister_class
|
||||||
|
for cls in self._class_store:
|
||||||
|
unregister_class(cls)
|
||||||
|
|
||||||
|
def _teardown_classes(self):
|
||||||
|
assert(self._class_store is not None)
|
||||||
|
|
||||||
|
from bpy.utils import register_class
|
||||||
|
for cls in self._class_store:
|
||||||
|
register_class(cls)
|
||||||
|
self._class_store = None
|
||||||
|
|
||||||
|
def _setup_ui_ignore(self):
|
||||||
|
import bl_app_override
|
||||||
|
|
||||||
|
self._ui_ignore_store = bl_app_override.ui_draw_filter_register(
|
||||||
|
ui_ignore_classes=(
|
||||||
|
None if self.ui_ignore_classes is None
|
||||||
|
else self.ui_ignore_classes()
|
||||||
|
),
|
||||||
|
ui_ignore_operator=self.ui_ignore_operator,
|
||||||
|
ui_ignore_property=self.ui_ignore_property,
|
||||||
|
ui_ignore_menu=self.ui_ignore_menu,
|
||||||
|
ui_ignore_label=self.ui_ignore_label,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _teardown_ui_ignore(self):
|
||||||
|
import bl_app_override
|
||||||
|
bl_app_override.ui_draw_filter_unregister(
|
||||||
|
self._ui_ignore_store
|
||||||
|
)
|
||||||
|
self._ui_ignore_store = None
|
||||||
|
|
||||||
|
def _setup_addons(self):
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys_path = []
|
||||||
|
if self.addon_paths is not None:
|
||||||
|
for path in self.addon_paths():
|
||||||
|
if path not in sys.path:
|
||||||
|
sys.path.append(path)
|
||||||
|
|
||||||
|
import addon_utils
|
||||||
|
addons = []
|
||||||
|
if self.addons is not None:
|
||||||
|
addons.extend(self.addons())
|
||||||
|
for addon in addons:
|
||||||
|
addon_utils.enable(addon)
|
||||||
|
|
||||||
|
self._addon_store = {
|
||||||
|
"sys_path": sys_path,
|
||||||
|
"addons": addons,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _teardown_addons(self):
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys_path = self._addon_store["sys_path"]
|
||||||
|
for path in sys_path:
|
||||||
|
# should always succeed, but if not it doesn't matter
|
||||||
|
# (someone else was changing the sys.path), ignore!
|
||||||
|
try:
|
||||||
|
sys.path.remove(path)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
addons = self._addon_store["addons"]
|
||||||
|
import addon_utils
|
||||||
|
for addon in addons:
|
||||||
|
addon_utils.disable(addon)
|
||||||
|
|
||||||
|
self._addon_store.clear()
|
||||||
|
self._addon_store = None
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
if self.class_ignore is not None:
|
||||||
|
self._setup_classes()
|
||||||
|
|
||||||
|
if any((self.addon_paths,
|
||||||
|
self.addons,
|
||||||
|
)):
|
||||||
|
self._setup_addons()
|
||||||
|
|
||||||
|
if any((self.ui_ignore_operator,
|
||||||
|
self.ui_ignore_property,
|
||||||
|
self.ui_ignore_menu,
|
||||||
|
self.ui_ignore_label,
|
||||||
|
)):
|
||||||
|
self._setup_ui_ignore()
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
if self._class_store is not None:
|
||||||
|
self._teardown_classes()
|
||||||
|
|
||||||
|
if self._addon_store is not None:
|
||||||
|
self._teardown_addons()
|
||||||
|
|
||||||
|
if self._ui_ignore_store is not None:
|
||||||
|
self._teardown_ui_ignore()
|
||||||
198
release/scripts/modules/bl_app_template_utils.py
Normal file
198
release/scripts/modules/bl_app_template_utils.py
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# <pep8-80 compliant>
|
||||||
|
|
||||||
|
"""
|
||||||
|
Similar to ``addon_utils``, except we can only have one active at a time.
|
||||||
|
|
||||||
|
In most cases users of this module will simply call 'activate'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
"activate",
|
||||||
|
"import_from_path",
|
||||||
|
"import_from_id",
|
||||||
|
"reset",
|
||||||
|
)
|
||||||
|
|
||||||
|
import bpy as _bpy
|
||||||
|
|
||||||
|
# Normally matches 'user_preferences.app_template_id',
|
||||||
|
# but loading new preferences will get us out of sync.
|
||||||
|
_app_template = {
|
||||||
|
"id": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
# instead of sys.modules
|
||||||
|
# note that we only ever have one template enabled at a time
|
||||||
|
# so it may not seem necessary to use this.
|
||||||
|
#
|
||||||
|
# However, templates may want to share between each-other,
|
||||||
|
# so any loaded modules are stored here?
|
||||||
|
#
|
||||||
|
# Note that the ID here is the app_template_id , not the modules __name__.
|
||||||
|
_modules = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _enable(template_id, *, handle_error=None, ignore_not_found=False):
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from bpy_restrict_state import RestrictBlend
|
||||||
|
|
||||||
|
if handle_error is None:
|
||||||
|
def handle_error(ex):
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# Split registering up into 2 steps so we can undo
|
||||||
|
# if it fails par way through.
|
||||||
|
|
||||||
|
# disable the context, using the context at all is
|
||||||
|
# really bad while loading an template, don't do it!
|
||||||
|
with RestrictBlend():
|
||||||
|
|
||||||
|
# 1) try import
|
||||||
|
try:
|
||||||
|
mod = import_from_id(template_id, ignore_not_found=ignore_not_found)
|
||||||
|
if mod is None:
|
||||||
|
return None
|
||||||
|
mod.__template_enabled__ = False
|
||||||
|
_modules[template_id] = mod
|
||||||
|
except Exception as ex:
|
||||||
|
handle_error(ex)
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 2) try run the modules register function
|
||||||
|
try:
|
||||||
|
mod.register()
|
||||||
|
except Exception as ex:
|
||||||
|
print("Exception in module register(): %r" %
|
||||||
|
getattr(mod, "__file__", template_id))
|
||||||
|
handle_error(ex)
|
||||||
|
del _modules[template_id]
|
||||||
|
return None
|
||||||
|
|
||||||
|
# * OK loaded successfully! *
|
||||||
|
mod.__template_enabled__ = True
|
||||||
|
|
||||||
|
if _bpy.app.debug_python:
|
||||||
|
print("\tapp_template_utils.enable", mod.__name__)
|
||||||
|
|
||||||
|
return mod
|
||||||
|
|
||||||
|
|
||||||
|
def _disable(template_id, *, handle_error=None):
|
||||||
|
"""
|
||||||
|
Disables a template by name.
|
||||||
|
|
||||||
|
:arg template_id: The name of the template and module.
|
||||||
|
:type template_id: string
|
||||||
|
:arg handle_error: Called in the case of an error,
|
||||||
|
taking an exception argument.
|
||||||
|
:type handle_error: function
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if handle_error is None:
|
||||||
|
def handle_error(ex):
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
mod = _modules.get(template_id)
|
||||||
|
|
||||||
|
if mod and getattr(mod, "__template_enabled__", False) is not False:
|
||||||
|
mod.__template_enabled__ = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
mod.unregister()
|
||||||
|
except Exception as ex:
|
||||||
|
print("Exception in module unregister(): %r" %
|
||||||
|
getattr(mod, "__file__", template_id))
|
||||||
|
handle_error(ex)
|
||||||
|
else:
|
||||||
|
print("\tapp_template_utils.disable: %s not %s." %
|
||||||
|
(template_id, "disabled" if mod is None else "loaded"))
|
||||||
|
|
||||||
|
if _bpy.app.debug_python:
|
||||||
|
print("\tapp_template_utils.disable", template_id)
|
||||||
|
|
||||||
|
|
||||||
|
def import_from_path(path, ignore_not_found=False):
|
||||||
|
import os
|
||||||
|
from importlib import import_module
|
||||||
|
base_module, template_id = path.rsplit(os.sep, 2)[-2:]
|
||||||
|
module_name = base_module + "." + template_id
|
||||||
|
|
||||||
|
try:
|
||||||
|
return import_module(module_name)
|
||||||
|
except ModuleNotFoundError as ex:
|
||||||
|
if ignore_not_found and ex.name == module_name:
|
||||||
|
return None
|
||||||
|
raise ex
|
||||||
|
|
||||||
|
|
||||||
|
def import_from_id(template_id, ignore_not_found=False):
|
||||||
|
import os
|
||||||
|
path = next(iter(_bpy.utils.app_template_paths(template_id)), None)
|
||||||
|
if path is None:
|
||||||
|
if ignore_not_found:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise Exception("%r template not found!" % template_id)
|
||||||
|
else:
|
||||||
|
if ignore_not_found:
|
||||||
|
if not os.path.exists(os.path.join(path, "__init__.py")):
|
||||||
|
return None
|
||||||
|
return import_from_path(path, ignore_not_found=ignore_not_found)
|
||||||
|
|
||||||
|
|
||||||
|
def activate(template_id=None):
|
||||||
|
template_id_prev = _app_template["id"]
|
||||||
|
|
||||||
|
# not needed but may as well avoid activating same template
|
||||||
|
# ... in fact keep this, it will show errors early on!
|
||||||
|
"""
|
||||||
|
if template_id_prev == template_id:
|
||||||
|
return
|
||||||
|
"""
|
||||||
|
|
||||||
|
if template_id_prev:
|
||||||
|
_disable(template_id_prev)
|
||||||
|
|
||||||
|
# Disable all addons, afterwards caller must reset.
|
||||||
|
import addon_utils
|
||||||
|
addon_utils.disable_all()
|
||||||
|
|
||||||
|
# ignore_not_found so modules that don't contain scripts don't raise errors
|
||||||
|
mod = _enable(template_id, ignore_not_found=True) if template_id else None
|
||||||
|
|
||||||
|
_app_template["id"] = template_id
|
||||||
|
|
||||||
|
|
||||||
|
def reset(*, reload_scripts=False):
|
||||||
|
"""
|
||||||
|
Sets default state.
|
||||||
|
"""
|
||||||
|
template_id = _bpy.context.user_preferences.app_template
|
||||||
|
if _bpy.app.debug_python:
|
||||||
|
print("bl_app_template_utils.reset('%s')" % template_id)
|
||||||
|
|
||||||
|
# TODO reload_scripts
|
||||||
|
|
||||||
|
activate(template_id)
|
||||||
@@ -32,6 +32,7 @@ __all__ = (
|
|||||||
"preset_find",
|
"preset_find",
|
||||||
"preset_paths",
|
"preset_paths",
|
||||||
"refresh_script_paths",
|
"refresh_script_paths",
|
||||||
|
"app_template_paths",
|
||||||
"register_class",
|
"register_class",
|
||||||
"register_module",
|
"register_module",
|
||||||
"register_manual_map",
|
"register_manual_map",
|
||||||
@@ -245,6 +246,12 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
|||||||
for mod in modules_from_path(path, loaded_modules):
|
for mod in modules_from_path(path, loaded_modules):
|
||||||
test_register(mod)
|
test_register(mod)
|
||||||
|
|
||||||
|
# load template (if set)
|
||||||
|
if any(_bpy.utils.app_template_paths()):
|
||||||
|
import bl_app_template_utils
|
||||||
|
bl_app_template_utils.reset(reload_scripts=reload_scripts)
|
||||||
|
del bl_app_template_utils
|
||||||
|
|
||||||
# deal with addons separately
|
# deal with addons separately
|
||||||
_initialize = getattr(_addon_utils, "_initialize", None)
|
_initialize = getattr(_addon_utils, "_initialize", None)
|
||||||
if _initialize is not None:
|
if _initialize is not None:
|
||||||
@@ -356,6 +363,38 @@ def refresh_script_paths():
|
|||||||
_sys_path_ensure(path)
|
_sys_path_ensure(path)
|
||||||
|
|
||||||
|
|
||||||
|
def app_template_paths(subdir=None):
|
||||||
|
"""
|
||||||
|
Returns valid application template paths.
|
||||||
|
|
||||||
|
:arg subdir: Optional subdir.
|
||||||
|
:type subdir: string
|
||||||
|
:return: app template paths.
|
||||||
|
:rtype: generator
|
||||||
|
"""
|
||||||
|
|
||||||
|
# note: LOCAL, USER, SYSTEM order matches script resolution order.
|
||||||
|
subdir_tuple = (subdir,) if subdir is not None else ()
|
||||||
|
|
||||||
|
path = _os.path.join(*(
|
||||||
|
resource_path('LOCAL'), "scripts", "startup",
|
||||||
|
"bl_app_templates_user", *subdir_tuple))
|
||||||
|
if _os.path.isdir(path):
|
||||||
|
yield path
|
||||||
|
else:
|
||||||
|
path = _os.path.join(*(
|
||||||
|
resource_path('USER'), "scripts", "startup",
|
||||||
|
"bl_app_templates_user", *subdir_tuple))
|
||||||
|
if _os.path.isdir(path):
|
||||||
|
yield path
|
||||||
|
|
||||||
|
path = _os.path.join(*(
|
||||||
|
resource_path('SYSTEM'), "scripts", "startup",
|
||||||
|
"bl_app_templates_system", *subdir_tuple))
|
||||||
|
if _os.path.isdir(path):
|
||||||
|
yield path
|
||||||
|
|
||||||
|
|
||||||
def preset_paths(subdir):
|
def preset_paths(subdir):
|
||||||
"""
|
"""
|
||||||
Returns a list of paths for a specific preset.
|
Returns a list of paths for a specific preset.
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ import bpy
|
|||||||
import os
|
import os
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import FloatProperty
|
from bpy.props import FloatProperty
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import (
|
||||||
|
Vector,
|
||||||
|
Matrix,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def CLIP_spaces_walk(context, all_screens, tarea, tspace, callback, *args):
|
def CLIP_spaces_walk(context, all_screens, tarea, tspace, callback, *args):
|
||||||
@@ -1084,4 +1087,4 @@ classes = (
|
|||||||
CLIP_OT_track_settings_as_default,
|
CLIP_OT_track_settings_as_default,
|
||||||
CLIP_OT_track_settings_to_track,
|
CLIP_OT_track_settings_to_track,
|
||||||
CLIP_OT_track_to_empty,
|
CLIP_OT_track_to_empty,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,13 +16,15 @@
|
|||||||
#
|
#
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# <pep8 compliant>
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
EnumProperty,
|
EnumProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
|
class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
|
||||||
|
|||||||
@@ -21,7 +21,10 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
|
|
||||||
from bpy.props import EnumProperty, IntProperty
|
from bpy.props import (
|
||||||
|
EnumProperty,
|
||||||
|
IntProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MeshMirrorUV(Operator):
|
class MeshMirrorUV(Operator):
|
||||||
@@ -254,4 +257,4 @@ classes = (
|
|||||||
MeshMirrorUV,
|
MeshMirrorUV,
|
||||||
MeshSelectNext,
|
MeshSelectNext,
|
||||||
MeshSelectPrev,
|
MeshSelectPrev,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,16 +21,16 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import nodeitems_utils
|
import nodeitems_utils
|
||||||
from bpy.types import (
|
from bpy.types import (
|
||||||
Operator,
|
Operator,
|
||||||
PropertyGroup,
|
PropertyGroup,
|
||||||
)
|
)
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
CollectionProperty,
|
CollectionProperty,
|
||||||
EnumProperty,
|
EnumProperty,
|
||||||
IntProperty,
|
IntProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class NodeSetting(PropertyGroup):
|
class NodeSetting(PropertyGroup):
|
||||||
|
|||||||
@@ -21,12 +21,12 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
StringProperty,
|
BoolProperty,
|
||||||
BoolProperty,
|
EnumProperty,
|
||||||
EnumProperty,
|
FloatProperty,
|
||||||
IntProperty,
|
IntProperty,
|
||||||
FloatProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SelectPattern(Operator):
|
class SelectPattern(Operator):
|
||||||
@@ -1054,4 +1054,4 @@ classes = (
|
|||||||
SubdivisionSet,
|
SubdivisionSet,
|
||||||
TransformsToDeltas,
|
TransformsToDeltas,
|
||||||
TransformsToDeltasAnim,
|
TransformsToDeltasAnim,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,13 +26,14 @@ from mathutils import Vector
|
|||||||
def GlobalBB_LQ(bb_world):
|
def GlobalBB_LQ(bb_world):
|
||||||
|
|
||||||
# Initialize the variables with the 8th vertex
|
# Initialize the variables with the 8th vertex
|
||||||
left, right, front, back, down, up = (bb_world[7][0],
|
left, right, front, back, down, up = (
|
||||||
bb_world[7][0],
|
bb_world[7][0],
|
||||||
bb_world[7][1],
|
bb_world[7][0],
|
||||||
bb_world[7][1],
|
bb_world[7][1],
|
||||||
bb_world[7][2],
|
bb_world[7][1],
|
||||||
bb_world[7][2],
|
bb_world[7][2],
|
||||||
)
|
bb_world[7][2],
|
||||||
|
)
|
||||||
|
|
||||||
# Test against the other 7 verts
|
# Test against the other 7 verts
|
||||||
for i in range(7):
|
for i in range(7):
|
||||||
@@ -398,13 +399,15 @@ class AlignObjects(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
align_axis = self.align_axis
|
align_axis = self.align_axis
|
||||||
ret = align_objects(context,
|
ret = align_objects(
|
||||||
'X' in align_axis,
|
context,
|
||||||
'Y' in align_axis,
|
'X' in align_axis,
|
||||||
'Z' in align_axis,
|
'Y' in align_axis,
|
||||||
self.align_mode,
|
'Z' in align_axis,
|
||||||
self.relative_to,
|
self.align_mode,
|
||||||
self.bb_quality)
|
self.relative_to,
|
||||||
|
self.bb_quality,
|
||||||
|
)
|
||||||
|
|
||||||
if not ret:
|
if not ret:
|
||||||
self.report({'WARNING'}, "No objects with bound-box selected")
|
self.report({'WARNING'}, "No objects with bound-box selected")
|
||||||
@@ -415,4 +418,4 @@ class AlignObjects(Operator):
|
|||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
AlignObjects,
|
AlignObjects,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ from mathutils import Vector
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
EnumProperty,
|
EnumProperty,
|
||||||
IntProperty,
|
IntProperty,
|
||||||
FloatProperty,
|
FloatProperty,
|
||||||
FloatVectorProperty,
|
FloatVectorProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def object_ensure_material(obj, mat_name):
|
def object_ensure_material(obj, mat_name):
|
||||||
@@ -652,4 +652,4 @@ classes = (
|
|||||||
QuickFluid,
|
QuickFluid,
|
||||||
QuickFur,
|
QuickFur,
|
||||||
QuickSmoke,
|
QuickSmoke,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import IntProperty
|
from bpy.props import (
|
||||||
from bpy.props import EnumProperty
|
EnumProperty,
|
||||||
|
IntProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CopyRigidbodySettings(Operator):
|
class CopyRigidbodySettings(Operator):
|
||||||
@@ -315,4 +317,4 @@ classes = (
|
|||||||
BakeToKeyframes,
|
BakeToKeyframes,
|
||||||
ConnectRigidBodies,
|
ConnectRigidBodies,
|
||||||
CopyRigidbodySettings,
|
CopyRigidbodySettings,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -18,7 +18,11 @@
|
|||||||
|
|
||||||
# TODO <pep8 compliant>
|
# TODO <pep8 compliant>
|
||||||
|
|
||||||
from mathutils import Matrix, Vector, geometry
|
from mathutils import (
|
||||||
|
Matrix,
|
||||||
|
Vector,
|
||||||
|
geometry,
|
||||||
|
)
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
|
|
||||||
@@ -1104,4 +1108,4 @@ class SmartProject(Operator):
|
|||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
SmartProject,
|
SmartProject,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,12 +21,12 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Operator
|
from bpy.types import Operator
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
StringProperty,
|
StringProperty,
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
IntProperty,
|
IntProperty,
|
||||||
FloatProperty,
|
FloatProperty,
|
||||||
EnumProperty,
|
EnumProperty,
|
||||||
)
|
)
|
||||||
|
|
||||||
from bpy.app.translations import pgettext_tip as tip_
|
from bpy.app.translations import pgettext_tip as tip_
|
||||||
|
|
||||||
@@ -130,6 +130,20 @@ def execute_context_assign(self, context):
|
|||||||
return operator_path_undo_return(context, data_path)
|
return operator_path_undo_return(context, data_path)
|
||||||
|
|
||||||
|
|
||||||
|
def module_filesystem_remove(path_base, module_name):
|
||||||
|
import os
|
||||||
|
module_name = os.path.splitext(module_name)[0]
|
||||||
|
for f in os.listdir(path_base):
|
||||||
|
f_base = os.path.splitext(f)[0]
|
||||||
|
if f_base == module_name:
|
||||||
|
f_full = os.path.join(path_base, f)
|
||||||
|
|
||||||
|
if os.path.isdir(f_full):
|
||||||
|
os.rmdir(f_full)
|
||||||
|
else:
|
||||||
|
os.remove(f_full)
|
||||||
|
|
||||||
|
|
||||||
class BRUSH_OT_active_index_set(Operator):
|
class BRUSH_OT_active_index_set(Operator):
|
||||||
"""Set active sculpt/paint brush from it's number"""
|
"""Set active sculpt/paint brush from it's number"""
|
||||||
bl_idname = "brush.active_index_set"
|
bl_idname = "brush.active_index_set"
|
||||||
@@ -907,7 +921,10 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
|
|||||||
# an operator (common case - just button referencing an op)
|
# an operator (common case - just button referencing an op)
|
||||||
if hasattr(bpy.types, class_name.upper() + "_OT_" + class_prop):
|
if hasattr(bpy.types, class_name.upper() + "_OT_" + class_prop):
|
||||||
if do_url:
|
if do_url:
|
||||||
url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
|
url = (
|
||||||
|
"%s/bpy.ops.%s.html#bpy.ops.%s.%s" %
|
||||||
|
(url_prefix, class_name, class_name, class_prop)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
|
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
|
||||||
else:
|
else:
|
||||||
@@ -922,7 +939,10 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
|
|||||||
class_name, class_prop = class_name.split("_OT_", 1)
|
class_name, class_prop = class_name.split("_OT_", 1)
|
||||||
class_name = class_name.lower()
|
class_name = class_name.lower()
|
||||||
if do_url:
|
if do_url:
|
||||||
url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
|
url = (
|
||||||
|
"%s/bpy.ops.%s.html#bpy.ops.%s.%s" %
|
||||||
|
(url_prefix, class_name, class_name, class_prop)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
|
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
|
||||||
else:
|
else:
|
||||||
@@ -938,9 +958,12 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
|
|||||||
rna_parent = rna_parent.base
|
rna_parent = rna_parent.base
|
||||||
|
|
||||||
if do_url:
|
if do_url:
|
||||||
url = ("%s/bpy.types.%s.html#bpy.types.%s.%s" % (url_prefix, class_name, class_name, class_prop))
|
url = (
|
||||||
|
"%s/bpy.types.%s.html#bpy.types.%s.%s" %
|
||||||
|
(url_prefix, class_name, class_name, class_prop)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
rna = ("bpy.types.%s.%s" % (class_name, class_prop))
|
rna = "bpy.types.%s.%s" % (class_name, class_prop)
|
||||||
else:
|
else:
|
||||||
# We assume this is custom property, only try to generate generic url/rna_id...
|
# We assume this is custom property, only try to generate generic url/rna_id...
|
||||||
if do_url:
|
if do_url:
|
||||||
@@ -1087,10 +1110,10 @@ class WM_OT_properties_edit(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from rna_prop_ui import (
|
from rna_prop_ui import (
|
||||||
rna_idprop_ui_prop_get,
|
rna_idprop_ui_prop_get,
|
||||||
rna_idprop_ui_prop_clear,
|
rna_idprop_ui_prop_clear,
|
||||||
rna_idprop_ui_prop_update,
|
rna_idprop_ui_prop_update,
|
||||||
)
|
)
|
||||||
|
|
||||||
data_path = self.data_path
|
data_path = self.data_path
|
||||||
value = self.value
|
value = self.value
|
||||||
@@ -1267,9 +1290,9 @@ class WM_OT_properties_add(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from rna_prop_ui import (
|
from rna_prop_ui import (
|
||||||
rna_idprop_ui_prop_get,
|
rna_idprop_ui_prop_get,
|
||||||
rna_idprop_ui_prop_update,
|
rna_idprop_ui_prop_update,
|
||||||
)
|
)
|
||||||
|
|
||||||
data_path = self.data_path
|
data_path = self.data_path
|
||||||
item = eval("context.%s" % data_path)
|
item = eval("context.%s" % data_path)
|
||||||
@@ -1284,10 +1307,10 @@ class WM_OT_properties_add(Operator):
|
|||||||
|
|
||||||
return prop_new
|
return prop_new
|
||||||
|
|
||||||
prop = unique_name(
|
prop = unique_name({
|
||||||
{*item.keys(),
|
*item.keys(),
|
||||||
*type(item).bl_rna.properties.keys(),
|
*type(item).bl_rna.properties.keys(),
|
||||||
})
|
})
|
||||||
|
|
||||||
item[prop] = 1.0
|
item[prop] = 1.0
|
||||||
rna_idprop_ui_prop_update(item, prop)
|
rna_idprop_ui_prop_update(item, prop)
|
||||||
@@ -1327,9 +1350,9 @@ class WM_OT_properties_remove(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
from rna_prop_ui import (
|
from rna_prop_ui import (
|
||||||
rna_idprop_ui_prop_clear,
|
rna_idprop_ui_prop_clear,
|
||||||
rna_idprop_ui_prop_update,
|
rna_idprop_ui_prop_update,
|
||||||
)
|
)
|
||||||
data_path = self.data_path
|
data_path = self.data_path
|
||||||
item = eval("context.%s" % data_path)
|
item = eval("context.%s" % data_path)
|
||||||
prop = self.property
|
prop = self.property
|
||||||
@@ -1367,7 +1390,10 @@ class WM_OT_appconfig_default(Operator):
|
|||||||
filepath = os.path.join(bpy.utils.preset_paths("interaction")[0], "blender.py")
|
filepath = os.path.join(bpy.utils.preset_paths("interaction")[0], "blender.py")
|
||||||
|
|
||||||
if os.path.exists(filepath):
|
if os.path.exists(filepath):
|
||||||
bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
|
bpy.ops.script.execute_preset(
|
||||||
|
filepath=filepath,
|
||||||
|
menu_idname="USERPREF_MT_interaction_presets",
|
||||||
|
)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@@ -1387,7 +1413,10 @@ class WM_OT_appconfig_activate(Operator):
|
|||||||
filepath = self.filepath.replace("keyconfig", "interaction")
|
filepath = self.filepath.replace("keyconfig", "interaction")
|
||||||
|
|
||||||
if os.path.exists(filepath):
|
if os.path.exists(filepath):
|
||||||
bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
|
bpy.ops.script.execute_preset(
|
||||||
|
filepath=filepath,
|
||||||
|
menu_idname="USERPREF_MT_interaction_presets",
|
||||||
|
)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@@ -1492,7 +1521,7 @@ class WM_OT_blenderplayer_start(Operator):
|
|||||||
"-g", "show_profile", "=", "%d" % gs.show_framerate_profile,
|
"-g", "show_profile", "=", "%d" % gs.show_framerate_profile,
|
||||||
"-g", "show_properties", "=", "%d" % gs.show_debug_properties,
|
"-g", "show_properties", "=", "%d" % gs.show_debug_properties,
|
||||||
"-g", "ignore_deprecation_warnings", "=", "%d" % (not gs.use_deprecation_warnings),
|
"-g", "ignore_deprecation_warnings", "=", "%d" % (not gs.use_deprecation_warnings),
|
||||||
])
|
])
|
||||||
|
|
||||||
# finish the call with the path to the blend file
|
# finish the call with the path to the blend file
|
||||||
args.append(filepath)
|
args.append(filepath)
|
||||||
@@ -1622,10 +1651,11 @@ class WM_OT_keyconfig_export(Operator):
|
|||||||
|
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
|
|
||||||
keyconfig_utils.keyconfig_export(wm,
|
keyconfig_utils.keyconfig_export(
|
||||||
wm.keyconfigs.active,
|
wm,
|
||||||
self.filepath,
|
wm.keyconfigs.active,
|
||||||
)
|
self.filepath,
|
||||||
|
)
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@@ -1890,7 +1920,10 @@ class WM_OT_theme_install(Operator):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
shutil.copyfile(xmlfile, path_dest)
|
shutil.copyfile(xmlfile, path_dest)
|
||||||
bpy.ops.script.execute_preset(filepath=path_dest, menu_idname="USERPREF_MT_interface_theme_presets")
|
bpy.ops.script.execute_preset(
|
||||||
|
filepath=path_dest,
|
||||||
|
menu_idname="USERPREF_MT_interface_theme_presets",
|
||||||
|
)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@@ -1917,10 +1950,12 @@ class WM_OT_addon_refresh(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
# Note: shares some logic with WM_OT_app_template_install
|
||||||
|
# but not enough to de-duplicate. Fixed here may apply to both.
|
||||||
class WM_OT_addon_install(Operator):
|
class WM_OT_addon_install(Operator):
|
||||||
"Install an add-on"
|
"Install an add-on"
|
||||||
bl_idname = "wm.addon_install"
|
bl_idname = "wm.addon_install"
|
||||||
bl_label = "Install from File..."
|
bl_label = "Install Add-on from File..."
|
||||||
|
|
||||||
overwrite = BoolProperty(
|
overwrite = BoolProperty(
|
||||||
name="Overwrite",
|
name="Overwrite",
|
||||||
@@ -1951,20 +1986,6 @@ class WM_OT_addon_install(Operator):
|
|||||||
options={'HIDDEN'},
|
options={'HIDDEN'},
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _module_remove(path_addons, module):
|
|
||||||
import os
|
|
||||||
module = os.path.splitext(module)[0]
|
|
||||||
for f in os.listdir(path_addons):
|
|
||||||
f_base = os.path.splitext(f)[0]
|
|
||||||
if f_base == module:
|
|
||||||
f_full = os.path.join(path_addons, f)
|
|
||||||
|
|
||||||
if os.path.isdir(f_full):
|
|
||||||
os.rmdir(f_full)
|
|
||||||
else:
|
|
||||||
os.remove(f_full)
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
import addon_utils
|
import addon_utils
|
||||||
import traceback
|
import traceback
|
||||||
@@ -2017,7 +2038,7 @@ class WM_OT_addon_install(Operator):
|
|||||||
|
|
||||||
if self.overwrite:
|
if self.overwrite:
|
||||||
for f in file_to_extract.namelist():
|
for f in file_to_extract.namelist():
|
||||||
WM_OT_addon_install._module_remove(path_addons, f)
|
module_filesystem_remove(path_addons, f)
|
||||||
else:
|
else:
|
||||||
for f in file_to_extract.namelist():
|
for f in file_to_extract.namelist():
|
||||||
path_dest = os.path.join(path_addons, os.path.basename(f))
|
path_dest = os.path.join(path_addons, os.path.basename(f))
|
||||||
@@ -2035,7 +2056,7 @@ class WM_OT_addon_install(Operator):
|
|||||||
path_dest = os.path.join(path_addons, os.path.basename(pyfile))
|
path_dest = os.path.join(path_addons, os.path.basename(pyfile))
|
||||||
|
|
||||||
if self.overwrite:
|
if self.overwrite:
|
||||||
WM_OT_addon_install._module_remove(path_addons, os.path.basename(pyfile))
|
module_filesystem_remove(path_addons, os.path.basename(pyfile))
|
||||||
elif os.path.exists(path_dest):
|
elif os.path.exists(path_dest):
|
||||||
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
|
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
@@ -2070,7 +2091,10 @@ class WM_OT_addon_install(Operator):
|
|||||||
bpy.utils.refresh_script_paths()
|
bpy.utils.refresh_script_paths()
|
||||||
|
|
||||||
# print message
|
# print message
|
||||||
msg = tip_("Modules Installed from %r into %r (%s)") % (pyfile, path_addons, ", ".join(sorted(addons_new)))
|
msg = (
|
||||||
|
tip_("Modules Installed (%s) from %r into %r (%s)") %
|
||||||
|
(", ".join(sorted(addons_new)), pyfile, path_addons)
|
||||||
|
)
|
||||||
print(msg)
|
print(msg)
|
||||||
self.report({'INFO'}, msg)
|
self.report({'INFO'}, msg)
|
||||||
|
|
||||||
@@ -2164,6 +2188,7 @@ class WM_OT_addon_expand(Operator):
|
|||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class WM_OT_addon_userpref_show(Operator):
|
class WM_OT_addon_userpref_show(Operator):
|
||||||
"Show add-on user preferences"
|
"Show add-on user preferences"
|
||||||
bl_idname = "wm.addon_userpref_show"
|
bl_idname = "wm.addon_userpref_show"
|
||||||
@@ -2194,6 +2219,123 @@ class WM_OT_addon_userpref_show(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
# Note: shares some logic with WM_OT_addon_install
|
||||||
|
# but not enough to de-duplicate. Fixes here may apply to both.
|
||||||
|
class WM_OT_app_template_install(Operator):
|
||||||
|
"Install an application-template"
|
||||||
|
bl_idname = "wm.app_template_install"
|
||||||
|
bl_label = "Install Template from File..."
|
||||||
|
|
||||||
|
overwrite = BoolProperty(
|
||||||
|
name="Overwrite",
|
||||||
|
description="Remove existing template with the same ID",
|
||||||
|
default=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
filepath = StringProperty(
|
||||||
|
subtype='FILE_PATH',
|
||||||
|
)
|
||||||
|
filter_folder = BoolProperty(
|
||||||
|
name="Filter folders",
|
||||||
|
default=True,
|
||||||
|
options={'HIDDEN'},
|
||||||
|
)
|
||||||
|
filter_python = BoolProperty(
|
||||||
|
name="Filter python",
|
||||||
|
default=True,
|
||||||
|
options={'HIDDEN'},
|
||||||
|
)
|
||||||
|
filter_glob = StringProperty(
|
||||||
|
default="*.py;*.zip",
|
||||||
|
options={'HIDDEN'},
|
||||||
|
)
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
import traceback
|
||||||
|
import zipfile
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
|
||||||
|
pyfile = self.filepath
|
||||||
|
|
||||||
|
path_app_templates = bpy.utils.user_resource(
|
||||||
|
'SCRIPTS', os.path.join("startup", "bl_app_templates_user"),
|
||||||
|
create=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not path_app_templates:
|
||||||
|
self.report({'ERROR'}, "Failed to get add-ons path")
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
if not os.path.isdir(path_app_templates):
|
||||||
|
try:
|
||||||
|
os.makedirs(path_app_templates, exist_ok=True)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
app_templates_old = set(os.listdir(path_app_templates))
|
||||||
|
|
||||||
|
# check to see if the file is in compressed format (.zip)
|
||||||
|
if zipfile.is_zipfile(pyfile):
|
||||||
|
try:
|
||||||
|
file_to_extract = zipfile.ZipFile(pyfile, 'r')
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
if self.overwrite:
|
||||||
|
for f in file_to_extract.namelist():
|
||||||
|
module_filesystem_remove(path_app_templates, f)
|
||||||
|
else:
|
||||||
|
for f in file_to_extract.namelist():
|
||||||
|
path_dest = os.path.join(path_app_templates, os.path.basename(f))
|
||||||
|
if os.path.exists(path_dest):
|
||||||
|
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
try: # extract the file to "bl_app_templates_user"
|
||||||
|
file_to_extract.extractall(path_app_templates)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
else:
|
||||||
|
path_dest = os.path.join(path_app_templates, os.path.basename(pyfile))
|
||||||
|
|
||||||
|
if self.overwrite:
|
||||||
|
module_filesystem_remove(path_app_templates, os.path.basename(pyfile))
|
||||||
|
elif os.path.exists(path_dest):
|
||||||
|
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
# if not compressed file just copy into the addon path
|
||||||
|
try:
|
||||||
|
shutil.copyfile(pyfile, path_dest)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old
|
||||||
|
|
||||||
|
# in case a new module path was created to install this addon.
|
||||||
|
bpy.utils.refresh_script_paths()
|
||||||
|
|
||||||
|
# print message
|
||||||
|
msg = (
|
||||||
|
tip_("Template Installed (%s) from %r into %r") %
|
||||||
|
(", ".join(sorted(app_templates_new)), pyfile, path_app_templates)
|
||||||
|
)
|
||||||
|
print(msg)
|
||||||
|
self.report({'INFO'}, msg)
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
wm = context.window_manager
|
||||||
|
wm.fileselect_add(self)
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
BRUSH_OT_active_index_set,
|
BRUSH_OT_active_index_set,
|
||||||
WM_OT_addon_disable,
|
WM_OT_addon_disable,
|
||||||
@@ -2203,6 +2345,7 @@ classes = (
|
|||||||
WM_OT_addon_refresh,
|
WM_OT_addon_refresh,
|
||||||
WM_OT_addon_remove,
|
WM_OT_addon_remove,
|
||||||
WM_OT_addon_userpref_show,
|
WM_OT_addon_userpref_show,
|
||||||
|
WM_OT_app_template_install,
|
||||||
WM_OT_appconfig_activate,
|
WM_OT_appconfig_activate,
|
||||||
WM_OT_appconfig_default,
|
WM_OT_appconfig_default,
|
||||||
WM_OT_blenderplayer_start,
|
WM_OT_blenderplayer_start,
|
||||||
@@ -2246,4 +2389,4 @@ classes = (
|
|||||||
WM_OT_sysinfo,
|
WM_OT_sysinfo,
|
||||||
WM_OT_theme_install,
|
WM_OT_theme_install,
|
||||||
WM_OT_url_open,
|
WM_OT_url_open,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -127,6 +127,18 @@ class INFO_MT_file(Menu):
|
|||||||
layout.operator("wm.save_homefile", icon='SAVE_PREFS')
|
layout.operator("wm.save_homefile", icon='SAVE_PREFS')
|
||||||
layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
|
layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
|
||||||
|
|
||||||
|
if any(bpy.utils.app_template_paths()):
|
||||||
|
app_template = context.user_preferences.app_template
|
||||||
|
if app_template:
|
||||||
|
layout.operator(
|
||||||
|
"wm.read_factory_settings",
|
||||||
|
text="Load Factory Template Settings",
|
||||||
|
icon='LOAD_FACTORY',
|
||||||
|
).app_template = app_template
|
||||||
|
del app_template
|
||||||
|
|
||||||
|
layout.menu("USERPREF_MT_app_templates", icon='FILE_BLEND')
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
layout.operator_context = 'INVOKE_AREA'
|
layout.operator_context = 'INVOKE_AREA'
|
||||||
|
|||||||
@@ -90,6 +90,63 @@ class USERPREF_MT_interaction_presets(Menu):
|
|||||||
draw = Menu.draw_preset
|
draw = Menu.draw_preset
|
||||||
|
|
||||||
|
|
||||||
|
class USERPREF_MT_app_templates(Menu):
|
||||||
|
bl_label = "Application Templates"
|
||||||
|
preset_subdir = "app_templates"
|
||||||
|
|
||||||
|
def draw_ex(self, context, *, use_splash=False, use_default=False, use_install=False):
|
||||||
|
import os
|
||||||
|
|
||||||
|
layout = self.layout
|
||||||
|
|
||||||
|
# now draw the presets
|
||||||
|
layout.operator_context = 'EXEC_DEFAULT'
|
||||||
|
|
||||||
|
if use_default:
|
||||||
|
props = layout.operator("wm.read_homefile", text="Default")
|
||||||
|
props.use_splash = True
|
||||||
|
props.app_template = ""
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
template_paths = bpy.utils.app_template_paths()
|
||||||
|
|
||||||
|
# expand template paths
|
||||||
|
app_templates = []
|
||||||
|
for path in template_paths:
|
||||||
|
for d in os.listdir(path):
|
||||||
|
if d.startswith(("__", ".")):
|
||||||
|
continue
|
||||||
|
template = os.path.join(path, d)
|
||||||
|
if os.path.isdir(template):
|
||||||
|
# template_paths_expand.append(template)
|
||||||
|
app_templates.append(d)
|
||||||
|
|
||||||
|
for d in sorted(app_templates):
|
||||||
|
props = layout.operator(
|
||||||
|
"wm.read_homefile",
|
||||||
|
text=bpy.path.display_name(d),
|
||||||
|
)
|
||||||
|
props.use_splash = True
|
||||||
|
props.app_template = d;
|
||||||
|
|
||||||
|
if use_install:
|
||||||
|
layout.separator()
|
||||||
|
layout.operator_context = 'INVOKE_DEFAULT'
|
||||||
|
props = layout.operator("wm.app_template_install")
|
||||||
|
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
self.draw_ex(context, use_splash=False, use_default=True, use_install=True)
|
||||||
|
|
||||||
|
|
||||||
|
class USERPREF_MT_templates_splash(Menu):
|
||||||
|
bl_label = "Startup Templates"
|
||||||
|
preset_subdir = "templates"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
USERPREF_MT_app_templates.draw_ex(self, context, use_splash=True, use_default=True)
|
||||||
|
|
||||||
|
|
||||||
class USERPREF_MT_appconfigs(Menu):
|
class USERPREF_MT_appconfigs(Menu):
|
||||||
bl_label = "AppPresets"
|
bl_label = "AppPresets"
|
||||||
preset_subdir = "keyconfig"
|
preset_subdir = "keyconfig"
|
||||||
@@ -110,7 +167,17 @@ class USERPREF_MT_splash(Menu):
|
|||||||
|
|
||||||
split = layout.split()
|
split = layout.split()
|
||||||
row = split.row()
|
row = split.row()
|
||||||
row.label("")
|
|
||||||
|
if any(bpy.utils.app_template_paths()):
|
||||||
|
row.label("Template:")
|
||||||
|
template = context.user_preferences.app_template
|
||||||
|
row.menu(
|
||||||
|
"USERPREF_MT_templates_splash",
|
||||||
|
text=bpy.path.display_name(template) if template else "Default",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
row.label("")
|
||||||
|
|
||||||
row = split.row()
|
row = split.row()
|
||||||
row.label("Interaction:")
|
row.label("Interaction:")
|
||||||
|
|
||||||
@@ -1485,6 +1552,8 @@ classes = (
|
|||||||
USERPREF_HT_header,
|
USERPREF_HT_header,
|
||||||
USERPREF_PT_tabs,
|
USERPREF_PT_tabs,
|
||||||
USERPREF_MT_interaction_presets,
|
USERPREF_MT_interaction_presets,
|
||||||
|
USERPREF_MT_templates_splash,
|
||||||
|
USERPREF_MT_app_templates,
|
||||||
USERPREF_MT_appconfigs,
|
USERPREF_MT_appconfigs,
|
||||||
USERPREF_MT_splash,
|
USERPREF_MT_splash,
|
||||||
USERPREF_MT_splash_footer,
|
USERPREF_MT_splash_footer,
|
||||||
|
|||||||
@@ -19,7 +19,11 @@
|
|||||||
# <pep8 compliant>
|
# <pep8 compliant>
|
||||||
import bpy
|
import bpy
|
||||||
import nodeitems_utils
|
import nodeitems_utils
|
||||||
from nodeitems_utils import NodeCategory, NodeItem, NodeItemCustom
|
from nodeitems_utils import (
|
||||||
|
NodeCategory,
|
||||||
|
NodeItem,
|
||||||
|
NodeItemCustom,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Subclasses for standard node types
|
# Subclasses for standard node types
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfold
|
|||||||
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
|
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
|
||||||
const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
|
const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
|
||||||
|
|
||||||
|
bool BKE_appdir_app_template_any(void);
|
||||||
|
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len);
|
||||||
|
|
||||||
/* Initialize path to program executable */
|
/* Initialize path to program executable */
|
||||||
void BKE_appdir_program_path_init(const char *argv0);
|
void BKE_appdir_program_path_init(const char *argv0);
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ void BKE_blender_userdef_set_data(struct UserDef *userdef);
|
|||||||
void BKE_blender_userdef_free_data(struct UserDef *userdef);
|
void BKE_blender_userdef_free_data(struct UserDef *userdef);
|
||||||
void BKE_blender_userdef_refresh(void);
|
void BKE_blender_userdef_refresh(void);
|
||||||
|
|
||||||
|
void BKE_blender_userdef_set_app_template(struct UserDef *userdef);
|
||||||
|
|
||||||
/* set this callback when a UI is running */
|
/* set this callback when a UI is running */
|
||||||
void BKE_blender_callback_test_break_set(void (*func)(void));
|
void BKE_blender_callback_test_break_set(void (*func)(void));
|
||||||
int BKE_blender_test_break(void);
|
int BKE_blender_test_break(void);
|
||||||
|
|||||||
@@ -683,6 +683,48 @@ bool BKE_appdir_program_python_search(
|
|||||||
return is_found;
|
return is_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *app_template_directory_search[2] = {
|
||||||
|
"startup" SEP_STR "bl_app_templates_user",
|
||||||
|
"startup" SEP_STR "bl_app_templates_system",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int app_template_directory_id[2] = {
|
||||||
|
BLENDER_USER_SCRIPTS,
|
||||||
|
BLENDER_SYSTEM_SCRIPTS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if templates exist
|
||||||
|
*/
|
||||||
|
bool BKE_appdir_app_template_any(void)
|
||||||
|
{
|
||||||
|
char temp_dir[FILE_MAX];
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (BKE_appdir_folder_id_ex(
|
||||||
|
app_template_directory_id[i], app_template_directory_search[i],
|
||||||
|
temp_dir, sizeof(temp_dir)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
char subdir[FILE_MAX];
|
||||||
|
BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template);
|
||||||
|
if (BKE_appdir_folder_id_ex(
|
||||||
|
app_template_directory_id[i], subdir,
|
||||||
|
path, path_len))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the temp directory when blender first runs.
|
* Gets the temp directory when blender first runs.
|
||||||
* If the default path is not found, use try $TEMP
|
* If the default path is not found, use try $TEMP
|
||||||
|
|||||||
@@ -238,6 +238,44 @@ void BKE_blender_userdef_refresh(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write U from userdef.
|
||||||
|
* This function defines which settings a template will override for the user preferences.
|
||||||
|
*/
|
||||||
|
void BKE_blender_userdef_set_app_template(UserDef *userdef)
|
||||||
|
{
|
||||||
|
/* TODO:
|
||||||
|
* - keymaps
|
||||||
|
* - various minor settings (add as needed).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIST_OVERRIDE(id) { \
|
||||||
|
BLI_freelistN(&U.id); \
|
||||||
|
BLI_movelisttolist(&U.id, &userdef->id); \
|
||||||
|
} ((void)0)
|
||||||
|
|
||||||
|
#define MEMCPY_OVERRIDE(id) \
|
||||||
|
memcpy(U.id, userdef->id, sizeof(U.id));
|
||||||
|
|
||||||
|
/* for some types we need custom free functions */
|
||||||
|
userdef_free_addons(&U);
|
||||||
|
userdef_free_keymaps(&U);
|
||||||
|
|
||||||
|
LIST_OVERRIDE(uistyles);
|
||||||
|
LIST_OVERRIDE(uifonts);
|
||||||
|
LIST_OVERRIDE(themes);
|
||||||
|
LIST_OVERRIDE(addons);
|
||||||
|
LIST_OVERRIDE(user_keymaps);
|
||||||
|
|
||||||
|
MEMCPY_OVERRIDE(light);
|
||||||
|
|
||||||
|
MEMCPY_OVERRIDE(font_path_ui);
|
||||||
|
MEMCPY_OVERRIDE(font_path_ui_mono);
|
||||||
|
|
||||||
|
#undef LIST_OVERRIDE
|
||||||
|
#undef MEMCPY_OVERRIDE
|
||||||
|
}
|
||||||
|
|
||||||
/* ***************** testing for break ************* */
|
/* ***************** testing for break ************* */
|
||||||
|
|
||||||
static void (*blender_test_break_cb)(void) = NULL;
|
static void (*blender_test_break_cb)(void) = NULL;
|
||||||
|
|||||||
@@ -33,14 +33,10 @@
|
|||||||
/** \file blender/blenkernel/intern/customdata.c
|
/** \file blender/blenkernel/intern/customdata.c
|
||||||
* \ingroup bke
|
* \ingroup bke
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "DNA_customdata_types.h"
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
|
|
||||||
@@ -48,7 +44,6 @@
|
|||||||
#include "BLI_path_util.h"
|
#include "BLI_path_util.h"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
#include "BLI_string_utils.h"
|
#include "BLI_string_utils.h"
|
||||||
#include "BLI_math.h"
|
|
||||||
#include "BLI_math_color_blend.h"
|
#include "BLI_math_color_blend.h"
|
||||||
#include "BLI_mempool.h"
|
#include "BLI_mempool.h"
|
||||||
|
|
||||||
@@ -66,16 +61,11 @@
|
|||||||
|
|
||||||
#include "bmesh.h"
|
#include "bmesh.h"
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* number of layers to add when growing a CustomData object */
|
/* number of layers to add when growing a CustomData object */
|
||||||
#define CUSTOMDATA_GROW 5
|
#define CUSTOMDATA_GROW 5
|
||||||
|
|
||||||
/* ensure typemap size is ok */
|
/* ensure typemap size is ok */
|
||||||
BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) /
|
BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "size mismatch");
|
||||||
sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES,
|
|
||||||
"size mismatch");
|
|
||||||
|
|
||||||
|
|
||||||
/********************* Layer type information **********************/
|
/********************* Layer type information **********************/
|
||||||
@@ -1062,15 +1052,10 @@ static void layerInterp_mcol(
|
|||||||
|
|
||||||
/* Subdivide smooth or fractal can cause problems without clamping
|
/* Subdivide smooth or fractal can cause problems without clamping
|
||||||
* although weights should also not cause this situation */
|
* although weights should also not cause this situation */
|
||||||
CLAMP(col[j].a, 0.0f, 255.0f);
|
mc[j].a = CLAMPIS(iroundf(col[j].a), 0, 255);
|
||||||
CLAMP(col[j].r, 0.0f, 255.0f);
|
mc[j].r = CLAMPIS(iroundf(col[j].r), 0, 255);
|
||||||
CLAMP(col[j].g, 0.0f, 255.0f);
|
mc[j].g = CLAMPIS(iroundf(col[j].g), 0, 255);
|
||||||
CLAMP(col[j].b, 0.0f, 255.0f);
|
mc[j].b = CLAMPIS(iroundf(col[j].b), 0, 255);
|
||||||
|
|
||||||
mc[j].a = (int)col[j].a;
|
|
||||||
mc[j].r = (int)col[j].r;
|
|
||||||
mc[j].g = (int)col[j].g;
|
|
||||||
mc[j].b = (int)col[j].b;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,7 +473,10 @@ typedef struct UserDef {
|
|||||||
char pad2;
|
char pad2;
|
||||||
short transopts;
|
short transopts;
|
||||||
short menuthreshold1, menuthreshold2;
|
short menuthreshold1, menuthreshold2;
|
||||||
|
|
||||||
|
/* startup template */
|
||||||
|
char app_template[64];
|
||||||
|
|
||||||
struct ListBase themes;
|
struct ListBase themes;
|
||||||
struct ListBase uifonts;
|
struct ListBase uifonts;
|
||||||
struct ListBase uistyles;
|
struct ListBase uistyles;
|
||||||
|
|||||||
@@ -4678,6 +4678,11 @@ void RNA_def_userdef(BlenderRNA *brna)
|
|||||||
"Active section of the user preferences shown in the user interface");
|
"Active section of the user preferences shown in the user interface");
|
||||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||||
|
|
||||||
|
/* don't expose this directly via the UI, modify via an operator */
|
||||||
|
prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE);
|
||||||
|
RNA_def_property_string_sdna(prop, NULL, "app_template");
|
||||||
|
RNA_def_property_ui_text(prop, "Application Template", "");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE);
|
prop = RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE);
|
||||||
RNA_def_property_collection_sdna(prop, NULL, "themes", NULL);
|
RNA_def_property_collection_sdna(prop, NULL, "themes", NULL);
|
||||||
RNA_def_property_struct_type(prop, "Theme");
|
RNA_def_property_struct_type(prop, "Theme");
|
||||||
|
|||||||
@@ -470,6 +470,10 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
|
|||||||
if (is_startup_file) {
|
if (is_startup_file) {
|
||||||
/* possible python hasn't been initialized */
|
/* possible python hasn't been initialized */
|
||||||
if (CTX_py_init_get(C)) {
|
if (CTX_py_init_get(C)) {
|
||||||
|
/* Only run when we have a template path found. */
|
||||||
|
if (BKE_appdir_app_template_any()) {
|
||||||
|
BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
|
||||||
|
}
|
||||||
/* sync addons, these may have changed from the defaults */
|
/* sync addons, these may have changed from the defaults */
|
||||||
BPY_execute_string(C, "__import__('addon_utils').reset_all()");
|
BPY_execute_string(C, "__import__('addon_utils').reset_all()");
|
||||||
|
|
||||||
@@ -635,15 +639,23 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
|
|||||||
* \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
|
* \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
|
||||||
* Used for "Restore Factory Settings".
|
* Used for "Restore Factory Settings".
|
||||||
* \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
|
* \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
|
||||||
|
* \param app_template_override: Template to use instead of the template defined in user-preferences.
|
||||||
|
* When not-null, this is written into the user preferences.
|
||||||
*/
|
*/
|
||||||
int wm_homefile_read(
|
int wm_homefile_read(
|
||||||
bContext *C, ReportList *reports,
|
bContext *C, ReportList *reports, bool use_factory_settings,
|
||||||
bool use_factory_settings, const char *filepath_startup_override)
|
const char *filepath_startup_override, const char *app_template_override)
|
||||||
{
|
{
|
||||||
ListBase wmbase;
|
ListBase wmbase;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
char filepath_startup[FILE_MAX];
|
char filepath_startup[FILE_MAX];
|
||||||
char filepath_userdef[FILE_MAX];
|
char filepath_userdef[FILE_MAX];
|
||||||
bool success = false;
|
|
||||||
|
/* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */
|
||||||
|
char app_template_system[FILE_MAX];
|
||||||
|
/* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */
|
||||||
|
char app_template_config[FILE_MAX];
|
||||||
|
|
||||||
/* Indicates whether user preferences were really load from memory.
|
/* Indicates whether user preferences were really load from memory.
|
||||||
*
|
*
|
||||||
@@ -675,12 +687,14 @@ int wm_homefile_read(
|
|||||||
|
|
||||||
filepath_startup[0] = '\0';
|
filepath_startup[0] = '\0';
|
||||||
filepath_userdef[0] = '\0';
|
filepath_userdef[0] = '\0';
|
||||||
|
app_template_system[0] = '\0';
|
||||||
|
app_template_config[0] = '\0';
|
||||||
|
|
||||||
|
const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
|
||||||
if (!use_factory_settings) {
|
if (!use_factory_settings) {
|
||||||
const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
|
|
||||||
if (cfgdir) {
|
if (cfgdir) {
|
||||||
BLI_make_file_string("/", filepath_startup, cfgdir, BLENDER_STARTUP_FILE);
|
BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL);
|
||||||
BLI_make_file_string("/", filepath_userdef, cfgdir, BLENDER_USERPREF_FILE);
|
BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
use_factory_settings = true;
|
use_factory_settings = true;
|
||||||
@@ -704,7 +718,43 @@ int wm_homefile_read(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_factory_settings) {
|
const char *app_template = NULL;
|
||||||
|
|
||||||
|
if (filepath_startup_override != NULL) {
|
||||||
|
/* pass */
|
||||||
|
}
|
||||||
|
else if (app_template_override) {
|
||||||
|
app_template = app_template_override;
|
||||||
|
}
|
||||||
|
else if (!use_factory_settings && U.app_template[0]) {
|
||||||
|
app_template = U.app_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_template != NULL) {
|
||||||
|
BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system));
|
||||||
|
BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert template name into startup file */
|
||||||
|
if (app_template != NULL) {
|
||||||
|
/* note that the path is being set even when 'use_factory_settings == true'
|
||||||
|
* this is done so we can load a templates factory-settings */
|
||||||
|
if (!use_factory_settings) {
|
||||||
|
BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL);
|
||||||
|
if (BLI_access(filepath_startup, R_OK) != 0) {
|
||||||
|
filepath_startup[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filepath_startup[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filepath_startup[0] == '\0') {
|
||||||
|
BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_factory_settings || (filepath_startup[0] != '\0')) {
|
||||||
if (BLI_access(filepath_startup, R_OK) == 0) {
|
if (BLI_access(filepath_startup, R_OK) == 0) {
|
||||||
success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL);
|
success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL);
|
||||||
}
|
}
|
||||||
@@ -716,8 +766,8 @@ int wm_homefile_read(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (success == false && filepath_startup_override && reports) {
|
if (success == false && filepath_startup_override && reports) {
|
||||||
|
/* We can not return from here because wm is already reset */
|
||||||
BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override);
|
BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override);
|
||||||
/*We can not return from here because wm is already reset*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success == false) {
|
if (success == false) {
|
||||||
@@ -733,7 +783,45 @@ int wm_homefile_read(
|
|||||||
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
|
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load template preferences,
|
||||||
|
* unlike regular preferences we only use some of the settings,
|
||||||
|
* see: BKE_blender_userdef_set_app_template */
|
||||||
|
if (app_template_system[0] != '\0') {
|
||||||
|
char temp_path[FILE_MAX];
|
||||||
|
temp_path[0] = '\0';
|
||||||
|
if (!use_factory_settings) {
|
||||||
|
BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL);
|
||||||
|
if (BLI_access(temp_path, R_OK) != 0) {
|
||||||
|
temp_path[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp_path[0] == '\0') {
|
||||||
|
BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDef *userdef_template = NULL;
|
||||||
|
/* just avoids missing file warning */
|
||||||
|
if (BLI_exists(temp_path)) {
|
||||||
|
userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
|
||||||
|
}
|
||||||
|
if (userdef_template == NULL) {
|
||||||
|
/* we need to have preferences load to overwrite preferences from previous template */
|
||||||
|
userdef_template = BKE_blendfile_userdef_read_from_memory(
|
||||||
|
datatoc_startup_blend, datatoc_startup_blend_size, NULL);
|
||||||
|
}
|
||||||
|
if (userdef_template) {
|
||||||
|
BKE_blender_userdef_set_app_template(userdef_template);
|
||||||
|
BKE_blender_userdef_free_data(userdef_template);
|
||||||
|
MEM_freeN(userdef_template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_template_override) {
|
||||||
|
BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template));
|
||||||
|
}
|
||||||
|
|
||||||
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
|
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
|
||||||
* can remove this eventually, only in a 2.53 and older, now its not written */
|
* can remove this eventually, only in a 2.53 and older, now its not written */
|
||||||
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
|
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
|
||||||
@@ -1271,6 +1359,13 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
|
|||||||
char filepath[FILE_MAX];
|
char filepath[FILE_MAX];
|
||||||
int fileflags;
|
int fileflags;
|
||||||
|
|
||||||
|
const char *app_template = U.app_template[0] ? U.app_template : NULL;
|
||||||
|
const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template);
|
||||||
|
if (cfgdir == NULL) {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "Unable to create user config path");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
|
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
|
||||||
|
|
||||||
/* check current window and close it if temp */
|
/* check current window and close it if temp */
|
||||||
@@ -1280,7 +1375,8 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
|
|||||||
/* update keymaps in user preferences */
|
/* update keymaps in user preferences */
|
||||||
WM_keyconfig_update(wm);
|
WM_keyconfig_update(wm);
|
||||||
|
|
||||||
BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
|
BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL);
|
||||||
|
|
||||||
printf("trying to save homefile at %s ", filepath);
|
printf("trying to save homefile at %s ", filepath);
|
||||||
|
|
||||||
ED_editors_flush_edits(C, false);
|
ED_editors_flush_edits(C, false);
|
||||||
@@ -1358,21 +1454,44 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op)
|
|||||||
{
|
{
|
||||||
wmWindowManager *wm = CTX_wm_manager(C);
|
wmWindowManager *wm = CTX_wm_manager(C);
|
||||||
char filepath[FILE_MAX];
|
char filepath[FILE_MAX];
|
||||||
|
const char *cfgdir;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
/* update keymaps in user preferences */
|
/* update keymaps in user preferences */
|
||||||
WM_keyconfig_update(wm);
|
WM_keyconfig_update(wm);
|
||||||
|
|
||||||
BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
|
if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
|
||||||
printf("trying to save userpref at %s ", filepath);
|
BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
|
||||||
|
printf("trying to save userpref at %s ", filepath);
|
||||||
if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) {
|
if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
|
||||||
printf("fail\n");
|
printf("ok\n");
|
||||||
return OPERATOR_CANCELLED;
|
ok = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("fail\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ok\n");
|
if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
|
||||||
|
/* Also save app-template prefs */
|
||||||
|
BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
|
||||||
|
printf("trying to save app-template userpref at %s ", filepath);
|
||||||
|
if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) {
|
||||||
|
printf("fail\n");
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("ok\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (U.app_template[0]) {
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
|
||||||
|
}
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WM_OT_save_userpref(wmOperatorType *ot)
|
void WM_OT_save_userpref(wmOperatorType *ot)
|
||||||
@@ -1433,9 +1552,21 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
|
|||||||
G.fileflags &= ~G_FILE_NO_UI;
|
G.fileflags &= ~G_FILE_NO_UI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wm_homefile_read(C, op->reports, use_factory_settings, filepath)) {
|
char app_template_buf[sizeof(U.app_template)];
|
||||||
/* Load a file but keep the splash open */
|
const char *app_template;
|
||||||
if (!use_factory_settings && RNA_boolean_get(op->ptr, "use_splash")) {
|
PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template");
|
||||||
|
const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash");
|
||||||
|
|
||||||
|
if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
|
||||||
|
RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
|
||||||
|
app_template = app_template_buf;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
app_template = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wm_homefile_read(C, op->reports, use_factory_settings, filepath, app_template)) {
|
||||||
|
if (use_splash) {
|
||||||
WM_init_splash(C);
|
WM_init_splash(C);
|
||||||
}
|
}
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
@@ -1469,17 +1600,26 @@ void WM_OT_read_homefile(wmOperatorType *ot)
|
|||||||
prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", "");
|
prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", "");
|
||||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||||
|
|
||||||
|
prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
|
||||||
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||||
|
|
||||||
/* omit poll to run in background mode */
|
/* omit poll to run in background mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
void WM_OT_read_factory_settings(wmOperatorType *ot)
|
void WM_OT_read_factory_settings(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
ot->name = "Load Factory Settings";
|
ot->name = "Load Factory Settings";
|
||||||
ot->idname = "WM_OT_read_factory_settings";
|
ot->idname = "WM_OT_read_factory_settings";
|
||||||
ot->description = "Load default file and user preferences";
|
ot->description = "Load default file and user preferences";
|
||||||
|
|
||||||
ot->invoke = WM_operator_confirm;
|
ot->invoke = WM_operator_confirm;
|
||||||
ot->exec = wm_homefile_read_exec;
|
ot->exec = wm_homefile_read_exec;
|
||||||
|
|
||||||
|
prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
|
||||||
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||||
|
|
||||||
/* omit poll to run in background mode */
|
/* omit poll to run in background mode */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ void WM_init(bContext *C, int argc, const char **argv)
|
|||||||
wm_init_reports(C);
|
wm_init_reports(C);
|
||||||
|
|
||||||
/* get the default database, plus a wm */
|
/* get the default database, plus a wm */
|
||||||
wm_homefile_read(C, NULL, G.factory_startup, NULL);
|
wm_homefile_read(C, NULL, G.factory_startup, NULL, NULL);
|
||||||
|
|
||||||
|
|
||||||
BLT_lang_set(NULL);
|
BLT_lang_set(NULL);
|
||||||
|
|||||||
@@ -1791,6 +1791,36 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
|
|||||||
ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png,
|
ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png,
|
||||||
datatoc_splash_png_size, IB_rect, NULL, "<splash screen>");
|
datatoc_splash_png_size, IB_rect, NULL, "<splash screen>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* overwrite splash with template image */
|
||||||
|
if (U.app_template[0] != '\0') {
|
||||||
|
ImBuf *ibuf_template = NULL;
|
||||||
|
char splash_filepath[FILE_MAX];
|
||||||
|
char template_directory[FILE_MAX];
|
||||||
|
|
||||||
|
if (BKE_appdir_app_template_id_search(
|
||||||
|
U.app_template,
|
||||||
|
template_directory, sizeof(template_directory)))
|
||||||
|
{
|
||||||
|
BLI_join_dirfile(
|
||||||
|
splash_filepath, sizeof(splash_filepath), template_directory,
|
||||||
|
(U.pixelsize == 2) ? "splash_2x.png" : "splash.png");
|
||||||
|
ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL);
|
||||||
|
if (ibuf_template) {
|
||||||
|
const int x_expect = ibuf_template->x;
|
||||||
|
const int y_expect = 230 * (int)U.pixelsize;
|
||||||
|
/* don't cover the header text */
|
||||||
|
if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) {
|
||||||
|
memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Splash expected %dx%d found %dx%d, ignoring: %s\n",
|
||||||
|
x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath);
|
||||||
|
}
|
||||||
|
IMB_freeImBuf(ibuf_template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
|
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ struct wmOperatorType;
|
|||||||
/* wm_files.c */
|
/* wm_files.c */
|
||||||
void wm_history_file_read(void);
|
void wm_history_file_read(void);
|
||||||
int wm_homefile_read(
|
int wm_homefile_read(
|
||||||
struct bContext *C, struct ReportList *reports,
|
struct bContext *C, struct ReportList *reports, bool use_factory_settings,
|
||||||
bool use_factory_settings, const char *filepath_startup_override);
|
const char *filepath_startup_override, const char *app_template_override);
|
||||||
void wm_file_read_report(bContext *C);
|
void wm_file_read_report(bContext *C);
|
||||||
|
|
||||||
void WM_OT_save_homefile(struct wmOperatorType *ot);
|
void WM_OT_save_homefile(struct wmOperatorType *ot);
|
||||||
|
|||||||
Reference in New Issue
Block a user