Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py2
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/render/render_internal.c85
-rw-r--r--source/blender/editors/space_image/image_ops.c16
-rw-r--r--source/blender/makesdna/DNA_scene_types.h3
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_scene.c5
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/source/pipeline.c26
-rw-r--r--source/blender/windowmanager/WM_api.h3
-rw-r--r--source/blender/windowmanager/WM_types.h1
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c96
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);
+}