Fix #35404: crash in file save with python code that accesses mesh from panel.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 18 May 2013 10:24:34 +0000 (10:24 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Sat, 18 May 2013 10:24:34 +0000 (10:24 +0000)
On file save the mesh gets loads from the editmesh but the derived mesh caches
wer not cleared. This usually happens through the depsgraph but it needs to be
done manually here. Most changes are some refactoring to deduplicate derived
mesh freeing code.

source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/paint.c
source/blender/editors/mesh/editmesh_utils.c
source/blender/editors/sculpt_paint/sculpt.c

index 8870355a9198969e44678dc461bca531c0a119ff..db93e4f419ea0f9251c46d5c718bd8d5d55efceb 100644 (file)
@@ -66,7 +66,7 @@ void BKE_object_free_bulletsoftbody(struct Object *ob);
 void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
 
 void BKE_object_free(struct Object *ob);
-void BKE_object_free_display(struct Object *ob);
+void BKE_object_free_derived_caches(struct Object *ob);
 
 bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type);
 
index 3dda6933eab1d67e3999fecd4c0d1e50bd8b73d8..02de0ce1d401264ae9c54f0e9788f2576b910384 100644 (file)
@@ -2163,38 +2163,6 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
                MEM_freeN(deformedVerts);
 }
 
-static void clear_mesh_caches(Object *ob)
-{
-       Mesh *me = ob->data;
-
-       /* also serves as signal to remake texspace */
-       if (ob->bb) {
-               MEM_freeN(ob->bb);
-               ob->bb = NULL;
-       }
-       if (me->bb) {
-               MEM_freeN(me->bb);
-               me->bb = NULL;
-       }
-
-       BKE_displist_free(&ob->disp);
-
-       if (ob->derivedFinal) {
-               ob->derivedFinal->needsFree = 1;
-               ob->derivedFinal->release(ob->derivedFinal);
-               ob->derivedFinal = NULL;
-       }
-       if (ob->derivedDeform) {
-               ob->derivedDeform->needsFree = 1;
-               ob->derivedDeform->release(ob->derivedDeform);
-               ob->derivedDeform = NULL;
-       }
-
-       if (ob->sculpt) {
-               BKE_object_sculpt_modifiers_changed(ob);
-       }
-}
-
 static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
                             int build_shapekey_layers)
 {
@@ -2205,7 +2173,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
 
        BLI_assert(ob->type == OB_MESH);
 
-       clear_mesh_caches(ob);
+       BKE_object_free_derived_caches(ob);
+       BKE_object_sculpt_modifiers_changed(ob);
 
        mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
                            &ob->derivedFinal, 0, 1,
@@ -2226,7 +2195,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
 
 static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
 {
-       clear_mesh_caches(obedit);
+       BKE_object_free_derived_caches(obedit);
+       BKE_object_sculpt_modifiers_changed(obedit);
 
        if (em->derivedFinal) {
                if (em->derivedFinal != em->derivedCage) {
index 86832a72b90b9fd2ba3b919480904b7e8be6b8b0..03891f0fed34d59acf8290266ef45549164bd437 100644 (file)
@@ -1511,7 +1511,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime)
                if ((all_layer & layer) == 0) { // XXX && (ob != obedit)) {
                        /* but existing displaylists or derivedmesh should be freed */
                        if (ob->recalc & OB_RECALC_DATA)
-                               BKE_object_free_display(ob);
+                               BKE_object_free_derived_caches(ob);
                        
                        ob->recalc &= ~OB_RECALC_ALL;
                }
index c1f1ca0bbaa6b424097ca2b1f03aeb8eb8b40f3d..7bd117ef7ce24ec81913bf0dcfb4864e258e0b03 100644 (file)
@@ -373,11 +373,8 @@ void multires_mark_as_modified(Object *ob, MultiresModifiedFlags flags)
 void multires_force_update(Object *ob)
 {
        if (ob) {
-               if (ob->derivedFinal) {
-                       ob->derivedFinal->needsFree = 1;
-                       ob->derivedFinal->release(ob->derivedFinal);
-                       ob->derivedFinal = NULL;
-               }
+               BKE_object_free_derived_caches(ob);
+
                if (ob->sculpt && ob->sculpt->pbvh) {
                        BKE_pbvh_free(ob->sculpt->pbvh);
                        ob->sculpt->pbvh = NULL;
index 741c4f5429e9d864300ba6db29d502e8c0323e6f..3779aa8cd887fbce2f154f11a2b04aead13e2a42 100644 (file)
@@ -241,20 +241,34 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
        /* TODO: smoke?, cloth? */
 }
 
-/* here we will collect all local displist stuff */
-/* also (ab)used in depsgraph */
-void BKE_object_free_display(Object *ob)
+/* free data derived from mesh, called when mesh changes or is freed */
+void BKE_object_free_derived_caches(Object *ob)
 {
-       if (ob->derivedDeform) {
-               ob->derivedDeform->needsFree = 1;
-               ob->derivedDeform->release(ob->derivedDeform);
-               ob->derivedDeform = NULL;
+       /* also serves as signal to remake texspace */
+       if (ob->type == OB_MESH) {
+               Mesh *me = ob->data;
+
+               if (me->bb) {
+                       MEM_freeN(me->bb);
+                       me->bb = NULL;
+               }
+       }
+
+       if (ob->bb) {
+               MEM_freeN(ob->bb);
+               ob->bb = NULL;
        }
+
        if (ob->derivedFinal) {
                ob->derivedFinal->needsFree = 1;
                ob->derivedFinal->release(ob->derivedFinal);
                ob->derivedFinal = NULL;
        }
+       if (ob->derivedDeform) {
+               ob->derivedDeform->needsFree = 1;
+               ob->derivedDeform->release(ob->derivedDeform);
+               ob->derivedDeform = NULL;
+       }
        
        BKE_displist_free(&ob->disp);
 }
@@ -264,7 +278,7 @@ void BKE_object_free(Object *ob)
 {
        int a;
        
-       BKE_object_free_display(ob);
+       BKE_object_free_derived_caches(ob);
        
        /* disconnect specific data, but not for lib data (might be indirect data, can get relinked) */
        if (ob->data) {
@@ -2790,27 +2804,29 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
 {
        SculptSession *ss = ob->sculpt;
 
-       if (!ss->cache) {
-               /* we free pbvh on changes, except during sculpt since it can't deal with
-                * changing PVBH node organization, we hope topology does not change in
-                * the meantime .. weak */
-               if (ss->pbvh) {
-                       BKE_pbvh_free(ss->pbvh);
-                       ss->pbvh = NULL;
-               }
+       if (ss) {
+               if (!ss->cache) {
+                       /* we free pbvh on changes, except during sculpt since it can't deal with
+                        * changing PVBH node organization, we hope topology does not change in
+                        * the meantime .. weak */
+                       if (ss->pbvh) {
+                               BKE_pbvh_free(ss->pbvh);
+                               ss->pbvh = NULL;
+                       }
 
-               free_sculptsession_deformMats(ob->sculpt);
-       }
-       else {
-               PBVHNode **nodes;
-               int n, totnode;
+                       free_sculptsession_deformMats(ob->sculpt);
+               }
+               else {
+                       PBVHNode **nodes;
+                       int n, totnode;
 
-               BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+                       BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
 
-               for (n = 0; n < totnode; n++)
-                       BKE_pbvh_node_mark_update(nodes[n]);
+                       for (n = 0; n < totnode; n++)
+                               BKE_pbvh_node_mark_update(nodes[n]);
 
-               MEM_freeN(nodes);
+                       MEM_freeN(nodes);
+               }
        }
 }
 
index 74542321a62a4f2bc543d2437373380f5a67dd5b..e8829c6216b4d48eafb64baebb456934e79dd658 100644 (file)
@@ -51,6 +51,7 @@
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_library.h"
+#include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_pbvh.h"
 #include "BKE_subsurf.h"
@@ -433,11 +434,8 @@ void sculptsession_bm_to_me_for_render(Object *object)
                         * here because this will lead to the while object
                         * surface to disappear, so we'll release DM in place.
                         */
-                       if (object->derivedFinal) {
-                               object->derivedFinal->needsFree = 1;
-                               object->derivedFinal->release(object->derivedFinal);
-                               object->derivedFinal = NULL;
-                       }
+                       BKE_object_free_derived_caches(object);
+
                        if (object->sculpt->pbvh) {
                                BKE_pbvh_free(object->sculpt->pbvh);
                                object->sculpt->pbvh = NULL;
index 719c7ab95e3ce8e431bbc4943ffab660f40b1211..40fda072180b5e77223654adf1758bc7dceb925c 100644 (file)
@@ -374,6 +374,11 @@ void EDBM_mesh_load(Object *ob)
 #ifdef USE_TESSFACE_DEFAULT
        BKE_mesh_tessface_calc(me);
 #endif
+
+       /* free derived mesh. usually this would happen through depsgraph but there
+        * are exceptions like file save that will not cause this, and we want to
+        * avoid ending up with an invalid derived mesh then */
+       BKE_object_free_derived_caches(ob);
 }
 
 /**
index fce520d04fa47cd815a96315470c7fa5e87b751e..ee10adbf7dba9fcafa4b2cc0b28e2a3090509491 100644 (file)
@@ -4542,7 +4542,7 @@ void sculpt_pbvh_clear(Object *ob)
        ss->pbvh = NULL;
        if (dm)
                dm->getPBVH(NULL, dm);
-       BKE_object_free_display(ob);
+       BKE_object_free_derived_caches(ob);
 }
 
 void sculpt_update_after_dynamic_topology_toggle(bContext *C)