From 02b20948479a4ffcc94fc26479ea873b6c50ec36 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 12:35:00 +1100 Subject: [PATCH 01/14] PyAPI: check modules are registered before unregister Needed since templates may unregister classes. Also replace old modules on reloading. --- release/scripts/startup/bl_operators/__init__.py | 6 +++--- release/scripts/startup/bl_ui/__init__.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py index c28c1461003..1e0dbe6925e 100644 --- a/release/scripts/startup/bl_operators/__init__.py +++ b/release/scripts/startup/bl_operators/__init__.py @@ -21,8 +21,7 @@ # support reloading sub-modules if "bpy" in locals(): from importlib import reload - for val in _modules_loaded: - reload(val) + _modules_loaded[:] = [reload(val) for val in _modules_loaded] del reload _modules = [ @@ -73,4 +72,5 @@ def unregister(): from bpy.utils import unregister_class for mod in reversed(_modules_loaded): for cls in reversed(mod.classes): - unregister_class(cls) + if cls.is_registered: + unregister_class(cls) diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 3e81724c1f9..5b609605cee 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -23,8 +23,7 @@ # support reloading sub-modules if "bpy" in locals(): from importlib import reload - for val in _modules_loaded: - reload(val) + _modules_loaded[:] = [reload(val) for val in _modules_loaded] del reload _modules = [ @@ -149,7 +148,8 @@ def unregister(): from bpy.utils import unregister_class for mod in reversed(_modules_loaded): for cls in reversed(mod.classes): - unregister_class(cls) + if cls.is_registered: + unregister_class(cls) # Define a default UIList, when a list does not need any custom drawing... # Keep in sync with its #defined name in UI_interface.h From d808557d15dbf09401d8ab40c59ce69c89a2d041 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 13:26:34 +1100 Subject: [PATCH 02/14] Fix memory leak re-registering operators Re-registering an operator used by the keymap would lead memory. Reload scripts for eg leaked over ~1600 blocks. --- source/blender/windowmanager/intern/wm_keymap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index e201fa433d4..db5fc23146f 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -121,6 +121,13 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi) if (ot->srna != kmi->ptr->type) { /* matches wm_keymap_item_properties_set but doesnt alloc new ptr */ WM_operator_properties_create_ptr(kmi->ptr, ot); + /* 'kmi->ptr->data' NULL'd above, keep using existing properties. + * Note: the operators property types may have changed, + * we will need a more comprehensive sanitize function to support this properly. + */ + if (kmi->properties) { + kmi->ptr->data = kmi->properties; + } WM_operator_properties_sanitize(kmi->ptr, 1); } } From 4f69dca547cf58f7a27dfa20699115e1171e84f1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 14:29:18 +1100 Subject: [PATCH 03/14] Fix 'bl_app_override' wrapping multiple times. Calling `SomeClass.draw(self, context)` instead of `self.draw()` would try to wrap the argument `self` multiple times, causing an error. --- release/scripts/modules/bl_app_override/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bl_app_override/__init__.py b/release/scripts/modules/bl_app_override/__init__.py index 66857701669..89cc8a0eb28 100644 --- a/release/scripts/modules/bl_app_override/__init__.py +++ b/release/scripts/modules/bl_app_override/__init__.py @@ -147,10 +147,12 @@ def ui_draw_filter_register( return super().operator(*args, **kw) def draw_override(func_orig, self_real, context): - # simple, no wrapping - # return func_orig(self_wrap, context) + cls_real = self_real.__class__ + if cls_real is super: + # simple, no wrapping + return func_orig(self_real, context) - class Wrapper(self_real.__class__): + class Wrapper(cls_real): __slots__ = () def __getattribute__(self, attr): if attr == "layout": From 4c7f4e4662ba9ecddd469d5f12e1b0de17ed553e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 15:07:41 +1100 Subject: [PATCH 04/14] PyAPI: minor path init simplification --- release/scripts/modules/bpy/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 26fdbc8cc56..545b891505f 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -48,11 +48,11 @@ def main(): import sys # Possibly temp. addons path - from os.path import join, dirname, normpath - sys.path.append(normpath(join(dirname(__file__), - "..", "..", "addons", "modules"))) - sys.path.append(join(utils.user_resource('SCRIPTS'), - "addons", "modules")) + from os.path import join, dirname + sys.path.extend([ + join(dirname(dirname(dirname(__file__))), "addons", "modules"), + join(utils.user_resource('SCRIPTS'), "addons", "modules"), + ]) # fake module to allow: # from bpy.types import Panel From 286adfde383cddb9870d53d1895d0fb1617af245 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Mar 2017 09:12:26 +0200 Subject: [PATCH 05/14] Cycles: Bring back preview AA samples when using BPT This was removed in 93426cb. Please be more accurate when changing interface. --- intern/cycles/blender/addon/ui.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6e25e44a5c2..2b50d272be8 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -183,6 +183,8 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): else: sub.label(text="AA Samples:") sub.prop(cscene, "aa_samples", text="Render") + sub.prop(cscene, "preview_aa_samples", text="Preview") + col = split.column() sub = col.column(align=True) sub.label(text="Samples:") From ac43e5cc87a75b99a86d9caf174b9af07421c18b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Mar 2017 10:16:41 +0200 Subject: [PATCH 06/14] Buildbot: Remove global hardcoded NVCC path This was initially needed for heterogeneous setup of two toolkits which we no longer need. --- build_files/buildbot/slave_compile.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 1d42f04f151..c8d69c38644 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -91,7 +91,6 @@ if 'cmake' in builder: elif builder.startswith('win32'): bits = 32 cmake_options.extend(['-G', 'Visual Studio 12 2013']) - cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE:FILEPATH=C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/nvcc.exe') elif builder.startswith('linux'): tokens = builder.split("_") @@ -111,8 +110,6 @@ if 'cmake' in builder: cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64' targets = ['player', 'blender', 'cuda'] - cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda/bin/nvcc') - cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file)) # Prepare CMake options needed to configure cuda binaries compilation. From 15ff75d06b3d9ffe255c391c875cea6cc99d6009 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Mar 2017 10:21:17 +0200 Subject: [PATCH 07/14] Buildbot: Use older NVCC on 32bit linux Newer toolkit has some weird issue with cross0-compiling 32bit kernels from 64bit environment. --- build_files/buildbot/slave_compile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index c8d69c38644..3c59f168356 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -109,6 +109,7 @@ if 'cmake' in builder: chroot_name = 'buildbot_' + deb_name + '_i686' cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64' targets = ['player', 'blender', 'cuda'] + cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-8.0.44/bin/nvcc') cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file)) From b3f9ae01255fc5801055682148ef274027f45006 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Mar 2017 10:46:53 +0200 Subject: [PATCH 08/14] Buildbot: Revert previous change, older toolkit has same exact behavior --- build_files/buildbot/slave_compile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 3c59f168356..c8d69c38644 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -109,7 +109,6 @@ if 'cmake' in builder: chroot_name = 'buildbot_' + deb_name + '_i686' cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64' targets = ['player', 'blender', 'cuda'] - cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-8.0.44/bin/nvcc') cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file)) From df7f6a3e2e91a7ad27f8ca2b2b43a6c51da8c2c9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 19:07:21 +1100 Subject: [PATCH 09/14] Option to load startup file with empty-data Useful for batch conversion and tests. --- source/blender/blenkernel/BKE_blendfile.h | 1 + source/blender/blenkernel/intern/blendfile.c | 26 +++++++++++++++++++ .../blender/windowmanager/intern/wm_files.c | 16 ++++++++++-- .../windowmanager/intern/wm_init_exit.c | 2 +- source/blender/windowmanager/wm_files.h | 3 ++- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 75978120051..ac58451e412 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -50,6 +50,7 @@ bool BKE_blendfile_read_from_memory( bool BKE_blendfile_read_from_memfile( struct bContext *C, struct MemFile *memfile, struct ReportList *reports, int skip_flag); +void BKE_blendfile_read_make_empty(struct bContext *C); struct UserDef *BKE_blendfile_userdef_read( const char *filepath, struct ReportList *reports); diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 6bcd3c8fb65..a521d671ea4 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -426,6 +426,32 @@ bool BKE_blendfile_read_from_memfile( return (bfd != NULL); } +/** + * Utility to make a file 'empty' used for startup to optionally give an empty file. + * Handy for tests. + */ +void BKE_blendfile_read_make_empty(bContext *C) +{ + Main *bmain = CTX_data_main(C); + + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + a = set_listbasepointers(bmain, lbarray); + while (a--) { + id = lbarray[a]->first; + if (id != NULL) { + if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM)) { + continue; + } + while ((id = lbarray[a]->first)) { + BKE_libblock_delete(bmain, id); + } + } + } +} + /* only read the userdef from a .blend */ UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 27395dbaf3e..2e799307cc0 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -643,7 +643,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) * When not-null, this is written into the user preferences. */ int wm_homefile_read( - bContext *C, ReportList *reports, bool use_factory_settings, + bContext *C, ReportList *reports, + bool use_factory_settings, bool use_empty_data, const char *filepath_startup_override, const char *app_template_override) { ListBase wmbase; @@ -779,6 +780,10 @@ int wm_homefile_read( } } + if (use_empty_data) { + BKE_blendfile_read_make_empty(C); + } + /* Load template preferences, * unlike regular preferences we only use some of the settings, * see: BKE_blender_userdef_set_app_template */ @@ -1551,6 +1556,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) const char *app_template; 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"); + const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty"); 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); @@ -1560,7 +1566,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) app_template = NULL; } - if (wm_homefile_read(C, op->reports, use_factory_settings, filepath, app_template)) { + if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) { if (use_splash) { WM_init_splash(C); } @@ -1591,6 +1597,9 @@ void WM_OT_read_homefile(wmOperatorType *ot) "Load user interface setup from the .blend file"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* So the splash can be kept open after loading a file (for templates). */ prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); @@ -1615,6 +1624,9 @@ void WM_OT_read_factory_settings(wmOperatorType *ot) prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* omit poll to run in background mode */ } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 5483cf25e40..9bafe72d805 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -192,7 +192,7 @@ void WM_init(bContext *C, int argc, const char **argv) wm_init_reports(C); /* get the default database, plus a wm */ - wm_homefile_read(C, NULL, G.factory_startup, NULL, NULL); + wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL); BLT_lang_set(NULL); diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 15a94d2da70..9a1518e15b0 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -36,7 +36,8 @@ struct wmOperatorType; /* wm_files.c */ void wm_history_file_read(void); int wm_homefile_read( - struct bContext *C, struct ReportList *reports, bool use_factory_settings, + struct bContext *C, struct ReportList *reports, + bool use_factory_settings, bool use_empty_data, const char *filepath_startup_override, const char *app_template_override); void wm_file_read_report(bContext *C); From 6332e0e1f7499755cfd4caa5a67066daf46d8b83 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 19:18:09 +1100 Subject: [PATCH 10/14] Use 'empty' option for clearing factory settings --- tests/python/batch_import.py | 35 +++++++++++--------------------- tests/python/bl_run_operators.py | 12 ++--------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/tests/python/batch_import.py b/tests/python/batch_import.py index 8fc679a7c15..bbe3a70327f 100644 --- a/tests/python/batch_import.py +++ b/tests/python/batch_import.py @@ -48,29 +48,17 @@ import os import sys -def clear_scene(): - import bpy - unique_obs = set() - for scene in bpy.data.scenes: - for obj in scene.objects[:]: - scene.objects.unlink(obj) - unique_obs.add(obj) - - # remove obdata, for now only worry about the startup scene - for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras): - for id_data in bpy_data_iter: - bpy_data_iter.remove(id_data) - - -def batch_import(operator="", - path="", - save_path="", - match="", - start=0, - end=sys.maxsize, - ): +def batch_import( + operator="", + path="", + save_path="", + match="", + start=0, + end=sys.maxsize, +): import addon_utils _reset_all = addon_utils.reset_all # XXX, hack + _disable_all = addon_utils.disable_all # XXX, hack import fnmatch @@ -116,11 +104,12 @@ def batch_import(operator="", # hack so loading the new file doesn't undo our loaded addons addon_utils.reset_all = lambda: None # XXX, hack + addon_utils.disable_all = lambda: None # XXX, hack - bpy.ops.wm.read_factory_settings() + bpy.ops.wm.read_factory_settings(use_empty=True) addon_utils.reset_all = _reset_all # XXX, hack - clear_scene() + addon_utils.disable_all = _disable_all # XXX, hack result = op(filepath=f) diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py index 7e92b424faa..7d5f4127378 100644 --- a/tests/python/bl_run_operators.py +++ b/tests/python/bl_run_operators.py @@ -65,6 +65,7 @@ op_blacklist = ( "wm.blenderplayer_start", "wm.recover_auto_save", "wm.quit_blender", + "wm.window_close", "wm.url_open", "wm.doc_view", "wm.doc_edit", @@ -308,16 +309,7 @@ def run_ops(operators, setup_func=None, reset=True): # contexts def ctx_clear_scene(): # copied from batch_import.py - unique_obs = set() - for scene in bpy.data.scenes: - for obj in scene.objects[:]: - scene.objects.unlink(obj) - unique_obs.add(obj) - - # remove obdata, for now only worry about the startup scene - for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras): - for id_data in bpy_data_iter: - bpy_data_iter.remove(id_data) + bpy.ops.wm.read_factory_settings(use_empty=True) def ctx_editmode_mesh(): From cb6ec44fc79df95bd94d313a01b63c60017886d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 19:19:25 +1100 Subject: [PATCH 11/14] Fix missing NULL check in gpencil poll Also de-duplicate poll functions --- .../editors/gpencil/gpencil_interpolate.c | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 297058168a0..d2360fea672 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -86,13 +86,14 @@ /* Core/Shared Utilities */ /* Poll callback for interpolation operators */ -static int gpencil_interpolate_poll(bContext *C) +static int gpencil_view3d_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only 3D view */ - if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) { + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacetype != SPACE_VIEW3D) { return 0; } @@ -673,7 +674,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) ot->invoke = gpencil_interpolate_invoke; ot->modal = gpencil_interpolate_modal; ot->cancel = gpencil_interpolate_cancel; - ot->poll = gpencil_interpolate_poll; + ot->poll = gpencil_view3d_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; @@ -1017,7 +1018,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) /* api callbacks */ ot->exec = gpencil_interpolate_seq_exec; - ot->poll = gpencil_interpolate_poll; + ot->poll = gpencil_view3d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1025,24 +1026,14 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) /* ******************** Remove Breakdowns ************************ */ -/* Same as gpencil_interpolate_poll(), - * except we ALSO need to have an active frame that is a breakdown - */ static int gpencil_interpolate_reverse_poll(bContext *C) { - bGPdata *gpd = CTX_data_gpencil_data(C); + if (!gpencil_view3d_poll(C)) { + return 0; + } + bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - - /* only 3D view */ - if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) { - return 0; - } - - /* need data to interpolate */ - if (ELEM(NULL, gpd, gpl)) { - return 0; - } - + /* need to be on a breakdown frame */ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) { CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown"); From a7ca9918414f87aa55aa1eaeba66c5728f45117f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 19:25:34 +1100 Subject: [PATCH 12/14] Fix crash closing window in background mode --- source/blender/windowmanager/intern/wm_window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 40baab8809c..51f501e0486 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -312,7 +312,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) if (tmpwin == NULL) do_exit = 1; - if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) { + if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { if (do_exit) { if (!GHOST_confirmQuit(win->ghostwin)) return; From dd662c74ae9533dae02b3e9b01417b71a7f3ff26 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 19:32:57 +1100 Subject: [PATCH 13/14] Fix skin mark operator Accessed custom-data layer offset before creating. --- source/blender/editors/object/object_modifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index d601f5c3b14..06d306ded42 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1484,7 +1484,6 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; - const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); BMVert *bm_vert; BMIter bm_iter; GSet *visited; @@ -1493,6 +1492,8 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_skin_customdata(ob->data); + const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); + BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) From c2d3bb709044b7a2730b9fb5005657f38eaff6f2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 29 Mar 2017 20:10:46 +1100 Subject: [PATCH 14/14] Remove non-bmesh case from test --- tests/python/bl_mesh_modifiers.py | 75 ++++++++++--------------------- 1 file changed, 24 insertions(+), 51 deletions(-) diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py index 526a54a49a2..bff2c31984c 100644 --- a/tests/python/bl_mesh_modifiers.py +++ b/tests/python/bl_mesh_modifiers.py @@ -31,7 +31,6 @@ import math USE_QUICK_RENDER = False -IS_BMESH = hasattr(__import__("bpy").types, "LoopColors") # ----------------------------------------------------------------------------- # utility functions @@ -203,13 +202,8 @@ def defaults_object(obj): mesh.show_normal_vertex = True - # lame! - if IS_BMESH: - for poly in mesh.polygons: - poly.use_smooth = True - else: - for face in mesh.faces: - face.use_smooth = True + for poly in mesh.polygons: + poly.use_smooth = True def defaults_modifier(mod): @@ -220,16 +214,14 @@ def defaults_modifier(mod): # ----------------------------------------------------------------------------- # models (utils) +def mesh_bmesh_poly_elems(poly, elems): + vert_start = poly.loop_start + vert_total = poly.loop_total + return elems[vert_start:vert_start + vert_total] -if IS_BMESH: - def mesh_bmesh_poly_elems(poly, elems): - vert_start = poly.loop_start - vert_total = poly.loop_total - return elems[vert_start:vert_start + vert_total] - - def mesh_bmesh_poly_vertices(poly): - return [loop.vertex_index - for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)] +def mesh_bmesh_poly_vertices(poly): + return [loop.vertex_index + for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)] def mesh_bounds(mesh): @@ -258,21 +250,14 @@ def mesh_uv_add(obj): uv_lay = obj.data.uv_textures.new() - if IS_BMESH: - # XXX, odd that we need to do this. until UV's and texface - # are separated we will need to keep it - uv_loops = obj.data.uv_layers[-1] - uv_list = uv_loops.data[:] - for poly in obj.data.polygons: - poly_uvs = mesh_bmesh_poly_elems(poly, uv_list) - for i, c in enumerate(poly_uvs): - c.uv = uvs[i % 4] - else: - for uv in uv_lay.data: - uv.uv1 = uvs[0] - uv.uv2 = uvs[1] - uv.uv3 = uvs[2] - uv.uv4 = uvs[3] + # XXX, odd that we need to do this. until UV's and texface + # are separated we will need to keep it + uv_loops = obj.data.uv_layers[-1] + uv_list = uv_loops.data[:] + for poly in obj.data.polygons: + poly_uvs = mesh_bmesh_poly_elems(poly, uv_list) + for i, c in enumerate(poly_uvs): + c.uv = uvs[i % 4] return uv_lay @@ -296,21 +281,12 @@ def mesh_vcol_add(obj, mode=0): mesh = obj.data - if IS_BMESH: - col_list = vcol_lay.data[:] - for poly in mesh.polygons: - face_verts = mesh_bmesh_poly_vertices(poly) - poly_cols = mesh_bmesh_poly_elems(poly, col_list) - for i, c in enumerate(poly_cols): - c.color = colors_get(face_verts[i]) - else: - for i, col in enumerate(vcol_lay.data): - face_verts = mesh.faces[i].vertices - col.color1 = colors_get(face_verts[0]) - col.color2 = colors_get(face_verts[1]) - col.color3 = colors_get(face_verts[2]) - if len(face_verts) == 4: - col.color4 = colors_get(face_verts[3]) + col_list = vcol_lay.data[:] + for poly in mesh.polygons: + face_verts = mesh_bmesh_poly_vertices(poly) + poly_cols = mesh_bmesh_poly_elems(poly, col_list) + for i, c in enumerate(poly_cols): + c.color = colors_get(face_verts[i]) return vcol_lay @@ -470,10 +446,7 @@ def modifier_build_add(scene, obj): defaults_modifier(mod) # ensure we display some faces - if IS_BMESH: - totface = len(obj.data.polygons) - else: - totface = len(obj.data.faces) + totface = len(obj.data.polygons) mod.frame_start = totface // 2 mod.frame_duration = totface