diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_render.py | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/render/render_internal.c | 85 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 16 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_windowmanager_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 5 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_pipeline.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/source/pipeline.c | 26 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 96 |
12 files changed, 193 insertions, 50 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 41516a74c9f..f1261534465 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -71,6 +71,8 @@ class RENDER_PT_render(RenderButtonsPanel, Panel): layout.prop(rd, "display_mode", text="Display") + layout.prop(rd, "use_lock_interface") + class RENDER_PT_dimensions(RenderButtonsPanel, Panel): bl_label = "Dimensions" diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 913bdfd1521..29de575e8b8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5554,6 +5554,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->winactive = NULL; wm->initialized = 0; wm->op_undo_depth = 0; + wm->is_interface_locked = 0; } static void lib_link_windowmanager(FileData *fd, Main *main) diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4ff4150e06a..e57474a0443 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -58,6 +58,7 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_multires.h" +#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_sequencer.h" @@ -116,6 +117,7 @@ typedef struct RenderJob { ScrArea *sa; ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; + bool interface_locked; } RenderJob; /* called inside thread! */ @@ -662,6 +664,29 @@ static void render_endjob(void *rjv) BKE_image_release_ibuf(ima, ibuf, lock); } + + /* Finally unlock the user interface (if it was locked). */ + if (rj->interface_locked) { + Scene *scene; + + /* Interface was locked, so window manager couldn't have been changed + * and using one from Global will unlock exactly the same manager as + * was locked before running the job. + */ + WM_set_locked_interface(G.main->wm.first, false); + + /* We've freed all the derived caches before rendering, which is + * effectively the same as if we re-loaded the file. + * + * So let's not try being smart here and just reset all updated + * scene layers and use generic DAG_on_visible_update. + */ + for (scene = G.main->scene.first; scene; scene = scene->id.next) { + scene->lay_updated = 0; + } + + DAG_on_visible_update(G.main, false); + } } /* called by render, check job 'stop' value or the global */ @@ -687,10 +712,14 @@ static int render_break(void *UNUSED(rjv)) /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */ /* maybe need a way to get job send notifer? */ -static void render_drawlock(void *UNUSED(rjv), int lock) +static void render_drawlock(void *rjv, int lock) { - BKE_spacedata_draw_locks(lock); - + RenderJob *rj = rjv; + + /* If interface is locked, renderer callback shall do nothing. */ + if (!rj->interface_locked) { + BKE_spacedata_draw_locks(lock); + } } /* catch esc */ @@ -721,6 +750,36 @@ static void screen_render_cancel(bContext *C, wmOperator *op) WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER); } +static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay) +{ + Object *object; + Scene *sce_iter; + Base *base; + + for (object = bmain->object.first; object; object = object->id.next) { + object->id.flag |= LIB_DOIT; + } + + for (SETLOOPER(scene, sce_iter, base)) { + if ((base->lay & renderlay) == 0) { + continue; + } + + if (RE_allow_render_generic_object(base->object)) { + base->object->id.flag &= ~LIB_DOIT; + } + } + + for (object = bmain->object.first; object; object = object->id.next) { + if ((object->id.flag & LIB_DOIT) == 0) { + continue; + } + object->id.flag &= ~LIB_DOIT; + + BKE_object_free_derived_caches(object); + } +} + /* using context, starts job */ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -832,6 +891,26 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->lay_override |= v3d->localvd->lay; } + /* Lock the user interface depending on render settings. */ + if (scene->r.use_lock_interface) { + int renderlay = rj->lay_override ? rj->lay_override : scene->lay; + + WM_set_locked_interface(CTX_wm_manager(C), true); + + /* Set flag interface need to be unlocked. + * + * This is so because we don't have copy of render settings + * accessible from render job and copy is needed in case + * of non-locked rendering, so we wouldn't try to unlock + * anything if option was initially unset but then was + * enabled during rendering. + */ + rj->interface_locked = true; + + /* Clean memory used by viewport? */ + clean_viewport_memory(rj->main, scene, renderlay); + } + /* setup job */ if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; else name = "Render"; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 38d19923c3d..120e6f52d95 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -363,7 +363,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS; /* properties */ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, @@ -577,7 +577,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING; + ot->flag = OPTYPE_BLOCKING | OPTYPE_LOCK_BYPASS; /* properties */ RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, @@ -640,6 +640,9 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot) /* api callbacks */ ot->invoke = image_view_ndof_invoke; + + /* flags */ + ot->flag = OPTYPE_LOCK_BYPASS; } /********************** view all operator *********************/ @@ -817,6 +820,9 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot) ot->exec = image_view_zoom_in_exec; ot->poll = space_image_main_area_poll; + /* flags */ + ot->flag = OPTYPE_LOCK_BYPASS; + /* properties */ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f); } @@ -859,6 +865,9 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot) ot->exec = image_view_zoom_out_exec; ot->poll = space_image_main_area_poll; + /* flags */ + ot->flag = OPTYPE_LOCK_BYPASS; + /* properties */ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f); } @@ -901,6 +910,9 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot) ot->exec = image_view_zoom_ratio_exec; ot->poll = space_image_main_area_poll; + /* flags */ + ot->flag = OPTYPE_LOCK_BYPASS; + /* properties */ RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX, "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 076dc9c7f59..177b687802d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -432,7 +432,8 @@ typedef struct RenderData { * Render to image editor, fullscreen or to new window. */ short displaymode; - short pad7; + char use_lock_interface; + char pad7; /** * Flags for render settings. Use bit-masking to access the settings. diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index ff43cc31b9a..a17e416b5bd 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -154,6 +154,9 @@ typedef struct wmWindowManager { ListBase timers; /* active timers */ struct wmTimer *autosavetimer; /* timer for auto save */ + + char is_interface_locked; /* indicates whether interface is locked for user interaction */ + char par[7]; } wmWindowManager; /* wmWindowManager.initialized */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 4a544606f09..19d90ab752b 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4539,6 +4539,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Display", "Select where rendered images will be displayed"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_lock_interface", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_lock_interface", 1); + RNA_def_property_ui_text(prop, "Lock Interface", "Lock interface during rendering in favor of giving more memory to the renderer"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "pic"); RNA_def_property_ui_text(prop, "Output Path", diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 32c0a1d8535..bc07f0ce6c0 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -290,5 +290,7 @@ struct Scene *RE_GetScene(struct Render *re); int RE_is_rendering_allowed(struct Scene *scene, struct Object *camera_override, struct ReportList *reports); +bool RE_allow_render_generic_object(struct Object *ob); + #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index ec2644e4d9b..39bc571853a 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1602,6 +1602,18 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node) return false; } +bool RE_allow_render_generic_object(Object *ob) +{ + /* override not showing object when duplis are used with particles */ + if (ob->transflag & OB_DUPLIPARTS) { + /* pass */ /* let particle system(s) handle showing vs. not showing */ + } + else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) { + return false; + } + return true; +} + /* Issue here is that it's possible that object which is used by boolean, * array or shrinkwrap modifiers weren't displayed in the viewport before * rendering. This leads to situations when apply() of this modifiers @@ -1619,18 +1631,6 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node) #define DEPSGRAPH_WORKAROUND_HACK #ifdef DEPSGRAPH_WORKAROUND_HACK -static bool allow_render_mesh_object(Object *ob) -{ - /* override not showing object when duplis are used with particles */ - if (ob->transflag & OB_DUPLIPARTS) { - /* pass */ /* let particle system(s) handle showing vs. not showing */ - } - else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) { - return false; - } - return true; -} - static void tag_dependend_objects_for_render(Scene *scene, int renderlay) { Scene *sce_iter; @@ -1643,7 +1643,7 @@ static void tag_dependend_objects_for_render(Scene *scene, int renderlay) } if (object->type == OB_MESH) { - if (allow_render_mesh_object(object)) { + if (RE_allow_render_generic_object(object)) { ModifierData *md; VirtualModifierData virtualModifierData; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index c13731e2459..a47018e21eb 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -428,6 +428,9 @@ void WM_main_playanim(int argc, const char **argv); /* debugging only, convenience function to write on crash */ bool write_crash_blend(void); + /* Lock the interface for any communication */ +void WM_set_locked_interface(struct wmWindowManager *wm, bool lock); + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 83c17170f9e..8bbdd7bd736 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -134,6 +134,7 @@ struct ImBuf; * and don't make sense to be accessed from the * search menu, even if poll() returns TRUE. * currently only used for the search toolbox */ +#define OPTYPE_LOCK_BYPASS 128 /* Allow operator to run when interface is locked */ /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index be4064a375f..6e2fcf15997 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1488,6 +1488,22 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve } } +/* Check whether operator is allowed to run in case interface is locked, + * If interface is unlocked, will always return truth. + */ +static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + if (wm->is_interface_locked) { + if ((ot->flag & OPTYPE_LOCK_BYPASS) == 0) { + return false; + } + } + + return true; +} + /* bad hacking event system... better restore event type for checking of KM_CLICK for example */ /* XXX modal maps could use different method (ton) */ static void wm_event_modalmap_end(wmEvent *event, bool dbl_click_disabled) @@ -1514,7 +1530,12 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wmOperator *op = handler->op; wmOperatorType *ot = op->type; - if (ot->modal) { + if (!wm_operator_check_locked_interface(C, ot)) { + /* Interface is locked and pperator is not allowed to run, + * nothing to do in this case. + */ + } + else if (ot->modal) { /* we set context to where modal handler came from */ wmWindowManager *wm = CTX_wm_manager(C); ScrArea *area = CTX_wm_area(C); @@ -1587,7 +1608,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0); if (ot) { - retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE); + if (wm_operator_check_locked_interface(C, ot)) { + retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE); + } } } /* Finished and pass through flag as handled */ @@ -1793,7 +1816,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers /* comment this out to flood the console! (if you really want to test) */ !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ; +# define PRINT if (do_debug_handler) printf +#else +# define PRINT(format, ...) #endif + wmWindowManager *wm = CTX_wm_manager(C); wmEventHandler *handler, *nexthandler; int action = WM_HANDLER_CONTINUE; @@ -1829,28 +1856,16 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers wmKeyMap *keymap = WM_keymap_active(wm, handler->keymap); wmKeyMapItem *kmi; -#ifndef NDEBUG - if (do_debug_handler) { - printf("%s: checking '%s' ...", __func__, keymap->idname); - } -#endif + PRINT("%s: checking '%s' ...", __func__, keymap->idname); if (!keymap->poll || keymap->poll(C)) { -#ifndef NDEBUG - if (do_debug_handler) { - printf("pass\n"); - } -#endif + PRINT("pass\n"); for (kmi = keymap->items.first; kmi; kmi = kmi->next) { if (wm_eventmatch(event, kmi)) { -#ifndef NDEBUG - if (do_debug_handler) { - printf("%s: item matched '%s'\n", __func__, kmi->idname); - } -#endif + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); /* weak, but allows interactive callback to not use rawkey */ event->keymap_idname = kmi->idname; @@ -1869,32 +1884,28 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); -#ifndef NDEBUG - if (do_debug_handler) { - printf("%s: un-handled '%s'...", __func__, kmi->idname); - } -#endif + PRINT("%s: un-handled '%s'...", __func__, kmi->idname); } } } } else { -#ifndef NDEBUG - if (do_debug_handler) { - printf("fail\n"); - } -#endif + PRINT("fail\n"); } } else if (handler->ui_handle) { - action |= wm_handler_ui_call(C, handler, event, always_pass); + if (!wm->is_interface_locked) { + action |= wm_handler_ui_call(C, handler, event, always_pass); + } } else if (handler->type == WM_HANDLER_FILESELECT) { - /* screen context changes here */ - action |= wm_handler_fileselect_call(C, handlers, handler, event); + if (!wm->is_interface_locked) { + /* screen context changes here */ + action |= wm_handler_fileselect_call(C, handlers, handler, event); + } } else if (handler->dropboxes) { - if (event->type == EVT_DROP) { + if (!wm->is_interface_locked && event->type == EVT_DROP) { wmDropBox *drop = handler->dropboxes->first; for (; drop; drop = drop->next) { /* other drop custom types allowed */ @@ -1960,6 +1971,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) wm_cursor_arrow_move(CTX_wm_window(C), event); +#undef PRINT + return action; } @@ -3277,3 +3290,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U WM_event_print(&event); #endif } + +void WM_set_locked_interface(wmWindowManager *wm, bool lock) +{ + /* This will prevent events from being handled while interface is locked + * + * Use a "local" flag for now, because currently no other areas could + * benefit of locked interface anyway (aka using G.is_interface_locked + * wouldn't be useful anywhere outside of window manager, so let's not + * pollute global context with such an information for now). + */ + wm->is_interface_locked = lock ? 1 : 0; + + /* This will prevent drawing regions which uses non-threadsafe data. + * Currently it'll be just a 3D viewport. + * + * TODO(sergey): Make it different locked states, so different jobs + * could lock different areas of blender and allow + * interation with others? + */ + BKE_spacedata_draw_locks(lock); +} |