Fix T49993: Indirectly used taper/bevel crashes new dependency graph
New dependency graph expects strict separation between nodes and relations builder, meaning, if we try to create relation with an object which is not in the graph yet we'll have an error in depsgraph. Now, so far object nodes were created from bases of the current scene, which caused missing objects in graph in certain cases. Didn't find better approach than to simply ensure object nodes exists when we know they'll be used by relation builder.
This commit is contained in:
@@ -108,6 +108,40 @@ extern "C" {
|
|||||||
|
|
||||||
namespace DEG {
|
namespace DEG {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct BuilderWalkUserData {
|
||||||
|
DepsgraphNodeBuilder *builder;
|
||||||
|
Scene *scene;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void modifier_walk(void *user_data,
|
||||||
|
struct Object * /*ob*/,
|
||||||
|
struct Object **obpoin,
|
||||||
|
int /*cd_flag*/)
|
||||||
|
{
|
||||||
|
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
|
||||||
|
if (*obpoin) {
|
||||||
|
data->builder->build_object(data->scene, NULL, *obpoin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void constraint_walk(bConstraint * /*con*/,
|
||||||
|
ID **idpoin,
|
||||||
|
bool /*is_reference*/,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
|
||||||
|
if (*idpoin) {
|
||||||
|
ID *id = *idpoin;
|
||||||
|
if (GS(id) == ID_OB) {
|
||||||
|
data->builder->build_object(data->scene, NULL, (Object *)id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace */
|
||||||
|
|
||||||
/* ************ */
|
/* ************ */
|
||||||
/* Node Builder */
|
/* Node Builder */
|
||||||
|
|
||||||
@@ -405,19 +439,22 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
|
|||||||
{
|
{
|
||||||
/*Object *ob = go->ob;*/
|
/*Object *ob = go->ob;*/
|
||||||
|
|
||||||
/* Each "group object" is effectively a separate instance of the underlying
|
/* Each "group object" is effectively a separate instance of the
|
||||||
* object data. When the group is evaluated, the transform results and/or
|
* underlying object data. When the group is evaluated, the transform
|
||||||
* some other attributes end up getting overridden by the group
|
* results and/or some other attributes end up getting overridden by
|
||||||
|
* the group.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a node for representing subgraph */
|
/* Create a node for representing subgraph. */
|
||||||
SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id);
|
SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id);
|
||||||
subgraph_node->graph = subgraph;
|
subgraph_node->graph = subgraph;
|
||||||
|
|
||||||
/* make a copy of the data this node will need? */
|
/* Make a copy of the data this node will need? */
|
||||||
// XXX: do we do this now, or later?
|
/* XXX: do we do this now, or later? */
|
||||||
// TODO: need API function which queries graph's ID's hash, and duplicates those blocks thoroughly with all outside links removed...
|
/* TODO: need API function which queries graph's ID's hash, and duplicates
|
||||||
|
* those blocks thoroughly with all outside links removed.
|
||||||
|
*/
|
||||||
|
|
||||||
return subgraph_node;
|
return subgraph_node;
|
||||||
}
|
}
|
||||||
@@ -432,13 +469,32 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
|
|||||||
ob->id.tag |= LIB_TAG_DOIT;
|
ob->id.tag |= LIB_TAG_DOIT;
|
||||||
|
|
||||||
IDDepsNode *id_node = add_id_node(&ob->id);
|
IDDepsNode *id_node = add_id_node(&ob->id);
|
||||||
id_node->layers |= base->lay;
|
if (base != NULL) {
|
||||||
|
id_node->layers |= base->lay;
|
||||||
|
}
|
||||||
ob->customdata_mask = 0;
|
ob->customdata_mask = 0;
|
||||||
|
|
||||||
/* standard components */
|
/* Standard components. */
|
||||||
build_object_transform(scene, ob);
|
build_object_transform(scene, ob);
|
||||||
|
|
||||||
/* object data */
|
if (ob->parent != NULL) {
|
||||||
|
build_object(scene, NULL, ob->parent);
|
||||||
|
}
|
||||||
|
if (ob->modifiers.first != NULL) {
|
||||||
|
BuilderWalkUserData data;
|
||||||
|
data.builder = this;
|
||||||
|
data.scene = scene;
|
||||||
|
modifiers_foreachObjectLink(ob, modifier_walk, &data);
|
||||||
|
}
|
||||||
|
if (ob->constraints.first != NULL) {
|
||||||
|
BuilderWalkUserData data;
|
||||||
|
data.builder = this;
|
||||||
|
data.scene = scene;
|
||||||
|
modifiers_foreachObjectLink(ob, modifier_walk, &data);
|
||||||
|
BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Object data. */
|
||||||
if (ob->data) {
|
if (ob->data) {
|
||||||
/* type-specific data... */
|
/* type-specific data... */
|
||||||
switch (ob->type) {
|
switch (ob->type) {
|
||||||
@@ -1110,9 +1166,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case OB_CURVE:
|
case OB_CURVE:
|
||||||
|
case OB_SURF:
|
||||||
case OB_FONT:
|
case OB_FONT:
|
||||||
{
|
{
|
||||||
/* Curve evaluation operations. */
|
/* Curve/nurms evaluation operations. */
|
||||||
/* - calculate curve geometry (including path) */
|
/* - calculate curve geometry (including path) */
|
||||||
add_operation_node(obdata,
|
add_operation_node(obdata,
|
||||||
DEPSNODE_TYPE_GEOMETRY,
|
DEPSNODE_TYPE_GEOMETRY,
|
||||||
@@ -1124,28 +1181,30 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
|
|||||||
"Geometry Eval");
|
"Geometry Eval");
|
||||||
|
|
||||||
/* Calculate curve path - this is used by constraints, etc. */
|
/* Calculate curve path - this is used by constraints, etc. */
|
||||||
add_operation_node(obdata,
|
if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
|
||||||
DEPSNODE_TYPE_GEOMETRY,
|
add_operation_node(obdata,
|
||||||
DEPSOP_TYPE_EXEC,
|
DEPSNODE_TYPE_GEOMETRY,
|
||||||
function_bind(BKE_curve_eval_path,
|
DEPSOP_TYPE_EXEC,
|
||||||
_1,
|
function_bind(BKE_curve_eval_path,
|
||||||
(Curve *)obdata),
|
_1,
|
||||||
DEG_OPCODE_GEOMETRY_PATH,
|
(Curve *)obdata),
|
||||||
"Path");
|
DEG_OPCODE_GEOMETRY_PATH,
|
||||||
break;
|
"Path");
|
||||||
}
|
}
|
||||||
|
|
||||||
case OB_SURF:
|
/* Make sure objects used for bevel.taper are in the graph.
|
||||||
{
|
* NOTE: This objects might be not linked to the scene.
|
||||||
/* Nurbs evaluation operations. */
|
*/
|
||||||
add_operation_node(obdata,
|
Curve *cu = (Curve *)obdata;
|
||||||
DEPSNODE_TYPE_GEOMETRY,
|
if (cu->bevobj != NULL) {
|
||||||
DEPSOP_TYPE_INIT,
|
build_object(scene, NULL, cu->bevobj);
|
||||||
function_bind(BKE_curve_eval_geometry,
|
}
|
||||||
_1,
|
if (cu->taperobj != NULL) {
|
||||||
(Curve *)obdata),
|
build_object(scene, NULL, cu->bevobj);
|
||||||
DEG_OPCODE_PLACEHOLDER,
|
}
|
||||||
"Geometry Eval");
|
if (ob->type == OB_FONT && cu->textoncurve != NULL) {
|
||||||
|
build_object(scene, NULL, cu->textoncurve);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1908,15 +1908,18 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
|
|||||||
// XXX: these needs geom data, but where is geom stored?
|
// XXX: these needs geom data, but where is geom stored?
|
||||||
if (cu->bevobj) {
|
if (cu->bevobj) {
|
||||||
ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY);
|
ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY);
|
||||||
|
build_object(bmain, scene, cu->bevobj);
|
||||||
add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel");
|
add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel");
|
||||||
}
|
}
|
||||||
if (cu->taperobj) {
|
if (cu->taperobj) {
|
||||||
ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
|
ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY);
|
||||||
|
build_object(bmain, scene, cu->taperobj);
|
||||||
add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper");
|
add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper");
|
||||||
}
|
}
|
||||||
if (ob->type == OB_FONT) {
|
if (ob->type == OB_FONT) {
|
||||||
if (cu->textoncurve) {
|
if (cu->textoncurve) {
|
||||||
ComponentKey textoncurve_key(&cu->textoncurve->id, DEPSNODE_TYPE_GEOMETRY);
|
ComponentKey textoncurve_key(&cu->textoncurve->id, DEPSNODE_TYPE_GEOMETRY);
|
||||||
|
build_object(bmain, scene, cu->textoncurve);
|
||||||
add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve");
|
add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user