Fix T66234: Issue on switching material mode between Object and Data
The root of the issue comes to the fact that part of dependency graph is being removed, without doing any further remapping. This was happening because only materials used by objects were pulled in, so when material mode is changed some material became unused and removed from the dependency graph and freed, causing object or its data to point to a freed memory in its materials array. Simplest and safest way to solve this is to pull materials referenced by both object and object data. This causes somewhat higher memory usage but keeps evaluated state of scene in an always consistent state, without any need to tag/update object's data on material mode change. Don't think it is a problem in practice. Reviewers: brecht, fclem Reviewed By: brecht, fclem Differential Revision: https://developer.blender.org/D5172
This commit is contained in:
@@ -697,6 +697,12 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Materials. */
|
||||
Material ***materials_ptr = give_matarar(object);
|
||||
if (materials_ptr != NULL) {
|
||||
short *num_materials_ptr = give_totcolp(object);
|
||||
build_materials(*materials_ptr, *num_materials_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_object_data_camera(Object *object)
|
||||
@@ -1195,14 +1201,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob
|
||||
function_bind(BKE_object_eval_uber_data, _1, scene_cow, object_cow));
|
||||
op_node->set_as_exit();
|
||||
/* Materials. */
|
||||
if (object->totcol != 0) {
|
||||
for (int a = 1; a <= object->totcol; a++) {
|
||||
Material *ma = give_current_material(object, a);
|
||||
if (ma != NULL) {
|
||||
build_material(ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
build_materials(object->mat, object->totcol);
|
||||
/* Point caches. */
|
||||
build_object_pointcache(object);
|
||||
/* Geometry. */
|
||||
@@ -1434,6 +1433,16 @@ void DepsgraphNodeBuilder::build_material(Material *material)
|
||||
build_nodetree(material->nodetree);
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_materials(Material **materials, int num_materials)
|
||||
{
|
||||
for (int i = 0; i < num_materials; ++i) {
|
||||
if (materials[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
build_material(materials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively build graph for texture */
|
||||
void DepsgraphNodeBuilder::build_texture(Tex *texture)
|
||||
{
|
||||
|
||||
@@ -202,6 +202,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
|
||||
void build_light(Light *lamp);
|
||||
void build_nodetree(bNodeTree *ntree);
|
||||
void build_material(Material *ma);
|
||||
void build_materials(Material **materials, int num_materials);
|
||||
void build_texture(Tex *tex);
|
||||
void build_image(Image *image);
|
||||
void build_world(World *world);
|
||||
|
||||
@@ -751,6 +751,12 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
|
||||
add_relation(key_key, geometry_key, "Shapekeys");
|
||||
build_nested_shapekey(&object->id, key);
|
||||
}
|
||||
/* Materials. */
|
||||
Material ***materials_ptr = give_matarar(object);
|
||||
if (materials_ptr != NULL) {
|
||||
short *num_materials_ptr = give_totcolp(object);
|
||||
build_materials(*materials_ptr, *num_materials_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_object_data_camera(Object *object)
|
||||
@@ -1934,14 +1940,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
|
||||
}
|
||||
}
|
||||
/* Materials. */
|
||||
if (object->totcol) {
|
||||
for (int a = 1; a <= object->totcol; a++) {
|
||||
Material *ma = give_current_material(object, a);
|
||||
if (ma != NULL) {
|
||||
build_material(ma);
|
||||
}
|
||||
}
|
||||
}
|
||||
build_materials(object->mat, object->totcol);
|
||||
/* Geometry collision. */
|
||||
if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
|
||||
// add geometry collider relations
|
||||
@@ -2236,6 +2235,16 @@ void DepsgraphRelationBuilder::build_material(Material *material)
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_materials(Material **materials, int num_materials)
|
||||
{
|
||||
for (int i = 0; i < num_materials; ++i) {
|
||||
if (materials[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
build_material(materials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively build graph for texture */
|
||||
void DepsgraphRelationBuilder::build_texture(Tex *texture)
|
||||
{
|
||||
|
||||
@@ -264,6 +264,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
|
||||
void build_light(Light *lamp);
|
||||
void build_nodetree(bNodeTree *ntree);
|
||||
void build_material(Material *ma);
|
||||
void build_materials(Material **materials, int num_materials);
|
||||
void build_texture(Tex *tex);
|
||||
void build_image(Image *image);
|
||||
void build_gpencil(bGPdata *gpd);
|
||||
|
||||
Reference in New Issue
Block a user