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:
authorSergey Sharybin <sergey.vfx@gmail.com>2018-03-02 18:42:27 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2018-03-02 18:42:27 +0300
commitc327cf489c4d145407786552e4d9027295754985 (patch)
tree9d1cc902a67988fe82d710d922d16794369c9615
parentf9f559a05fc16e66031210e62bd7bc51d26208a3 (diff)
parentf76d49ed9504612cc5ba3956b53f920f7c93bd20 (diff)
Merge branch 'master' into blender2.8
-rw-r--r--intern/cycles/util/util_math_int3.h3
-rw-r--r--source/blender/blenkernel/intern/constraint.c19
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc95
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc86
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc20
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc18
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h1
-rwxr-xr-xtests/python/modules/test_utils.py12
10 files changed, 198 insertions, 68 deletions
diff --git a/intern/cycles/util/util_math_int3.h b/intern/cycles/util/util_math_int3.h
index 1bc6ca7f376..6eef8517665 100644
--- a/intern/cycles/util/util_math_int3.h
+++ b/intern/cycles/util/util_math_int3.h
@@ -76,8 +76,6 @@ ccl_device_inline int3 clamp(const int3& a, int3& mn, int mx)
clamp(a.z, mn.z, mx));
#endif
}
-#endif /* !__KERNEL_OPENCL__ */
-
ccl_device_inline bool operator==(const int3 &a, const int3 &b)
{
@@ -93,6 +91,7 @@ ccl_device_inline bool operator<(const int3 &a, const int3 &b)
{
return a.x < b.x && a.y < b.y && a.z < b.z;
}
+#endif /* !__KERNEL_OPENCL__ */
CCL_NAMESPACE_END
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index f0e60296119..b070ccdd4eb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1917,28 +1917,29 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
bSameVolumeConstraint *data = con->data;
float volume = data->volume;
- float fac = 1.0f;
+ float fac = 1.0f, total_scale;
float obsize[3];
mat4_to_size(obsize, cob->matrix);
/* calculate normalizing scale factor for non-essential values */
- if (obsize[data->flag] != 0)
- fac = sqrtf(volume / obsize[data->flag]);
+ total_scale = obsize[0] * obsize[1] * obsize[2];
+ if (total_scale != 0)
+ fac = sqrtf(volume / total_scale);
/* apply scaling factor to the channels not being kept */
switch (data->flag) {
case SAMEVOL_X:
- mul_v3_fl(cob->matrix[1], fac / obsize[1]);
- mul_v3_fl(cob->matrix[2], fac / obsize[2]);
+ mul_v3_fl(cob->matrix[1], fac);
+ mul_v3_fl(cob->matrix[2], fac);
break;
case SAMEVOL_Y:
- mul_v3_fl(cob->matrix[0], fac / obsize[0]);
- mul_v3_fl(cob->matrix[2], fac / obsize[2]);
+ mul_v3_fl(cob->matrix[0], fac);
+ mul_v3_fl(cob->matrix[2], fac);
break;
case SAMEVOL_Z:
- mul_v3_fl(cob->matrix[0], fac / obsize[0]);
- mul_v3_fl(cob->matrix[1], fac / obsize[1]);
+ mul_v3_fl(cob->matrix[0], fac);
+ mul_v3_fl(cob->matrix[1], fac);
break;
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index c9fa35bd551..026aa309b02 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -46,6 +46,8 @@
namespace DEG {
+namespace {
+
typedef enum eCyclicCheckVisitedState {
/* Not is not visited at all during traversal. */
NODE_NOT_VISITED = 0,
@@ -55,6 +57,30 @@ typedef enum eCyclicCheckVisitedState {
NODE_IN_STACK = 2,
} eCyclicCheckVisitedState;
+struct StackEntry {
+ OperationDepsNode *node;
+ StackEntry *from;
+ DepsRelation *via_relation;
+};
+
+struct CyclesSolverState {
+ CyclesSolverState(Depsgraph *graph)
+ : graph(graph),
+ traversal_stack(BLI_stack_new(sizeof(StackEntry),
+ "DEG detect cycles stack")),
+ num_cycles(0) {
+ }
+ ~CyclesSolverState() {
+ BLI_stack_free(traversal_stack);
+ if (num_cycles != 0) {
+ printf("Detected %d dependency cycles\n", num_cycles);
+ }
+ }
+ Depsgraph *graph;
+ BLI_Stack *traversal_stack;
+ int num_cycles;
+};
+
BLI_INLINE void set_node_visited_state(DepsNode *node,
eCyclicCheckVisitedState state)
{
@@ -76,19 +102,20 @@ BLI_INLINE int get_node_num_visited_children(DepsNode *node)
return node->done >> 2;
}
-void deg_graph_detect_cycles(Depsgraph *graph)
+void schedule_node_to_stack(CyclesSolverState *state, OperationDepsNode *node)
{
- struct StackEntry {
- OperationDepsNode *node;
- StackEntry *from;
- DepsRelation *via_relation;
- };
-
- BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry),
- "DEG detect cycles stack");
+ StackEntry entry;
+ entry.node = node;
+ entry.from = NULL;
+ entry.via_relation = NULL;
+ BLI_stack_push(state->traversal_stack, &entry);
+ set_node_visited_state(node, NODE_IN_STACK);
+}
- int num_cycles = 0;
- foreach (OperationDepsNode *node, graph->operations) {
+/* Schedule leaf nodes (node without input links) for traversal. */
+void schedule_leaf_nodes(CyclesSolverState *state)
+{
+ foreach (OperationDepsNode *node, state->graph->operations) {
bool has_inlinks = false;
foreach (DepsRelation *rel, node->inlinks) {
if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
@@ -97,18 +124,32 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
node->done = 0;
if (has_inlinks == false) {
- StackEntry entry;
- entry.node = node;
- entry.from = NULL;
- entry.via_relation = NULL;
- BLI_stack_push(traversal_stack, &entry);
- set_node_visited_state(node, NODE_IN_STACK);
+ schedule_node_to_stack(state, node);
}
else {
set_node_visited_state(node, NODE_NOT_VISITED);
}
}
+}
+
+/* Schedule node which was not checked yet for being belong to
+ * any of dependency cycle.
+ */
+bool schedule_non_checked_node(CyclesSolverState *state)
+{
+ foreach (OperationDepsNode *node, state->graph->operations) {
+ if (get_node_visited_state(node) == NODE_NOT_VISITED) {
+ schedule_node_to_stack(state, node);
+ return true;
+ }
+ }
+ return false;
+}
+/* Solve cycles with all nodes which are scheduled for traversal. */
+void solve_cycles(CyclesSolverState *state)
+{
+ BLI_Stack *traversal_stack = state->traversal_stack;
while (!BLI_stack_is_empty(traversal_stack)) {
StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
OperationDepsNode *node = entry->node;
@@ -137,7 +178,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
/* TODO(sergey): So called russian roulette cycle solver. */
rel->flag |= DEPSREL_FLAG_CYCLIC;
- ++num_cycles;
+ ++state->num_cycles;
}
else if (to_state == NODE_NOT_VISITED) {
StackEntry new_entry;
@@ -157,11 +198,23 @@ void deg_graph_detect_cycles(Depsgraph *graph)
BLI_stack_discard(traversal_stack);
}
}
+}
- BLI_stack_free(traversal_stack);
+} // namespace
- if (num_cycles != 0) {
- printf("Detected %d dependency cycles\n", num_cycles);
+void deg_graph_detect_cycles(Depsgraph *graph)
+{
+ CyclesSolverState state(graph);
+ /* First we solve cycles which are reachable from leaf nodes. */
+ schedule_leaf_nodes(&state);
+ solve_cycles(&state);
+ /* We are not done yet. It is possible to have closed loop cycle,
+ * for example A -> B -> C -> A. These nodes were not scheduled
+ * yet (since they all have inlinks), and were not traversed since
+ * nobody else points to them.
+ */
+ while (schedule_non_checked_node(&state)) {
+ solve_cycles(&state);
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index d115111b7e8..e7a9b4b5a69 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -285,6 +285,22 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
name_tag);
}
+OperationDepsNode *DepsgraphNodeBuilder::ensure_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ const DepsEvalOperationCb& op,
+ eDepsOperation_Code opcode,
+ const char *name,
+ int name_tag)
+{
+ OperationDepsNode *operation =
+ find_operation_node(id, comp_type, opcode, name, name_tag);
+ if (operation != NULL) {
+ return operation;
+ }
+ return add_operation_node(id, comp_type, op, opcode, name, name_tag);
+}
+
bool DepsgraphNodeBuilder::has_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
@@ -693,37 +709,57 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
* \param id: ID-Block that driver is attached to
* \param fcu: Driver-FCurve
*/
-OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
+void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve)
{
ID *id_cow = get_cow_id(id);
/* Create data node for this driver */
- /* TODO(sergey): Avoid creating same operation multiple times,
- * in the future we need to avoid lookup of the operation as well
- * and use some tagging magic instead.
- */
- OperationDepsNode *driver_op = find_operation_node(
- id,
- DEG_NODE_TYPE_PARAMETERS,
- DEG_OPCODE_DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
-
- if (driver_op == NULL) {
- /* TODO(sergey): Shall we use COW of fcu itself here? */
- driver_op = add_operation_node(id,
- DEG_NODE_TYPE_PARAMETERS,
- function_bind(BKE_animsys_eval_driver,
- _1,
- id_cow,
- fcu),
- DEG_OPCODE_DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
+ /* TODO(sergey): Shall we use COW of fcu itself here? */
+ ensure_operation_node(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ function_bind(BKE_animsys_eval_driver, _1, id_cow, fcurve),
+ DEG_OPCODE_DRIVER,
+ fcurve->rna_path ? fcurve->rna_path : "",
+ fcurve->array_index);
+ build_driver_variables(id, fcurve);
+}
+
+void DepsgraphNodeBuilder::build_driver_variables(ID * id, FCurve *fcurve)
+{
+ build_driver_id_property(id, fcurve->rna_path);
+ LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ build_driver_id_property(dtar->id, dtar->rna_path);
+ }
+ DRIVER_TARGETS_LOOPER_END
}
+}
- /* return driver node created */
- return driver_op;
+void DepsgraphNodeBuilder::build_driver_id_property(ID *id,
+ const char *rna_path)
+{
+ if (id == NULL || rna_path == NULL) {
+ return;
+ }
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, NULL)) {
+ return;
+ }
+ if (prop == NULL) {
+ return;
+ }
+ if (!RNA_property_is_idprop(prop)) {
+ return;
+ }
+ const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
+ ensure_operation_node(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ NULL,
+ DEG_OPCODE_ID_PROPERTY,
+ prop_identifier);
}
/* Recursively build graph for world */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index ce0ad1e2037..49cccb60843 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -140,6 +140,13 @@ struct DepsgraphNodeBuilder {
const char *name = "",
int name_tag = -1);
+ OperationDepsNode *ensure_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const DepsEvalOperationCb& op,
+ eDepsOperation_Code opcode,
+ const char *name = "",
+ int name_tag = -1);
+
bool has_operation_node(ID *id,
eDepsNode_Type comp_type,
const char *comp_name,
@@ -179,7 +186,9 @@ struct DepsgraphNodeBuilder {
void build_particle_settings(ParticleSettings *part);
void build_cloth(Object *object);
void build_animdata(ID *id);
- OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
+ void build_driver(ID *id, FCurve *fcurve);
+ void build_driver_variables(ID *id, FCurve *fcurve);
+ void build_driver_id_property(ID *id, const char *rna_path);
void build_ik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index f9d0349a5dc..ddb0f809a53 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1178,6 +1178,26 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
}
+ if (RNA_pointer_is_null(&target_key.ptr)) {
+ /* TODO(sergey): This would only mean that driver is broken.
+ * so we can't create relation anyway. However, we need to avoid
+ * adding drivers which are known to be buggy to a dependency
+ * graph, in order to save computational power.
+ */
+ }
+ else {
+ if (target_key.prop != NULL &&
+ RNA_property_is_idprop(target_key.prop))
+ {
+ OperationKey parameters_key(id,
+ DEG_NODE_TYPE_PARAMETERS,
+ DEG_OPCODE_PARAMETERS_EVAL);
+ add_relation(target_key,
+ parameters_key,
+ "Driver Target -> Properties");
+ }
+ add_relation(driver_key, target_key, "Driver -> Target");
+ }
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 987a0654cca..ee4ffee772e 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -140,7 +140,7 @@ static bool pointer_to_component_node_criteria(
*type = DEG_NODE_TYPE_PARAMETERS;
*subdata = "";
*operation_code = DEG_OPCODE_PARAMETERS_EVAL;
- *operation_name = pchan->name;;
+ *operation_name = pchan->name;
}
else {
/* Bone - generally, we just want the bone component. */
@@ -230,10 +230,18 @@ static bool pointer_to_component_node_criteria(
}
if (prop != NULL) {
/* All unknown data effectively falls under "parameter evaluation". */
- *type = DEG_NODE_TYPE_PARAMETERS;
- *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
- *operation_name = "";
- *operation_name_tag = -1;
+ if (RNA_property_is_idprop(prop)) {
+ *type = DEG_NODE_TYPE_PARAMETERS;
+ *operation_code = DEG_OPCODE_ID_PROPERTY;
+ *operation_name = RNA_property_identifier((PropertyRNA *)prop);
+ *operation_name_tag = -1;
+ }
+ else {
+ *type = DEG_NODE_TYPE_PARAMETERS;
+ *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
+ *operation_name = "";
+ *operation_name_tag = -1;
+ }
return true;
}
return false;
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 886601225c7..1ae1b52b8d2 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -81,6 +81,7 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
#define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name
/* Generic Operations. */
STRINGIFY_OPCODE(OPERATION);
+ STRINGIFY_OPCODE(ID_PROPERTY);
STRINGIFY_OPCODE(PARAMETERS_EVAL);
STRINGIFY_OPCODE(PLACEHOLDER);
/* Animation, Drivers, etc. */
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index 3f4df21b8d6..f8699186866 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -162,6 +162,7 @@ typedef enum eDepsOperation_Code {
DEG_OPCODE_OPERATION = 0,
/* Generic parameters evaluation. */
+ DEG_OPCODE_ID_PROPERTY,
DEG_OPCODE_PARAMETERS_EVAL,
// XXX: Placeholder while porting depsgraph code
diff --git a/tests/python/modules/test_utils.py b/tests/python/modules/test_utils.py
index 489f36c913f..6ca498d8cdf 100755
--- a/tests/python/modules/test_utils.py
+++ b/tests/python/modules/test_utils.py
@@ -58,11 +58,10 @@ def with_tempdir(wrapped):
class AbstractBlenderRunnerTest(unittest.TestCase):
"""Base class for all test suites which needs to run Blender"""
- @classmethod
- def setUpClass(cls):
- global args
- cls.blender = args.blender
- cls.testdir = pathlib.Path(args.testdir)
+ # Set in a subclass
+ blender: pathlib.Path = None
+ testdir: pathlib.Path = None
+
def run_blender(self, filepath: str, python_script: str, timeout: int=300) -> str:
"""Runs Blender by opening a blendfile and executing a script.
@@ -73,6 +72,9 @@ class AbstractBlenderRunnerTest(unittest.TestCase):
:param timeout: in seconds
"""
+ assert self.blender, "Path to Blender binary is to be set in setUpClass()"
+ assert self.testdir, "Path to tests binary is to be set in setUpClass()"
+
blendfile = self.testdir / filepath
command = (