Partial fix for T37604: Deadlock when stopping rendered viewport (Blender Internal)
[blender.git] / source / blender / editors / space_view3d / space_view3d.c
index 236cbb86724294280fe4859cfcd9f86c8993b725..03b89972e559d52c39aaad429bd127728f4495b6 100644 (file)
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <stdio.h>
 
+#include "DNA_material_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
-#include "BLI_rand.h"
 #include "BLI_utildefines.h"
 
-#include "BKE_object.h"
 #include "BKE_context.h"
+#include "BKE_icons.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
 #include "BKE_screen.h"
 
+#include "ED_render.h"
 #include "ED_space_api.h"
 #include "ED_screen.h"
 #include "ED_object.h"
 
-#include "BIF_gl.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
 
+#include "BIF_gl.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
 #include "RE_engine.h"
+#include "RE_pipeline.h"
 
 #include "RNA_access.h"
 
 #include "UI_resources.h"
 
+#ifdef WITH_PYTHON
+#  include "BPY_extern.h"
+#endif
+
 #include "view3d_intern.h"  /* own include */
 
 /* ******************** manage regions ********************* */
@@ -117,7 +128,7 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
                
                BLI_insertlinkafter(&sa->regionbase, arhead, artool);
                artool->regiontype = RGN_TYPE_TOOLS;
-               artool->alignment = RGN_ALIGN_LEFT; //RGN_OVERLAP_LEFT;
+               artool->alignment = RGN_ALIGN_LEFT;
                artool->flag = RGN_FLAG_HIDDEN;
        }
 
@@ -143,7 +154,7 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
        if (rv3d == NULL) {
                ScrArea *sa = CTX_wm_area(C);
                if (sa && sa->spacetype == SPACE_VIEW3D) {
-                       ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+                       ARegion *ar = BKE_area_find_region_active_win(sa);
                        if (ar) {
                                rv3d = ar->regiondata;
                        }
@@ -154,12 +165,12 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
 
 /* ideally would return an rv3d but in some cases the region is needed too
  * so return that, the caller can then access the ar->regiondata */
-int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
+bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
 {
        ScrArea *sa = CTX_wm_area(C);
 
-       *v3d_r = NULL;
-       *ar_r = NULL;
+       *r_v3d = NULL;
+       *r_ar = NULL;
 
        if (sa && sa->spacetype == SPACE_VIEW3D) {
                ARegion *ar = CTX_wm_region(C);
@@ -168,9 +179,9 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
                if (ar) {
                        RegionView3D *rv3d = ar->regiondata;
                        if (rv3d && rv3d->viewlock == 0) {
-                               *v3d_r = v3d;
-                               *ar_r = ar;
-                               return 1;
+                               *r_v3d = v3d;
+                               *r_ar = ar;
+                               return true;
                        }
                        else {
                                ARegion *ar_unlock_user = NULL;
@@ -185,27 +196,27 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
                                                                ar_unlock_user = ar;
                                                                break;
                                                        }
-                                               } 
+                                               }
                                        }
                                }
 
                                /* camera/perspective view get priority when the active region is locked */
                                if (ar_unlock_user) {
-                                       *v3d_r = v3d;
-                                       *ar_r = ar_unlock_user;
-                                       return 1;
+                                       *r_v3d = v3d;
+                                       *r_ar = ar_unlock_user;
+                                       return true;
                                }
 
                                if (ar_unlock) {
-                                       *v3d_r = v3d;
-                                       *ar_r = ar_unlock;
-                                       return 1;
+                                       *r_v3d = v3d;
+                                       *r_ar = ar_unlock;
+                                       return true;
                                }
                        }
                }
        }
 
-       return 0;
+       return false;
 }
 
 /* Most of the time this isn't needed since you could assume the view matrix was
@@ -222,8 +233,8 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
 {
        /* local viewmat and persmat, to calculate projections */
-       mult_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
-       mult_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
+       mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
+       mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
 
        /* initializes object space clipping, speeds up clip tests */
        ED_view3d_clipping_local(rv3d, ob->obmat);
@@ -239,6 +250,57 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
        glMultMatrixf(ob->obmat);
 }
 
+#ifdef DEBUG
+/* ensure we correctly initialize */
+void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
+{
+       zero_m4(rv3d->viewmatob);
+       zero_m4(rv3d->persmatob);
+}
+
+void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
+{
+       BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
+       BLI_ASSERT_ZERO_M4(rv3d->persmatob);
+}
+#endif
+
+static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
+{
+       RegionView3D *rv3d = ar->regiondata;
+
+       if (rv3d->render_engine) {
+#ifdef WITH_PYTHON
+               BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+               WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+
+#ifdef WITH_PYTHON
+               BPy_END_ALLOW_THREADS;
+#endif
+
+               if (rv3d->render_engine->re)
+                       RE_Database_Free(rv3d->render_engine->re);
+               RE_engine_free(rv3d->render_engine);
+               rv3d->render_engine = NULL;
+       }
+}
+
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+{
+       wmWindowManager *wm = bmain->wm.first;
+
+       if (v3d->drawtype != OB_RENDER) {
+               ARegion *ar;
+
+               for (ar = sa->regionbase.first; ar; ar = ar->next) {
+                       if (ar->regiondata)
+                               view3d_stop_render_preview(wm, ar);
+               }
+       }
+}
+
 /* ******************** default callbacks for view3d space ***************** */
 
 static SpaceLink *view3d_new(const bContext *C)
@@ -261,14 +323,11 @@ static SpaceLink *view3d_new(const bContext *C)
        v3d->gridlines = 16;
        v3d->gridsubdiv = 10;
        v3d->drawtype = OB_SOLID;
+
+       v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
        
-       v3d->gridflag |= V3D_SHOW_X;
-       v3d->gridflag |= V3D_SHOW_Y;
-       v3d->gridflag |= V3D_SHOW_FLOOR;
-       v3d->gridflag &= ~V3D_SHOW_Z;
-       
-       v3d->flag |= V3D_SELECT_OUTLINE;
-       v3d->flag2 |= V3D_SHOW_RECONSTRUCTION;
+       v3d->flag = V3D_SELECT_OUTLINE;
+       v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
        
        v3d->lens = 35.0f;
        v3d->near = 0.01f;
@@ -338,11 +397,19 @@ static void view3d_free(SpaceLink *sl)
        if (vd->localvd) MEM_freeN(vd->localvd);
        
        if (vd->properties_storage) MEM_freeN(vd->properties_storage);
+       
+       /* matcap material, its preview rect gets freed via icons */
+       if (vd->defmaterial) {
+               if (vd->defmaterial->gpumaterial.first)
+                       GPU_material_free(vd->defmaterial);
+               BKE_previewimg_free(&vd->defmaterial->preview);
+               MEM_freeN(vd->defmaterial);
+       }
 }
 
 
 /* spacetype; init callback */
-static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
 {
 
 }
@@ -356,11 +423,10 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
        
 // XXX BIF_view3d_previewrender_free(v3do);
        
-       if (v3do->localvd) {
-               v3do->localvd = NULL;
-               v3do->properties_storage = NULL;
-               v3do->lay = v3dn->localvd->lay;
-               v3do->lay &= 0xFFFFFF;
+       if (v3dn->localvd) {
+               v3dn->localvd = NULL;
+               v3dn->properties_storage = NULL;
+               v3dn->lay = v3do->localvd->lay & 0xFFFFFF;
        }
 
        if (v3dn->drawtype == OB_RENDER)
@@ -368,6 +434,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
        
        /* copy or clear inside new stuff */
 
+       v3dn->defmaterial = NULL;
+       
        BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
 
        v3dn->properties_storage = NULL;
@@ -459,7 +527,19 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
        
 }
 
-static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
+{
+       RegionView3D *rv3d = ar->regiondata;
+
+       view3d_stop_render_preview(wm, ar);
+
+       if (rv3d->gpuoffscreen) {
+               GPU_offscreen_free(rv3d->gpuoffscreen);
+               rv3d->gpuoffscreen = NULL;
+       }
+}
+
+static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
 {
        if (drag->type == WM_DRAG_ID) {
                ID *id = (ID *)drag->poin;
@@ -469,7 +549,17 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSE
        return 0;
 }
 
-static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+{
+       if (drag->type == WM_DRAG_ID) {
+               ID *id = (ID *)drag->poin;
+               if (GS(id->name) == ID_GR)
+                       return 1;
+       }
+       return 0;
+}
+
+static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
 {
        if (drag->type == WM_DRAG_ID) {
                ID *id = (ID *)drag->poin;
@@ -479,7 +569,7 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
        return 0;
 }
 
-static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
 {
        if (drag->type == WM_DRAG_ID) {
                ID *id = (ID *)drag->poin;
@@ -493,34 +583,50 @@ static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
        return 0;
 }
 
-
-static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
 {
-       if (ED_view3d_give_base_under_cursor(C, event->mval) ) {
-               return 0;
+       if (event->ctrl)
+               return false;
+
+       if (!ED_view3d_give_base_under_cursor(C, event->mval)) {
+               return view3d_ima_drop_poll(C, drag, event);
        }
-       return view3d_ima_drop_poll(C, drag, event);
+       return 0;
 }
 
-static int view3d_ima_ob_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
 {
-       if (ED_view3d_give_base_under_cursor(C, event->mval) ) {
+       Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+
+       /* either holding and ctrl and no object, or dropping to empty */
+       if ((event->ctrl && !base) || (base && base->object->type == OB_EMPTY))
+               return view3d_ima_drop_poll(C, drag, event);
+
+       return 0;
+}
+
+static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+{
+       Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+
+       if (base && base->object->type == OB_MESH)
                return view3d_ima_drop_poll(C, drag, event);
-       }
        return 0;
 }
 
 static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
 {
        ID *id = (ID *)drag->poin;
-       PointerRNA ptr;
 
-       /* need to put name in sub-operator in macro */
-       ptr = RNA_pointer_get(drop->ptr, "OBJECT_OT_add_named");
-       if (ptr.data)
-               RNA_string_set(&ptr, "name", id->name + 2);
-       else
-               RNA_string_set(drop->ptr, "name", id->name + 2);
+       RNA_string_set(drop->ptr, "name", id->name + 2);
+}
+
+static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+{
+       ID *id = (ID *)drag->poin;
+       
+       drop->opcontext = WM_OP_EXEC_DEFAULT;
+       RNA_string_set(drop->ptr, "name", id->name + 2);
 }
 
 static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop)
@@ -546,10 +652,12 @@ static void view3d_dropboxes(void)
 {
        ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW);
        
-       WM_dropbox_add(lb, "OBJECT_OT_add_named_cursor", view3d_ob_drop_poll, view3d_ob_drop_copy);
+       WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy);
        WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy);
-       WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_ob_drop_poll, view3d_id_path_drop_copy);
+       WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
+       WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
        WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
+       WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
 }
 
 
@@ -574,6 +682,13 @@ static void view3d_main_area_free(ARegion *ar)
                        if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths);
                        MEM_freeN(rv3d->depths);
                }
+               if (rv3d->sms) {
+                       MEM_freeN(rv3d->sms);
+               }
+               if (rv3d->gpuoffscreen) {
+                       GPU_offscreen_free(rv3d->gpuoffscreen);
+               }
+
                MEM_freeN(rv3d);
                ar->regiondata = NULL;
        }
@@ -592,6 +707,7 @@ static void *view3d_main_area_duplicate(void *poin)
                        new->clipbb = MEM_dupallocN(rv3d->clipbb);
                
                new->depths = NULL;
+               new->gpuoffscreen = NULL;
                new->ri = NULL;
                new->render_engine = NULL;
                new->gpd = NULL;
@@ -633,10 +749,11 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
        }
 }
 
-static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
 {
-       bScreen *sc;
-
+       Scene *scene = sc->scene;
+       View3D *v3d = sa->spacedata.first;
+       
        /* context changes */
        switch (wmn->category) {
                case NC_ANIMATION:
@@ -659,7 +776,8 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                case NC_SCENE:
                        switch (wmn->data) {
                                case ND_LAYER_CONTENT:
-                                       view3d_recalc_used_layers(ar, wmn, wmn->reference);
+                                       if (wmn->reference)
+                                               view3d_recalc_used_layers(ar, wmn, wmn->reference);
                                        ED_region_tag_redraw(ar);
                                        break;
                                case ND_FRAME:
@@ -669,6 +787,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_OB_VISIBLE:
                                case ND_LAYER:
                                case ND_RENDER_OPTIONS:
+                               case ND_MARKERS:
                                case ND_MODE:
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -702,6 +821,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                case NC_GEOM:
                        switch (wmn->data) {
                                case ND_DATA:
+                               case ND_VERTEX_GROUP:
                                case ND_SELECT:
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -719,10 +839,21 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                case NC_BRUSH:
                        if (wmn->action == NA_EDITED)
                                ED_region_tag_redraw_overlay(ar);
-                       break;                  
+                       break;
                case NC_MATERIAL:
                        switch (wmn->data) {
+                               case ND_SHADING:
+                               case ND_NODES:
+                                       if ((v3d->drawtype == OB_MATERIAL) ||
+                                           (v3d->drawtype == OB_TEXTURE &&
+                                                (scene->gm.matmode == GAME_MAT_GLSL ||
+                                                 BKE_scene_use_new_shading_nodes(scene))))
+                                       {
+                                               ED_region_tag_redraw(ar);
+                                       }
+                                       break;
                                case ND_SHADING_DRAW:
+                               case ND_SHADING_LINKS:
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
@@ -732,28 +863,28 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_WORLD_DRAW:
                                        /* handled by space_view3d_listener() for v3d access */
                                        break;
-                               case ND_WORLD_STARS:
-                               {
-                                       RegionView3D *rv3d = ar->regiondata;
-                                       if (rv3d->persp == RV3D_CAMOB) {
-                                               ED_region_tag_redraw(ar);
-                                       }
-                               }
                        }
                        break;
                case NC_LAMP:
                        switch (wmn->data) {
+                               case ND_LIGHTING:
+                                       if ((v3d->drawtype == OB_MATERIAL) ||
+                                           (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)))
+                                       {
+                                               ED_region_tag_redraw(ar);
+                                       }
+                                       break;
                                case ND_LIGHTING_DRAW:
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
                        break;
-               case NC_IMAGE:  
+               case NC_IMAGE:
                        /* this could be more fine grained checks if we had
                         * more context than just the region */
                        ED_region_tag_redraw(ar);
                        break;
-               case NC_TEXTURE:        
+               case NC_TEXTURE:
                        /* same as above */
                        ED_region_tag_redraw(ar);
                        break;
@@ -785,8 +916,10 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_SCREENSET:
                                        /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
                                        /* updates used layers only for View3D in active screen */
-                                       sc = wmn->reference;
-                                       view3d_recalc_used_layers(ar, wmn, sc->scene);
+                                       if (wmn->reference) {
+                                               bScreen *sc_ref = wmn->reference;
+                                               view3d_recalc_used_layers(ar, wmn, sc_ref->scene);
+                                       }
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
@@ -827,7 +960,7 @@ static void view3d_header_area_draw(const bContext *C, ARegion *ar)
        ED_region_header(C, ar);
 }
 
-static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -868,7 +1001,7 @@ static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
        ED_region_panels(C, ar, 1, NULL, -1);
 }
 
-static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -882,7 +1015,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_KEYFRAME:
                                        if (wmn->action == NA_EDITED)
                                                ED_region_tag_redraw(ar);
-                                       break;  
+                                       break;
                        }
                        break;
                case NC_SCENE:
@@ -920,6 +1053,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
                case NC_GEOM:
                        switch (wmn->data) {
                                case ND_DATA:
+                               case ND_VERTEX_GROUP:
                                case ND_SELECT:
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -945,7 +1079,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
                                ED_region_tag_redraw(ar);
                        break;
                case NC_GPENCIL:
-                       if (wmn->data == ND_DATA)
+                       if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
                                ED_region_tag_redraw(ar);
                        break;
        }
@@ -967,7 +1101,7 @@ static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
        ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
 }
 
-static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -987,7 +1121,7 @@ static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
 }
 
 /*area (not region) level listener*/
-static void space_view3d_listener(ScrArea *sa, struct wmNotifier *wmn)
+static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn)
 {
        View3D *v3d = sa->spacedata.first;
 
@@ -1043,17 +1177,17 @@ const char *view3d_context_dir[] = {
 
 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
 {
-       View3D *v3d = CTX_wm_view3d(C);
-       Scene *scene = CTX_data_scene(C);
-       Base *base;
        /* fallback to the scene layer, allows duplicate and other object operators to run outside the 3d view */
-       unsigned int lay = v3d ? v3d->lay : scene->lay;
 
        if (CTX_data_dir(member)) {
                CTX_data_dir_set(result, view3d_context_dir);
        }
        else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
-               int selected_objects = CTX_data_equals(member, "selected_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selected_objects = CTX_data_equals(member, "selected_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if ((base->flag & SELECT) && (base->lay & lay)) {
@@ -1069,7 +1203,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
-               int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if ((base->flag & SELECT) && (base->lay & lay)) {
@@ -1087,7 +1225,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
-               int visible_objects = CTX_data_equals(member, "visible_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool visible_objects = CTX_data_equals(member, "visible_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if (base->lay & lay) {
@@ -1103,7 +1245,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
-               int selectable_objects = CTX_data_equals(member, "selectable_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if (base->lay & lay) {
@@ -1119,16 +1265,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "active_base")) {
-               if (scene->basact && (scene->basact->lay & lay))
-                       if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0)
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               if (scene->basact && (scene->basact->lay & lay)) {
+                       Object *ob = scene->basact->object;
+                       /* if hidden but in edit mode, we still display, can happen with animation */
+                       if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
                                CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
+               }
                
                return 1;
        }
        else if (CTX_data_equals(member, "active_object")) {
-               if (scene->basact && (scene->basact->lay & lay))
-                       if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0)
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               if (scene->basact && (scene->basact->lay & lay)) {
+                       Object *ob = scene->basact->object;
+                       if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
                                CTX_data_id_pointer_set(result, &scene->basact->object->id);
+               }
                
                return 1;
        }
@@ -1165,6 +1322,7 @@ void ED_spacetype_view3d(void)
        art->keymapflag = ED_KEYMAP_GPENCIL;
        art->draw = view3d_main_area_draw;
        art->init = view3d_main_area_init;
+       art->exit = view3d_main_area_exit;
        art->free = view3d_main_area_free;
        art->duplicate = view3d_main_area_duplicate;
        art->listener = view3d_main_area_listener;