Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Sat, 19 Nov 2016 15:28:39 +0000 (16:28 +0100)
committerBastien Montagne <montagne29@wanadoo.fr>
Sat, 19 Nov 2016 15:28:39 +0000 (16:28 +0100)
Conflicts:
source/blender/blenloader/intern/versioning_270.c
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/editors/space_view3d/drawobject.c

44 files changed:
build_files/cmake/platform/platform_win32_msvc.cmake
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
make.bat
release/scripts/modules/bpy/utils/__init__.py
release/scripts/modules/bpy_extras/object_utils.py
release/scripts/startup/bl_operators/add_mesh_torus.py
release/scripts/startup/bl_ui/properties_paint_common.py
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenkernel/intern/blender_undo.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/library_remap.c
source/blender/blenkernel/intern/node.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_core.c
source/blender/bmesh/intern/bmesh_mesh_validate.c
source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/bmesh_polygon.c
source/blender/bmesh/intern/bmesh_queries.h
source/blender/bmesh/operators/bmo_primitive.c
source/blender/depsgraph/CMakeLists.txt
source/blender/depsgraph/intern/builder/deg_builder.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.h
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc [new file with mode: 0644]
source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc [new file with mode: 0644]
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc [new file with mode: 0644]
source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc [new file with mode: 0644]
source/blender/depsgraph/util/deg_util_foreach.h
source/blender/editors/interface/interface_anim.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/render/render_opengl.c
source/blender/editors/sculpt_paint/paint_image_2d.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_view3d/drawobject.c
source/blender/modifiers/intern/MOD_meshsequencecache.c
source/blender/nodes/intern/node_common.c
source/blender/windowmanager/intern/wm_files.c
source/creator/CMakeLists.txt

index 5efda52b2c58d3ce8a403fd5bab4095161d36f20..6ca0568b5fd067a1d685bd3e57dd782a9263dbba 100644 (file)
@@ -129,8 +129,10 @@ if(NOT DEFINED LIBDIR)
                message(STATUS "32 bit compiler detected.")
                set(LIBDIR_BASE "windows")
        endif()
-
-       if(MSVC_VERSION EQUAL 1900)
+       if(MSVC_VERSION EQUAL 1910)
+               message(STATUS "Visual Studio 2017 detected.")
+               set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
+       elseif(MSVC_VERSION EQUAL 1900)
                message(STATUS "Visual Studio 2015 detected.")
                set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc14)
        else()
index 3888cdef70e5cf755ba46ab295f899aa1dacc2e0..fc08a913f58f91267c07d28690718cff3f066578 100644 (file)
@@ -1156,15 +1156,21 @@ class CyclesPreferences(bpy.types.AddonPreferences):
         return cuda_devices, opencl_devices
 
 
-    def has_active_device(self):
+    def get_num_gpu_devices(self):
         import _cycles
         device_list = _cycles.available_devices()
+        num = 0
         for device in device_list:
             if device[1] != self.compute_device_type:
                 continue
-            if any(dev.use and dev.id == device[2] for dev in self.devices):
-                return True
-        return False
+            for dev in self.devices:
+                if dev.use and dev.id == device[2]:
+                    num += 1
+        return num
+
+
+    def has_active_device(self):
+        return self.get_num_gpu_devices() > 0
 
 
     def draw_impl(self, layout, context):
index 2d9785b94d08bece25dbaf87c229b2ae54ccab3a..7ed8c5f0a1310d9955c244469b1d253bb2c5cf3e 100644 (file)
@@ -1556,7 +1556,7 @@ def draw_device(self, context):
         sub = row.split(align=True)
         sub.active = show_device_selection(context)
         sub.prop(cscene, "device", text="")
-        row.operator("wm.addon_userpref_show", text="Preferences", icon='PREFERENCES').module = __package__
+        row.operator("wm.addon_userpref_show", text="", icon='PREFERENCES').module = __package__
 
         if engine.with_osl() and use_cpu(context):
             layout.prop(cscene, "shading_system")
index c250a54f259d03df16a0d7985d35ef1d521705f3..171153dd440ddf76041a5ec19e1d1c4f0f18adf9 100644 (file)
@@ -32,6 +32,7 @@
 #include "util_color.h"
 #include "util_foreach.h"
 #include "util_function.h"
+#include "util_hash.h"
 #include "util_logging.h"
 #include "util_progress.h"
 #include "util_time.h"
@@ -498,7 +499,8 @@ void BlenderSession::render()
                scene->film->tag_update(scene);
                scene->integrator->tag_update(scene);
 
-               for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
+               int view_index = 0;
+               for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) {
                        b_rview_name = b_view_iter->name();
 
                        /* set the current view */
@@ -514,6 +516,12 @@ void BlenderSession::render()
                                        &python_thread_state,
                                        b_rlay_name.c_str());
 
+                       /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
+                       if(view_index != 0) {
+                               scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef));
+                               scene->integrator->tag_update(scene);
+                       }
+
                        /* Update number of samples per layer. */
                        int samples = sync->get_layer_samples();
                        bool bound_samples = sync->get_layer_bound_samples();
index 74148e5599d4bc36f12eedc26c8351c9d21ac23f..f3ec646dc8f6ecfd5a44c1da540325158e3f82f6 100644 (file)
--- a/make.bat
+++ b/make.bat
@@ -61,6 +61,9 @@ if NOT "%1" == "" (
                set BUILD_ARCH=x86
        )       else if "%1" == "x64" (
                set BUILD_ARCH=x64
+       )       else if "%1" == "2017" (
+       set BUILD_VS_VER=15
+       set BUILD_VS_YEAR=2017
        )       else if "%1" == "2015" (
        set BUILD_VS_VER=14
        set BUILD_VS_YEAR=2015
@@ -140,7 +143,7 @@ if "%target%"=="Release" (
 )
 
 :DetectMSVC
-REM Detect MSVC Installation
+REM Detect MSVC Installation for 2013-2015
 if DEFINED VisualStudioVersion goto msvc_detect_finally
 set VALUE_NAME=ProductDir
 REM Check 64 bits
@@ -153,7 +156,18 @@ for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAM
 if DEFINED MSVC_VC_DIR goto msvc_detect_finally
 :msvc_detect_finally
 if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
+if DEFINED MSVC_VC_DIR goto sanity_checks
 
+rem MSVC Build environment 2017 and up. 
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
+if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
+REM Check 32 bits
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\sxs\vs7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
+if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
+:msvc_detect_finally_2017
+if DEFINED MSVC_VS_DIR call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat"
+
+:sanity_checks
 REM Sanity Checks
 where /Q msbuild
 if %ERRORLEVEL% NEQ 0 (
index 66974dedc2460685e40bd886eeb71105f327025d..31dd836e034cf6f3e1090f91da575b5b90002be3 100644 (file)
@@ -154,8 +154,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
         original_modules = _sys.modules.values()
 
     if reload_scripts:
-        _bpy_types.TypeMap.clear()
-
         # just unload, don't change user defaults, this means we can sync
         # to reload. note that they will only actually reload of the
         # modification time changes. This `won't` work for packages so...
@@ -163,6 +161,9 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
         for module_name in [ext.module for ext in _user_preferences.addons]:
             _addon_utils.disable(module_name)
 
+        # *AFTER* unregistering all add-ons, otherwise all calls to unregister_module() will silently fail (do nothing).
+        _bpy_types.TypeMap.clear()
+
     def register_module_call(mod):
         register = getattr(mod, "register", None)
         if register:
index 88cd7398fe0c9fae045f38942e1fe1ec322ddf97..c48f03c133d69ec3381741f50bda8e31214830d0 100644 (file)
@@ -189,6 +189,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
         scene.update()  # apply location
         # scene.objects.active = obj_new
 
+        # Match up UV layers, this is needed so adding an object with UV's
+        # doesn't create new layers when there happens to be a naming mis-match.
+        uv_new = obdata.uv_layers.active
+        if uv_new is not None:
+            uv_act = obj_act.data.uv_layers.active
+            if uv_act is not None:
+                uv_new.name = uv_act.name
+
         bpy.ops.object.join()  # join into the active.
         if obdata:
             bpy.data.meshes.remove(obdata)
index 303a8b01192e9a611dbd8278c8951ef8c91e6c00..f12e7484e6453e87ebf2adec14c66b9292860f31 100644 (file)
@@ -84,26 +84,27 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
 
 def add_uvs(mesh, minor_seg, major_seg):
     mesh.uv_textures.new()
-    uv_layer = mesh.uv_layers.active
-    u_step = 1.0/major_seg
-    v_step = 1.0/minor_seg
+    uv_data = mesh.uv_layers.active.data
+    polygons = mesh.polygons
+    u_step = 1.0 / major_seg
+    v_step = 1.0 / minor_seg
     vertex_index = 0
 
     u = 0.5
     for major_index in range(major_seg):
         v = 0.5
         for minor_index in range(minor_seg):
-            loops = mesh.polygons[vertex_index].loop_indices
-            if minor_index == minor_seg-1 and major_index == 0:
-                uv_layer.data[loops[1]].uv = (u, v)
-                uv_layer.data[loops[2]].uv = (u + u_step, v)
-                uv_layer.data[loops[0]].uv = (u, v + v_step)
-                uv_layer.data[loops[3]].uv = (u + u_step, v + v_step)
+            loops = polygons[vertex_index].loop_indices
+            if minor_index == minor_seg - 1 and major_index == 0:
+                uv_data[loops[1]].uv = (u, v)
+                uv_data[loops[2]].uv = (u + u_step, v)
+                uv_data[loops[0]].uv = (u, v + v_step)
+                uv_data[loops[3]].uv = (u + u_step, v + v_step)
             else:
-                uv_layer.data[loops[0]].uv = (u, v)
-                uv_layer.data[loops[1]].uv = (u + u_step, v)
-                uv_layer.data[loops[3]].uv = (u, v + v_step)
-                uv_layer.data[loops[2]].uv = (u + u_step, v + v_step)
+                uv_data[loops[0]].uv = (u, v)
+                uv_data[loops[1]].uv = (u + u_step, v)
+                uv_data[loops[3]].uv = (u, v + v_step)
+                uv_data[loops[2]].uv = (u + u_step, v + v_step)
             v = (v + v_step) % 1.0
             vertex_index += 1
         u = (u + u_step) % 1.0
index c18aa10e229ff0730d4e65e35fd840e4db9f5a7e..c7bae0d87d645738bf6c96cbe4b5ab6606de8529 100644 (file)
@@ -117,16 +117,14 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
                 col.label("Gradient Colors")
                 col.template_color_ramp(brush, "gradient", expand=True)
 
-                if brush.image_tool != 'FILL':
+                if brush.image_tool == 'DRAW':
                     col.label("Background Color")
                     row = col.row(align=True)
                     panel.prop_unified_color(row, context, brush, "secondary_color", text="")
-
-                if brush.image_tool == 'DRAW':
                     col.prop(brush, "gradient_stroke_mode", text="Mode")
                     if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}:
                         col.prop(brush, "grad_spacing")
-                elif brush.image_tool == 'FILL':
+                else: # if brush.image_tool == 'FILL':
                     col.prop(brush, "gradient_fill_mode")
             else:
                 row = col.row(align=True)
@@ -137,6 +135,9 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal
                     panel.prop_unified_color(row, context, brush, "secondary_color", text="")
                     row.separator()
                     row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
+        else:
+            if brush.image_tool == 'FILL' and not projpaint:
+                col.prop(brush, "fill_threshold")
 
     elif brush.image_tool == 'SOFTEN':
         col = layout.column(align=True)
index baf8510dd0dc19d67181b0196502890e3b7726a5..4f4787f9da59d49fd8df358ef988f24c93e7e072 100644 (file)
@@ -28,7 +28,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         278
-#define BLENDER_SUBVERSION      3
+#define BLENDER_SUBVERSION      4
 /* Several breakages with 270, e.g. constraint deg vs rad */
 #define BLENDER_MINVERSION      270
 #define BLENDER_MINSUBVERSION   6
index ce6d29bbfeea36e52ef63b16c01d7161d70beb39..bc98d6f68051d2fbd4fa614def79f59d90e0a5fe 100644 (file)
@@ -320,7 +320,7 @@ const char *BKE_undo_get_name(int nr, bool *r_active)
 }
 
 /* return the name of the last item */
-const char *BKE_undo_get_name_last()
+const char *BKE_undo_get_name_last(void)
 {
        UndoElem *uel = undobase.last;
        return (uel ? uel->name : NULL);
index df3a7630bb03716e38b4b684976bf1e5f94844b6..c9bad2160ffd2b2b0c90b55eb3af70b4bed6a9c4 100644 (file)
@@ -1244,7 +1244,6 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
                case R_IMF_IMTYPE_RAWTGA:
                case R_IMF_IMTYPE_IRIS:
                case R_IMF_IMTYPE_PNG:
-               case R_IMF_IMTYPE_RADHDR:
                case R_IMF_IMTYPE_TIFF:
                case R_IMF_IMTYPE_OPENEXR:
                case R_IMF_IMTYPE_MULTILAYER:
index 785fb44c9460f1c4739750434473769273e986b5..3b757a46e2e79da8ec30a8fc8f656e43ddbd54ee 100644 (file)
@@ -377,6 +377,18 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), O
        }
 }
 
+static void libblock_remap_data_postprocess_nodetree_update(Main *bmain, ID *new_id)
+{
+       /* Verify all nodetree user nodes. */
+       ntreeVerifyNodes(bmain, new_id);
+
+       /* Update node trees as necessary. */
+       FOREACH_NODETREE(bmain, ntree, id) {
+               /* make an update call for the tree */
+               ntreeUpdateTree(bmain, ntree);
+       } FOREACH_NODETREE_END
+}
+
 /**
  * Execute the 'data' part of the remapping (that is, all ID pointers from other ID datablocks).
  *
@@ -550,6 +562,8 @@ void BKE_libblock_remap_locked(
                default:
                        break;
        }
+       /* Node trees may virtually use any kind of data-block... */
+       libblock_remap_data_postprocess_nodetree_update(bmain, new_id);
 
        /* Full rebuild of DAG! */
        DAG_relations_tag_update(bmain);
index 2b88ae4823c33bd4ec695be287d834d4cb5a628a..a227228ceb510e64d6ef8ddcbfb709850f7b866c 100644 (file)
@@ -736,11 +736,14 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
                node_socket_free(ntree, sock, node);
                MEM_freeN(sock);
        }
+       BLI_listbase_clear(&node->inputs);
+
        for (sock = node->outputs.first; sock; sock = sock_next) {
                sock_next = sock->next;
                node_socket_free(ntree, sock, node);
                MEM_freeN(sock);
        }
+       BLI_listbase_clear(&node->outputs);
        
        node->update |= NODE_UPDATE;
 }
index 577c278e0e4f7c11c20b232d8223020d36f73c9e..3fa3f037600367b35d084e8fc0cc6c18ca2ee307 100644 (file)
@@ -1367,6 +1367,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                }
        }
 
+       if (!MAIN_VERSION_ATLEAST(main, 278, 4)) {
+               const float sqrt_3 = (float)M_SQRT3;
+               for (Brush *br = main->brush.first; br; br = br->id.next) {
+                       br->fill_threshold /= sqrt_3;
+               }
+       }
+
        {
                if (!DNA_struct_elem_find(fd->filesdna, "View3DDebug", "char", "background")) {
                        bScreen *screen;
index 03436f4658ace15261a93c6bab638a7cbc2045ea..d8097f1a50adb9e35eb359d32a71c2492b241b44 100644 (file)
@@ -912,20 +912,22 @@ static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
 static void write_node_socket(WriteData *wd, bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock)
 {
 #ifdef USE_NODE_COMPAT_CUSTOMNODES
-       /* forward compatibility code, so older blenders still open */
-       sock->stack_type = 1;
-
-       if (node->type == NODE_GROUP) {
-               bNodeTree *ngroup = (bNodeTree *)node->id;
-               if (ngroup) {
-                       /* for node groups: look up the deprecated groupsock pointer */
-                       sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
-                       BLI_assert(sock->groupsock != NULL);
-
-                       /* node group sockets now use the generic identifier string to verify group nodes,
-                        * old blender uses the own_index.
-                        */
-                       sock->own_index = sock->groupsock->own_index;
+       /* forward compatibility code, so older blenders still open (not for undo) */
+       if (wd->current == NULL) {
+               sock->stack_type = 1;
+
+               if (node->type == NODE_GROUP) {
+                       bNodeTree *ngroup = (bNodeTree *)node->id;
+                       if (ngroup) {
+                               /* for node groups: look up the deprecated groupsock pointer */
+                               sock->groupsock = ntreeFindSocketInterface(ngroup, sock->in_out, sock->identifier);
+                               BLI_assert(sock->groupsock != NULL);
+
+                               /* node group sockets now use the generic identifier string to verify group nodes,
+                                * old blender uses the own_index.
+                                */
+                               sock->own_index = sock->groupsock->own_index;
+                       }
                }
        }
 #endif
index 0cd91107171adc17df032b156cac573330f72ae9..d1178a198dcda792f78412c03239f4bbcbea181a 100644 (file)
@@ -2682,8 +2682,10 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
 
 /**
  * A version of #bmesh_urmv_loop that disconnects multiple loops at once.
+ * The loops must all share the same vertex, can be in any order
+ * and are all moved to use a single new vertex - which is returned.
  *
- * Handles the task of finding fans boundaries.
+ * This function handles the details of finding fans boundaries.
  */
 BMVert *bmesh_urmv_loop_multi(
         BMesh *bm, BMLoop **larr, int larr_len)
index 478194735f3ca7ff7dbe4e0025a9bde34e294353..7c9ebc800a343a6685397db4ef66892f38c23459 100644 (file)
@@ -64,7 +64,7 @@ bool BM_mesh_validate(BMesh *bm)
 
        int i, j;
 
-       errtot = -1;
+       errtot = -1; /* 'ERRMSG' next line will set at zero */
        fprintf(stderr, "\n");
        ERRMSG("This is a debugging function and not intended for general use, running slow test!");
 
@@ -187,15 +187,22 @@ bool BM_mesh_validate(BMesh *bm)
                } while ((l_iter = l_iter->next) != l_first);
 
                if (j != f->len) {
-                       ERRMSG("face %d: has length if %d but should be %d", i, f->len, j);
+                       ERRMSG("face %d: has length of %d but should be %d", i, f->len, j);
                }
+
+               /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */
+               do {
+                       BM_elem_flag_disable(l_iter,    BM_ELEM_INTERNAL_TAG);
+                       BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+                       BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG);
+               } while ((l_iter = l_iter->next) != l_first);
        }
 
        BLI_edgehash_free(edge_hash, NULL);
 
+       const bool is_valid = (errtot == 0);
        ERRMSG("Finished - errors %d", errtot);
-
-       return (errtot == 0);
+       return is_valid;
 }
 
 
index 03165beb329e16f1f50c86e949d7967e7e61d024..500da6b8788114e2c60df5a46e28fc292236c548 100644 (file)
@@ -346,7 +346,7 @@ BMFace *BM_face_split_n(
         BMLoop **r_l, BMEdge *example)
 {
        BMFace *f_new, *f_tmp;
-       BMLoop *l_dummy;
+       BMLoop *l_new;
        BMEdge *e, *e_new;
        BMVert *v_new;
        // BMVert *v_a = l_a->v; /* UNUSED */
@@ -368,24 +368,21 @@ BMFace *BM_face_split_n(
        }
 
        f_tmp = BM_face_copy(bm, bm, f, true, true);
-
-       if (!r_l)
-               r_l = &l_dummy;
        
 #ifdef USE_BMESH_HOLES
-       f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, NULL, example, false);
+       f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, NULL, example, false);
 #else
-       f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, example, false);
+       f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, example, false);
 #endif
-       /* bmesh_sfme returns in r_l a Loop for f_new going from v_a to v_b.
-        * The radial_next is for f and goes from v_b to v_a  */
+       /* bmesh_sfme returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
+        * The radial_next is for 'f' and goes from 'v_b' to 'v_a'  */
 
        if (f_new) {
-               e = (*r_l)->e;
+               e = l_new->e;
                for (i = 0; i < n; i++) {
                        v_new = bmesh_semv(bm, v_b, e, &e_new);
                        BLI_assert(v_new != NULL);
-                       /* bmesh_semv returns in e_new the edge going from v_new to tv */
+                       /* bmesh_semv returns in 'e_new' the edge going from 'v_new' to 'v_b' */
                        copy_v3_v3(v_new->co, cos[i]);
 
                        /* interpolate the loop data for the loops with (v == v_new), using orig face */
@@ -405,6 +402,10 @@ BMFace *BM_face_split_n(
 
        BM_face_verts_kill(bm, f_tmp);
 
+       if (r_l) {
+               *r_l = l_new;
+       }
+
        return f_new;
 }
 
index c500d7b9ec2398fd0143e926447d8e3fa7a4cd20..6acd790fc0ca82464473019934ef7d1c6c9b67f3 100644 (file)
@@ -225,24 +225,16 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
  */
 float BM_face_calc_area(const BMFace *f)
 {
+       /* inline 'area_poly_v3' logic, avoid creating a temp array */
        const BMLoop *l_iter, *l_first;
-       float (*verts)[3] = BLI_array_alloca(verts, f->len);
-       float area;
-       unsigned int i = 0;
+       float n[3];
 
+       zero_v3(n);
        l_iter = l_first = BM_FACE_FIRST_LOOP(f);
        do {
-               copy_v3_v3(verts[i++], l_iter->v->co);
+               add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co);
        } while ((l_iter = l_iter->next) != l_first);
-
-       if (f->len == 3) {
-               area = area_tri_v3(verts[0], verts[1], verts[2]);
-       }
-       else {
-               area = area_poly_v3((const float (*)[3])verts, f->len);
-       }
-
-       return area;
+       return len_v3(n) * 0.5f;
 }
 
 /**
index a6a37767ee9c68e9a319351f3f731b7ba6b29a0e..903fdc59cb8d6b1406d6da64ba21efecf5973b24 100644 (file)
@@ -135,7 +135,7 @@ BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNUL
 BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
-BMFaceBM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1);
+BMFace *BM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1);
 
 bool    BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 bool    BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
index 7b32921f8cff6c5d6a77eef27e3f835bc326f69d..8408169d85e50888565fcfeaaf3dde2fe1376c3e 100644 (file)
@@ -1174,7 +1174,7 @@ void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag)
        }
 
        BMIter iter2;
-       BMLoopl;
+       BMLoop *l;
        int loop_index;
        float minx = 1.0f;
 
@@ -1236,14 +1236,14 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
        int uvi = 0;
        const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
        for (i = 0; i < monkeynf; i++) {
-               BMFace* temp1 = BM_face_create_quad_tri(bm,
+               BMFace *f_new_a = BM_face_create_quad_tri(bm,
                                        tv[monkeyf[i][0] + i - monkeyo],
                                        tv[monkeyf[i][1] + i - monkeyo],
                                        tv[monkeyf[i][2] + i - monkeyo],
                                        (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
                                        NULL, BM_CREATE_NOP);
 
-               BMFace* temp2 = BM_face_create_quad_tri(bm,
+               BMFace *f_new_b = BM_face_create_quad_tri(bm,
                                        tv[monkeynv + monkeyf[i][2] + i - monkeyo],
                                        tv[monkeynv + monkeyf[i][1] + i - monkeyo],
                                        tv[monkeynv + monkeyf[i][0] + i - monkeyo],
@@ -1252,20 +1252,19 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
 
                /* Set the UVs here, the iteration order of the faces is not guaranteed,
                 * so it's best to set the UVs right after the face is created. */
-               if(calc_uvs) {
-                       BMLoopl;
+               if (calc_uvs) {
+                       BMLoop *l;
                        BMIter liter;
-                       int loop_index;
-                       BM_ITER_ELEM_INDEX (l, &liter, temp1, BM_LOOPS_OF_FACE, loop_index) {
+                       BM_ITER_ELEM (l, &liter, f_new_a, BM_LOOPS_OF_FACE) {
                                MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                               luv->uv[0] = monkeyuvs[uvi*2 + 0];
-                               luv->uv[1] = monkeyuvs[uvi*2 + 1];
+                               luv->uv[0] = monkeyuvs[uvi * 2 + 0];
+                               luv->uv[1] = monkeyuvs[uvi * 2 + 1];
                                uvi++;
                        }
-                       BM_ITER_ELEM_INDEX (l, &liter, temp2, BM_LOOPS_OF_FACE, loop_index) {
+                       BM_ITER_ELEM (l, &liter, f_new_b, BM_LOOPS_OF_FACE) {
                                MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-                               luv->uv[0] = monkeyuvs[uvi*2 + 0];
-                               luv->uv[1] = monkeyuvs[uvi*2 + 1];
+                               luv->uv[0] = monkeyuvs[uvi * 2 + 0];
+                               luv->uv[1] = monkeyuvs[uvi * 2 + 1];
                                uvi++;
                        }
 
index ab12a8d5b3ef98c17e0c596664ac9ae4f469704b..e635256cda64db7c5e00a47704d7fa6ede6de353 100644 (file)
@@ -43,9 +43,13 @@ set(SRC
        intern/builder/deg_builder.cc
        intern/builder/deg_builder_cycle.cc
        intern/builder/deg_builder_nodes.cc
+       intern/builder/deg_builder_nodes_rig.cc
+       intern/builder/deg_builder_nodes_scene.cc
        intern/builder/deg_builder_pchanmap.cc
        intern/builder/deg_builder_relations.cc
        intern/builder/deg_builder_relations_keys.cc
+       intern/builder/deg_builder_relations_rig.cc
+       intern/builder/deg_builder_relations_scene.cc
        intern/builder/deg_builder_transitive.cc
        intern/debug/deg_debug_graphviz.cc
        intern/eval/deg_eval.cc
index 8939e4cc93a6e32d837fbaa911566f251a9c72e0..8a0bec5ed1d909d312d612d10e88597d73c959ec 100644 (file)
@@ -85,7 +85,7 @@ void deg_graph_build_finalize(Depsgraph *graph)
         */
        GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
        {
-               if (id_node->layers == 0 || 1) {
+               if (id_node->layers == 0) {
                        ID *id = id_node->id;
                        if (GS(id->name) == ID_OB) {
                                Object *object = (Object *)id;
index 1abce2e6b18ad344a2528c0f0f87bbea423fbcf9..3cf510eef2597839918c8dfa60a44356b75eaae6 100644 (file)
@@ -55,8 +55,10 @@ extern "C" {
 #include "DNA_key_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_rigidbody_types.h"
@@ -103,6 +105,7 @@ extern "C" {
 #include "intern/nodes/deg_node_operation.h"
 #include "intern/depsgraph_types.h"
 #include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
 
 namespace DEG {
 
@@ -315,92 +318,6 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
 
 /* **** Build functions for entity nodes **** */
 
-void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
-{
-       /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
-        * created or not. This flag is being set in add_id_node(), so functions
-        * shouldn't bother with setting it, they only might query this flag when
-        * needed.
-        */
-       BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-       /* XXX nested node trees are not included in tag-clearing above,
-        * so we need to do this manually.
-        */
-       FOREACH_NODETREE(bmain, nodetree, id) {
-               if (id != (ID *)nodetree)
-                       nodetree->id.tag &= ~LIB_TAG_DOIT;
-       } FOREACH_NODETREE_END
-
-       /* scene ID block */
-       add_id_node(&scene->id);
-
-       /* timesource */
-       add_time_source(NULL);
-
-       /* build subgraph for set, and link this in... */
-       // XXX: depending on how this goes, that scene itself could probably store its
-       //      own little partial depsgraph?
-       if (scene->set) {
-               build_scene(bmain, scene->set);
-       }
-
-       /* scene objects */
-       for (Base *base = (Base *)scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
-
-               /* object itself */
-               build_object(scene, base, ob);
-
-               /* object that this is a proxy for */
-               // XXX: the way that proxies work needs to be completely reviewed!
-               if (ob->proxy) {
-                       ob->proxy->proxy_from = ob;
-                       build_object(scene, base, ob->proxy);
-               }
-
-               /* Object dupligroup. */
-               if (ob->dup_group) {
-                       build_group(scene, base, ob->dup_group);
-               }
-       }
-
-       /* rigidbody */
-       if (scene->rigidbody_world) {
-               build_rigidbody(scene);
-       }
-
-       /* scene's animation and drivers */
-       if (scene->adt) {
-               build_animdata(&scene->id);
-       }
-
-       /* world */
-       if (scene->world) {
-               build_world(scene->world);
-       }
-
-       /* compo nodes */
-       if (scene->nodetree) {
-               build_compositor(scene);
-       }
-
-       /* sequencer */
-       // XXX...
-
-       /* grease pencil */
-       if (scene->gpd) {
-               build_gpencil(scene->gpd);
-       }
-
-       /* cache files */
-       for (CacheFile *cachefile = static_cast<CacheFile *>(bmain->cachefiles.first);
-            cachefile;
-            cachefile = static_cast<CacheFile *>(cachefile->id.next))
-       {
-               build_cachefile(cachefile);
-       }
-}
-
 void DepsgraphNodeBuilder::build_group(Scene *scene,
                                        Base *base,
                                        Group *group)
@@ -411,10 +328,7 @@ void DepsgraphNodeBuilder::build_group(Scene *scene,
        }
        group_id->tag |= LIB_TAG_DOIT;
 
-       for (GroupObject *go = (GroupObject *)group->gobject.first;
-            go != NULL;
-            go = go->next)
-       {
+       LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
                build_object(scene, base, go->ob);
        }
 }
@@ -431,10 +345,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
        DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph);
 
        /* add group objects */
-       for (GroupObject *go = (GroupObject *)group->gobject.first;
-            go != NULL;
-            go = go->next)
-       {
+       LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
                /*Object *ob = go->ob;*/
 
                /* Each "group object" is effectively a separate instance of the
@@ -619,14 +530,6 @@ void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob)
                           DEG_OPCODE_TRANSFORM_CONSTRAINTS);
 }
 
-void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
-{
-       /* create node for constraint stack */
-       add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                          DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan),
-                          DEG_OPCODE_BONE_CONSTRAINTS);
-}
-
 /**
  * Build graph nodes for AnimData block
  * \param id: ID-Block which hosts the AnimData
@@ -654,7 +557,7 @@ void DepsgraphNodeBuilder::build_animdata(ID *id)
                }
 
                /* drivers */
-               for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
+               LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
                        /* create driver */
                        build_driver(id, fcu);
                }
@@ -767,7 +670,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
 
        /* objects - simulation participants */
        if (rbw->group) {
-               for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) {
+               LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
                        Object *ob = go->ob;
 
                        if (!ob || (ob->type != OB_MESH))
@@ -782,207 +685,6 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
        }
 }
 
-/* IK Solver Eval Steps */
-void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
-{
-       bKinematicConstraint *data = (bKinematicConstraint *)con->data;
-
-       /* Find the chain's root. */
-       bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
-
-       if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
-                              DEG_OPCODE_POSE_IK_SOLVER))
-       {
-               return;
-       }
-
-       /* Operation node for evaluating/running IK Solver. */
-       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
-                          DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
-                          DEG_OPCODE_POSE_IK_SOLVER);
-}
-
-/* Spline IK Eval Steps */
-void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
-{
-       bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
-
-       /* Find the chain's root. */
-       bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
-
-       /* Operation node for evaluating/running Spline IK Solver.
-        * Store the "root bone" of this chain in the solver, so it knows where to start.
-        */
-       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
-                          DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
-                          DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
-}
-
-/* Pose/Armature Bones Graph */
-void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
-{
-       bArmature *arm = (bArmature *)ob->data;
-
-       /* animation and/or drivers linking posebones to base-armature used to define them
-        * NOTE: AnimData here is really used to control animated deform properties,
-        *       which ideally should be able to be unique across different instances.
-        *       Eventually, we need some type of proxy/isolation mechanism in-between here
-        *       to ensure that we can use same rig multiple times in same scene...
-        */
-       build_animdata(&arm->id);
-
-       /* Rebuild pose if not up to date. */
-       if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
-               BKE_pose_rebuild_ex(ob, arm, false);
-               /* XXX: Without this animation gets lost in certain circumstances
-                * after loading file. Need to investigate further since it does
-                * not happen with simple scenes..
-                */
-               if (ob->adt) {
-                       ob->adt->recalc |= ADT_RECALC_ANIM;
-               }
-       }
-
-       /* speed optimization for animation lookups */
-       if (ob->pose) {
-               BKE_pose_channels_hash_make(ob->pose);
-               if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
-                       BKE_pose_update_constraint_flags(ob->pose);
-               }
-       }
-
-       /* Make sure pose is up-to-date with armature updates. */
-       add_operation_node(&arm->id,
-                          DEPSNODE_TYPE_PARAMETERS,
-                          DEPSOP_TYPE_EXEC,
-                          NULL,
-                          DEG_OPCODE_PLACEHOLDER,
-                          "Armature Eval");
-
-       /**
-        * Pose Rig Graph
-        * ==============
-        *
-        * Pose Component:
-        * - Mainly used for referencing Bone components.
-        * - This is where the evaluation operations for init/exec/cleanup
-        *   (ik) solvers live, and are later hooked up (so that they can be
-        *   interleaved during runtime) with bone-operations they depend on/affect.
-        * - init_pose_eval() and cleanup_pose_eval() are absolute first and last
-        *   steps of pose eval process. ALL bone operations must be performed
-        *   between these two...
-        *
-        * Bone Component:
-        * - Used for representing each bone within the rig
-        * - Acts to encapsulate the evaluation operations (base matrix + parenting,
-        *   and constraint stack) so that they can be easily found.
-        * - Everything else which depends on bone-results hook up to the component only
-        *   so that we can redirect those to point at either the the post-IK/
-        *   post-constraint/post-matrix steps, as needed.
-        */
-
-       /* pose eval context */
-       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
-                          DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
-
-       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
-                          DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
-
-       /* bones */
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-               /* node for bone eval */
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
-                                  DEG_OPCODE_BONE_LOCAL);
-
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
-                                  DEG_OPCODE_BONE_POSE_PARENT);
-
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
-                                  DEG_OPCODE_BONE_READY);
-
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
-                                  DEG_OPCODE_BONE_DONE);
-
-               /* constraints */
-               if (pchan->constraints.first != NULL) {
-                       build_pose_constraints(ob, pchan);
-               }
-
-               /**
-                * IK Solvers...
-                *
-                * - These require separate processing steps are pose-level
-                *   to be executed between chains of bones (i.e. once the
-                *   base transforms of a bunch of bones is done)
-                *
-                * Unsolved Issues:
-                * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
-                * - Animated chain-lengths are a problem...
-                */
-               for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
-                       switch (con->type) {
-                               case CONSTRAINT_TYPE_KINEMATIC:
-                                       build_ik_pose(scene, ob, pchan, con);
-                                       break;
-
-                               case CONSTRAINT_TYPE_SPLINEIK:
-                                       build_splineik_pose(scene, ob, pchan, con);
-                                       break;
-
-                               default:
-                                       break;
-                       }
-               }
-       }
-}
-
-void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
-{
-       ID *obdata = (ID *)ob->data;
-       build_animdata(obdata);
-
-       BLI_assert(ob->pose != NULL);
-
-       /* speed optimization for animation lookups */
-       BKE_pose_channels_hash_make(ob->pose);
-       if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
-               BKE_pose_update_constraint_flags(ob->pose);
-       }
-
-       add_operation_node(&ob->id,
-                          DEPSNODE_TYPE_EVAL_POSE,
-                          DEPSOP_TYPE_INIT,
-                          function_bind(BKE_pose_eval_proxy_copy, _1, ob),
-                          DEG_OPCODE_POSE_INIT);
-
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
-            pchan != NULL;
-            pchan = pchan->next)
-       {
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_INIT, NULL,
-                                  DEG_OPCODE_BONE_LOCAL);
-
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_EXEC, NULL,
-                                  DEG_OPCODE_BONE_READY);
-
-               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
-                                  DEPSOP_TYPE_POST, NULL,
-                                  DEG_OPCODE_BONE_DONE);
-       }
-
-       add_operation_node(&ob->id,
-                          DEPSNODE_TYPE_EVAL_POSE,
-                          DEPSOP_TYPE_POST,
-                          NULL,
-                          DEG_OPCODE_POSE_DONE);
-}
-
 /* Shapekeys */
 void DepsgraphNodeBuilder::build_shapekeys(Key *key)
 {
@@ -1033,33 +735,26 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
        // TODO: "Done" operation
 
        /* Modifiers */
-       if (ob->modifiers.first) {
-               for (ModifierData *md = (ModifierData *)ob->modifiers.first;
-                    md != NULL;
-                    md = md->next)
-               {
-                       add_operation_node(&ob->id,
-                                          DEPSNODE_TYPE_GEOMETRY,
-                                          DEPSOP_TYPE_EXEC,
-                                          function_bind(BKE_object_eval_modifier,
-                                                        _1,
-                                                        scene,
-                                                        ob,
-                                                        md),
-                                          DEG_OPCODE_GEOMETRY_MODIFIER,
-                                          md->name);
-               }
+       LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
+               add_operation_node(&ob->id,
+                                  DEPSNODE_TYPE_GEOMETRY,
+                                  DEPSOP_TYPE_EXEC,
+                                  function_bind(BKE_object_eval_modifier,
+                                                _1,
+                                                scene,
+                                                ob,
+                                                md),
+                                  DEG_OPCODE_GEOMETRY_MODIFIER,
+                                  md->name);
        }
 
        /* materials */
-       if (ob->totcol) {
-               for (int a = 1; a <= ob->totcol; a++) {
-                       Material *ma = give_current_material(ob, a);
-                       if (ma != NULL) {
-                               // XXX?!
-                               ComponentDepsNode *geom_node = add_component_node(&ob->id, DEPSNODE_TYPE_GEOMETRY);
-                               build_material(geom_node, ma);
-                       }
+       for (int a = 1; a <= ob->totcol; a++) {
+               Material *ma = give_current_material(ob, a);
+               if (ma != NULL) {
+                       // XXX?!
+                       ComponentDepsNode *geom_node = add_component_node(&ob->id, DEPSNODE_TYPE_GEOMETRY);
+                       build_material(geom_node, ma);
                }
        }
 
@@ -1155,7 +850,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
                                build_object(scene, NULL, cu->bevobj);
                        }
                        if (cu->taperobj != NULL) {
-                               build_object(scene, NULL, cu->bevobj);
+                               build_object(scene, NULL, cu->taperobj);
                        }
                        if (ob->type == OB_FONT && cu->textoncurve != NULL) {
                                build_object(scene, NULL, cu->textoncurve);
@@ -1253,7 +948,7 @@ void DepsgraphNodeBuilder::build_nodetree(DepsNode *owner_node, bNodeTree *ntree
                           DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
 
        /* nodetree's nodes... */
-       for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
+       LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
                ID *id = bnode->id;
                if (id != NULL) {
                        short id_type = GS(id->name);
@@ -1384,7 +1079,6 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
        ID *cache_file_id = &cache_file->id;
 
        add_component_node(cache_file_id, DEPSNODE_TYPE_CACHE);
-
        add_operation_node(cache_file_id, DEPSNODE_TYPE_CACHE,
                           DEPSOP_TYPE_EXEC, NULL,
                           DEG_OPCODE_PLACEHOLDER, "Cache File Update");
@@ -1393,4 +1087,17 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
        build_animdata(cache_file_id);
 }
 
+void DepsgraphNodeBuilder::build_mask(Mask *mask)
+{
+       ID *mask_id = &mask->id;
+       add_id_node(mask_id);
+       build_animdata(mask_id);
+}
+
+void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip) {
+       ID *clip_id = &clip->id;
+       add_id_node(clip_id);
+       build_animdata(clip_id);
+}
+
 }  // namespace DEG
index 72dc73357bfc00d33c82a3ee93b053c1f0579965..9cb8bc5d45ccb660f9f44a32407f9e79588646bf 100644 (file)
@@ -44,7 +44,9 @@ struct Group;
 struct Key;
 struct Main;
 struct Material;
+struct Mask;
 struct MTex;
+struct MovieClip;
 struct bNodeTree;
 struct Object;
 struct bPoseChannel;
@@ -154,6 +156,8 @@ struct DepsgraphNodeBuilder {
        void build_compositor(Scene *scene);
        void build_gpencil(bGPdata *gpd);
        void build_cachefile(CacheFile *cache_file);
+       void build_mask(Mask *mask);
+       void build_movieclip(MovieClip *clip);
 
 protected:
        Main *m_bmain;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
new file mode 100644 (file)
index 0000000..4a5f3dc
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+ *  \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph's nodes
+ */
+
+#include "intern/builder/deg_builder_nodes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan)
+{
+       /* create node for constraint stack */
+       add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                          DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan),
+                          DEG_OPCODE_BONE_CONSTRAINTS);
+}
+
+/* IK Solver Eval Steps */
+void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+       bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+
+       /* Find the chain's root. */
+       bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+
+       if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+                              DEG_OPCODE_POSE_IK_SOLVER))
+       {
+               return;
+       }
+
+       /* Operation node for evaluating/running IK Solver. */
+       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+                          DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan),
+                          DEG_OPCODE_POSE_IK_SOLVER);
+}
+
+/* Spline IK Eval Steps */
+void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+       bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+
+       /* Find the chain's root. */
+       bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+
+       /* Operation node for evaluating/running Spline IK Solver.
+        * Store the "root bone" of this chain in the solver, so it knows where to start.
+        */
+       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name,
+                          DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan),
+                          DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+}
+
+/* Pose/Armature Bones Graph */
+void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
+{
+       bArmature *arm = (bArmature *)ob->data;
+
+       /* animation and/or drivers linking posebones to base-armature used to define them
+        * NOTE: AnimData here is really used to control animated deform properties,
+        *       which ideally should be able to be unique across different instances.
+        *       Eventually, we need some type of proxy/isolation mechanism in-between here
+        *       to ensure that we can use same rig multiple times in same scene...
+        */
+       build_animdata(&arm->id);
+
+       /* Rebuild pose if not up to date. */
+       if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
+               BKE_pose_rebuild_ex(ob, arm, false);
+               /* XXX: Without this animation gets lost in certain circumstances
+                * after loading file. Need to investigate further since it does
+                * not happen with simple scenes..
+                */
+               if (ob->adt) {
+                       ob->adt->recalc |= ADT_RECALC_ANIM;
+               }
+       }
+
+       /* speed optimization for animation lookups */
+       if (ob->pose) {
+               BKE_pose_channels_hash_make(ob->pose);
+               if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+                       BKE_pose_update_constraint_flags(ob->pose);
+               }
+       }
+
+       /* Make sure pose is up-to-date with armature updates. */
+       add_operation_node(&arm->id,
+                          DEPSNODE_TYPE_PARAMETERS,
+                          DEPSOP_TYPE_EXEC,
+                          NULL,
+                          DEG_OPCODE_PLACEHOLDER,
+                          "Armature Eval");
+
+       /**
+        * Pose Rig Graph
+        * ==============
+        *
+        * Pose Component:
+        * - Mainly used for referencing Bone components.
+        * - This is where the evaluation operations for init/exec/cleanup
+        *   (ik) solvers live, and are later hooked up (so that they can be
+        *   interleaved during runtime) with bone-operations they depend on/affect.
+        * - init_pose_eval() and cleanup_pose_eval() are absolute first and last
+        *   steps of pose eval process. ALL bone operations must be performed
+        *   between these two...
+        *
+        * Bone Component:
+        * - Used for representing each bone within the rig
+        * - Acts to encapsulate the evaluation operations (base matrix + parenting,
+        *   and constraint stack) so that they can be easily found.
+        * - Everything else which depends on bone-results hook up to the component only
+        *   so that we can redirect those to point at either the the post-IK/
+        *   post-constraint/post-matrix steps, as needed.
+        */
+
+       /* pose eval context */
+       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
+                          DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT);
+
+       add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE,
+                          DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE);
+
+       /* bones */
+       LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+               /* node for bone eval */
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local
+                                  DEG_OPCODE_BONE_LOCAL);
+
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose
+                                  DEG_OPCODE_BONE_POSE_PARENT);
+
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */
+                                  DEG_OPCODE_BONE_READY);
+
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan),
+                                  DEG_OPCODE_BONE_DONE);
+
+               /* constraints */
+               if (pchan->constraints.first != NULL) {
+                       build_pose_constraints(ob, pchan);
+               }
+
+               /**
+                * IK Solvers...
+                *
+                * - These require separate processing steps are pose-level
+                *   to be executed between chains of bones (i.e. once the
+                *   base transforms of a bunch of bones is done)
+                *
+                * Unsolved Issues:
+                * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
+                * - Animated chain-lengths are a problem...
+                */
+               LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
+                       switch (con->type) {
+                               case CONSTRAINT_TYPE_KINEMATIC:
+                                       build_ik_pose(scene, ob, pchan, con);
+                                       break;
+
+                               case CONSTRAINT_TYPE_SPLINEIK:
+                                       build_splineik_pose(scene, ob, pchan, con);
+                                       break;
+
+                               default:
+                                       break;
+                       }
+               }
+       }
+}
+
+void DepsgraphNodeBuilder::build_proxy_rig(Object *ob)
+{
+       ID *obdata = (ID *)ob->data;
+       build_animdata(obdata);
+
+       BLI_assert(ob->pose != NULL);
+
+       /* speed optimization for animation lookups */
+       BKE_pose_channels_hash_make(ob->pose);
+       if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+               BKE_pose_update_constraint_flags(ob->pose);
+       }
+
+       add_operation_node(&ob->id,
+                          DEPSNODE_TYPE_EVAL_POSE,
+                          DEPSOP_TYPE_INIT,
+                          function_bind(BKE_pose_eval_proxy_copy, _1, ob),
+                          DEG_OPCODE_POSE_INIT);
+
+       LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_INIT, NULL,
+                                  DEG_OPCODE_BONE_LOCAL);
+
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_EXEC, NULL,
+                                  DEG_OPCODE_BONE_READY);
+
+               add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name,
+                                  DEPSOP_TYPE_POST, NULL,
+                                  DEG_OPCODE_BONE_DONE);
+       }
+
+       add_operation_node(&ob->id,
+                          DEPSNODE_TYPE_EVAL_POSE,
+                          DEPSOP_TYPE_POST,
+                          NULL,
+                          DEG_OPCODE_POSE_DONE);
+}
+
+}  // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
new file mode 100644 (file)
index 0000000..bcd4bc5
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+ *  \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph's nodes
+ */
+
+#include "intern/builder/deg_builder_nodes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
+{
+       /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
+        * created or not. This flag is being set in add_id_node(), so functions
+        * shouldn't bother with setting it, they only might query this flag when
+        * needed.
+        */
+       BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+       /* XXX nested node trees are not included in tag-clearing above,
+        * so we need to do this manually.
+        */
+       FOREACH_NODETREE(bmain, nodetree, id) {
+               if (id != (ID *)nodetree)
+                       nodetree->id.tag &= ~LIB_TAG_DOIT;
+       } FOREACH_NODETREE_END
+
+       /* scene ID block */
+       add_id_node(&scene->id);
+
+       /* timesource */
+       add_time_source(NULL);
+
+       /* build subgraph for set, and link this in... */
+       // XXX: depending on how this goes, that scene itself could probably store its
+       //      own little partial depsgraph?
+       if (scene->set) {
+               build_scene(bmain, scene->set);
+       }
+
+       /* scene objects */
+       LINKLIST_FOREACH (Base *, base, &scene->base) {
+               Object *ob = base->object;
+
+               /* object itself */
+               build_object(scene, base, ob);
+
+               /* object that this is a proxy for */
+               // XXX: the way that proxies work needs to be completely reviewed!
+               if (ob->proxy) {
+                       ob->proxy->proxy_from = ob;
+                       build_object(scene, base, ob->proxy);
+               }
+
+               /* Object dupligroup. */
+               if (ob->dup_group) {
+                       build_group(scene, base, ob->dup_group);
+               }
+       }
+
+       /* rigidbody */
+       if (scene->rigidbody_world) {
+               build_rigidbody(scene);
+       }
+
+       /* scene's animation and drivers */
+       if (scene->adt) {
+               build_animdata(&scene->id);
+       }
+
+       /* world */
+       if (scene->world) {
+               build_world(scene->world);
+       }
+
+       /* compo nodes */
+       if (scene->nodetree) {
+               build_compositor(scene);
+       }
+
+       /* sequencer */
+       // XXX...
+
+       /* grease pencil */
+       if (scene->gpd) {
+               build_gpencil(scene->gpd);
+       }
+
+       /* Cache file. */
+       LINKLIST_FOREACH (CacheFile *, cachefile, &bmain->cachefiles) {
+               build_cachefile(cachefile);
+       }
+
+       /* Masks. */
+       LINKLIST_FOREACH (Mask *, mask, &bmain->mask) {
+               build_mask(mask);
+       }
+
+       /* Movie clips. */
+       LINKLIST_FOREACH (MovieClip *, clip, &bmain->movieclip) {
+               build_movieclip(clip);
+       }
+}
+
+}  // namespace DEG
index bd62833846172d4ebaa5745b93936687e01566df..dca1da0979b56216f3d7af225b72bc4cb5378e1c 100644 (file)
@@ -55,8 +55,10 @@ extern "C" {
 #include "DNA_key_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_rigidbody_types.h"
@@ -320,88 +322,6 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
 
 /* **** Functions to build relations between entities  **** */
 
-void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
-{
-       /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
-        * created or not.
-        */
-       BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-       /* XXX nested node trees are not included in tag-clearing above,
-        * so we need to do this manually.
-        */
-       FOREACH_NODETREE(bmain, nodetree, id) {
-               if (id != (ID *)nodetree)
-                       nodetree->id.tag &= ~LIB_TAG_DOIT;
-       } FOREACH_NODETREE_END
-
-       if (scene->set) {
-               // TODO: link set to scene, especially our timesource...
-       }
-
-       /* scene objects */
-       for (Base *base = (Base *)scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
-
-               /* object itself */
-               build_object(bmain, scene, ob);
-
-               /* object that this is a proxy for */
-               if (ob->proxy) {
-                       ob->proxy->proxy_from = ob;
-                       build_object(bmain, scene, ob->proxy);
-                       /* TODO(sergey): This is an inverted relation, matches old depsgraph
-                        * behavior and need to be investigated if it still need to be inverted.
-                        */
-                       ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-                       ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
-                       add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
-               }
-
-               /* Object dupligroup. */
-               if (ob->dup_group) {
-                       build_group(bmain, scene, ob, ob->dup_group);
-               }
-       }
-
-       /* rigidbody */
-       if (scene->rigidbody_world) {
-               build_rigidbody(scene);
-       }
-
-       /* scene's animation and drivers */
-       if (scene->adt) {
-               build_animdata(&scene->id);
-       }
-
-       /* world */
-       if (scene->world) {
-               build_world(scene->world);
-       }
-
-       /* compo nodes */
-       if (scene->nodetree) {
-               build_compositor(scene);
-       }
-
-       /* grease pencil */
-       if (scene->gpd) {
-               build_gpencil(&scene->id, scene->gpd);
-       }
-
-       for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
-            it_op != m_graph->operations.end();
-            ++it_op)
-       {
-               OperationDepsNode *node = *it_op;
-               IDDepsNode *id_node = node->owner->owner;
-               ID *id = id_node->id;
-               if (GS(id->name) == ID_OB) {
-                       Object *object = (Object *)id;
-                       object->customdata_mask |= node->customdata_mask;
-               }
-       }
-}
-
 void DepsgraphRelationBuilder::build_group(Main *bmain,
                                            Scene *scene,
                                            Object *object,
@@ -412,10 +332,7 @@ void DepsgraphRelationBuilder::build_group(Main *bmain,
        OperationKey object_local_transform_key(&object->id,
                                                DEPSNODE_TYPE_TRANSFORM,
                                                DEG_OPCODE_TRANSFORM_LOCAL);
-       for (GroupObject *go = (GroupObject *)group->gobject.first;
-            go != NULL;
-            go = go->next)
-       {
+       LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
                if (!group_done) {
                        build_object(bmain, scene, go->ob);
                }
@@ -687,9 +604,10 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
                        ListBase targets = {NULL, NULL};
                        cti->get_constraint_targets(con, &targets);
 
-                       for (bConstraintTarget *ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
-                               if (!ct->tar)
+                       LINKLIST_FOREACH (bConstraintTarget *, ct, &targets) {
+                               if (ct->tar == NULL) {
                                        continue;
+                               }
 
                                if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
                                        /* ignore IK constraints - these are handled separately (on pose level) */
@@ -816,7 +734,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
        }
 
        /* drivers */
-       for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
+       LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
                OperationKey driver_key(id,
                                        DEPSNODE_TYPE_PARAMETERS,
                                        DEG_OPCODE_DRIVER,
@@ -840,10 +758,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
                 */
                if (fcu->array_index > 0) {
                        FCurve *fcu_prev = NULL;
-                       for (FCurve *fcu_candidate = (FCurve *)adt->drivers.first;
-                            fcu_candidate != NULL;
-                            fcu_candidate = fcu_candidate->next)
-                       {
+                       LINKLIST_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
                                /* Writing to different RNA paths is  */
                                if (!STREQ(fcu_candidate->rna_path, fcu->rna_path)) {
                                        continue;
@@ -1007,7 +922,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
        // XXX: the data itself could also set this, if it were to be truly initialised later?
 
        /* loop over variables to get the target relationships */
-       for (DriverVar *dvar = (DriverVar *)driver->variables.first; dvar; dvar = dvar->next) {
+       LINKLIST_FOREACH (DriverVar *, dvar, &driver->variables) {
                /* only used targets */
                DRIVER_TARGETS_USED_LOOPER(dvar)
                {
@@ -1127,10 +1042,11 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* objects - simulation participants */
        if (rbw->group) {
-               for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) {
+               LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
                        Object *ob = go->ob;
-                       if (!ob || ob->type != OB_MESH)
+                       if (ob == NULL || ob->type != OB_MESH) {
                                continue;
+                       }
 
                        /* hook up evaluation order...
                         * 1) flushing rigidbody results follows base transforms being applied
@@ -1178,10 +1094,11 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* constraints */
        if (rbw->constraints) {
-               for (GroupObject *go = (GroupObject *)rbw->constraints->gobject.first; go; go = go->next) {
+               LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
                        Object *ob = go->ob;
-                       if (!ob || !ob->rigidbody_constraint)
+                       if (ob == NULL || !ob->rigidbody_constraint) {
                                continue;
+                       }
 
                        RigidBodyCon *rbc = ob->rigidbody_constraint;
 
@@ -1202,391 +1119,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
        }
 }
 
-/* IK Solver Eval Steps */
-void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
-                                             bPoseChannel *pchan,
-                                             bConstraint *con,
-                                             RootPChanMap *root_map)
-{
-       bKinematicConstraint *data = (bKinematicConstraint *)con->data;
-
-       /* attach owner to IK Solver too
-        * - assume that owner is always part of chain
-        * - see notes on direction of rel below...
-        */
-       bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
-       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
-
-       /* IK target */
-       // XXX: this should get handled as part of the constraint code
-       if (data->tar != NULL) {
-               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
-                * we create dependency between target object and pose eval component.
-                *
-                * This way we ensuring the whole subtree is updated from scratch without
-                * need of intermediate matricies. This is an overkill, but good enough for
-                * testing IK solver.
-                */
-               // FIXME: geometry targets...
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
-                       /* TODO(sergey): This is only for until granular update stores intermediate result. */
-                       if (data->tar != ob) {
-                               /* different armature - can just read the results */
-                               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
-                               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
-                       }
-                       else {
-                               /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
-                               OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
-                               add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-                       }
-               }
-               else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
-                       /* vertex group target */
-                       /* NOTE: for now, we don't need to represent vertex groups separately... */
-                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
-                       if (data->tar->type == OB_MESH) {
-                               OperationDepsNode *node2 = find_operation_node(target_key);
-                               if (node2 != NULL) {
-                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
-                               }
-                       }
-               }
-               else {
-                       /* Standard Object Target */
-                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
-                       add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-
-               if ((data->tar == ob) && (data->subtarget[0])) {
-                       /* Prevent target's constraints from linking to anything from same
-                        * chain that it controls.
-                        */
-                       root_map->add_bone(data->subtarget, rootchan->name);
-               }
-       }
-
-       /* Pole Target */
-       // XXX: this should get handled as part of the constraint code
-       if (data->poletar != NULL) {
-               if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
-                       // XXX: same armature issues - ready vs done?
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-               else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
-                       /* vertex group target */
-                       /* NOTE: for now, we don't need to represent vertex groups separately... */
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
-                       if (data->poletar->type == OB_MESH) {
-                               OperationDepsNode *node2 = find_operation_node(target_key);
-                               if (node2 != NULL) {
-                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
-                               }
-                       }
-               }
-               else {
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-       }
-
-       DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
-                        pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
-
-       bPoseChannel *parchan = pchan;
-       /* exclude tip from chain? */
-       if (!(data->flag & CONSTRAINT_IK_TIP)) {
-               OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
-                                               parchan->name, DEG_OPCODE_BONE_LOCAL);
-               add_relation(solver_key, tip_transforms_key,
-                            DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
-               parchan = pchan->parent;
-       }
-
-       root_map->add_bone(parchan->name, rootchan->name);
-
-       OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
-                                           parchan->name, DEG_OPCODE_BONE_READY);
-       add_relation(parchan_transforms_key, solver_key,
-                    DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
-
-       /* Walk to the chain's root */
-       //size_t segcount = 0;
-       int segcount = 0;
-
-       while (parchan) {
-               /* Make IK-solver dependent on this bone's result,
-                * since it can only run after the standard results
-                * of the bone are know. Validate links step on the
-                * bone will ensure that users of this bone only
-                * grab the result with IK solver results...
-                */
-               if (parchan != pchan) {
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
-                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
-
-                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
-               }
-               else {
-                       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
-               }
-               parchan->flag |= POSE_DONE;
-
-
-               root_map->add_bone(parchan->name, rootchan->name);
-
-               /* continue up chain, until we reach target number of items... */
-               DEG_DEBUG_PRINTF("  %d = %s\n", segcount, parchan->name);
-               segcount++;
-               if ((segcount == data->rootbone) || (segcount > 255)) break;  /* 255 is weak */
-
-               parchan  = parchan->parent;
-       }
-
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-}
-
-/* Spline IK Eval Steps */
-void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
-                                                   bPoseChannel *pchan,
-                                                   bConstraint *con,
-                                                   RootPChanMap *root_map)
-{
-       bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
-       bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
-       OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
-
-       /* attach owner to IK Solver too
-        * - assume that owner is always part of chain
-        * - see notes on direction of rel below...
-        */
-       add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
-
-       /* attach path dependency to solver */
-       if (data->tar) {
-               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
-                * we create dependency between target object and pose eval component.
-                * See IK pose for a bit more information.
-                */
-               // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
-               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
-       }
-
-       pchan->flag |= POSE_DONE;
-       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
-
-       root_map->add_bone(pchan->name, rootchan->name);
-
-       /* Walk to the chain's root */
-       //size_t segcount = 0;
-       int segcount = 0;
-
-       for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) {
-               /* Make Spline IK solver dependent on this bone's result,
-                * since it can only run after the standard results
-                * of the bone are know. Validate links step on the
-                * bone will ensure that users of this bone only
-                * grab the result with IK solver results...
-                */
-               if (parchan != pchan) {
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
-                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
-
-                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
-               }
-               parchan->flag |= POSE_DONE;
-
-               OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-               add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
-
-               root_map->add_bone(parchan->name, rootchan->name);
-
-               /* continue up chain, until we reach target number of items... */
-               segcount++;
-               if ((segcount == data->chainlen) || (segcount > 255)) break;  /* 255 is weak */
-       }
-
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-}
-
-/* Pose/Armature Bones Graph */
-void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
-{
-       /* Armature-Data */
-       bArmature *arm = (bArmature *)ob->data;
-
-       // TODO: selection status?
-
-       /* attach links between pose operations */
-       OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-
-       add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
-
-       /* Make sure pose is up-to-date with armature updates. */
-       OperationKey armature_key(&arm->id,
-                                 DEPSNODE_TYPE_PARAMETERS,
-                                 DEG_OPCODE_PLACEHOLDER,
-                                 "Armature Eval");
-       add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
-
-       if (needs_animdata_node(&ob->id)) {
-               ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
-               add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
-       }
-
-       /* IK Solvers...
-        * - These require separate processing steps are pose-level
-        *   to be executed between chains of bones (i.e. once the
-        *   base transforms of a bunch of bones is done)
-        *
-        * - We build relations for these before the dependencies
-        *   between ops in the same component as it is necessary
-        *   to check whether such bones are in the same IK chain
-        *   (or else we get weird issues with either in-chain
-        *   references, or with bones being parented to IK'd bones)
-        *
-        * Unsolved Issues:
-        * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
-        * - Animated chain-lengths are a problem...
-        */
-       RootPChanMap root_map;
-       bool pose_depends_on_local_transform = false;
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-               for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
-                       switch (con->type) {
-                               case CONSTRAINT_TYPE_KINEMATIC:
-                                       build_ik_pose(ob, pchan, con, &root_map);
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               case CONSTRAINT_TYPE_SPLINEIK:
-                                       build_splineik_pose(ob, pchan, con, &root_map);
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               /* Constraints which needs world's matrix for transform.
-                                * TODO(sergey): More constraints here?
-                                */
-                               case CONSTRAINT_TYPE_ROTLIKE:
-                               case CONSTRAINT_TYPE_SIZELIKE:
-                               case CONSTRAINT_TYPE_LOCLIKE:
-                               case CONSTRAINT_TYPE_TRANSLIKE:
-                                       /* TODO(sergey): Add used space check. */
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               default:
-                                       break;
-                       }
-               }
-       }
-       //root_map.print_debug();
-
-       if (pose_depends_on_local_transform) {
-               /* TODO(sergey): Once partial updates are possible use relation between
-                * object transform and solver itself in it's build function.
-                */
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
-               add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
-       }
-
-
-       /* links between operations for each bone */
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
-               OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
-               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-
-               pchan->flag &= ~POSE_DONE;
-
-               /* pose init to bone local */
-               add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
-
-               /* local to pose parenting operation */
-               add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
-
-               /* parent relation */
-               if (pchan->parent != NULL) {
-                       eDepsOperation_Code parent_key_opcode;
-
-                       /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */
-                       if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
-                               parent_key_opcode = DEG_OPCODE_BONE_READY;
-                       }
-                       else {
-                               parent_key_opcode = DEG_OPCODE_BONE_DONE;
-                       }
-
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
-                       add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
-               }
-
-               /* constraints */
-               if (pchan->constraints.first != NULL) {
-                       /* constraints stack and constraint dependencies */
-                       build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
-
-                       /* pose -> constraints */
-                       OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
-                       add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
-
-                       /* constraints -> ready */
-                       // TODO: when constraint stack is exploded, this step should occur before the first IK solver
-                       add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
-               }
-               else {
-                       /* pose -> ready */
-                       add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
-               }
-
-               /* bone ready -> done
-                * NOTE: For bones without IK, this is all that's needed.
-                *       For IK chains however, an additional rel is created from IK to done,
-                *       with transitive reduction removing this one...
-                */
-               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
-
-               /* assume that all bones must be done for the pose to be ready (for deformers) */
-               add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-       }
-}
-
-void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
-{
-       OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
-       OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
-            pchan != NULL;
-            pchan = pchan->next)
-       {
-               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
-               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-               add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
-               add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
-               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
-               add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
-       }
-}
-
 /* Shapekeys */
 void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
 {
@@ -1647,10 +1179,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
 
        /* Modifiers */
        if (ob->modifiers.first) {
-               ModifierData *md;
                OperationKey prev_mod_key;
 
-               for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) {
+               LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
                        const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
                        OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
 
@@ -1885,7 +1416,7 @@ void DepsgraphRelationBuilder::build_nodetree(ID *owner, bNodeTree *ntree)
                                    "Parameters Eval");
 
        /* nodetree's nodes... */
-       for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
+       LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
                if (bnode->id) {
                        if (GS(bnode->id->name) == ID_MA) {
                                build_material(owner, (Material *)bnode->id);
@@ -1989,4 +1520,21 @@ bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
        return false;
 }
 
+void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) {
+       /* Animation. */
+       build_animdata(&cache_file->id);
+}
+
+void DepsgraphRelationBuilder::build_mask(Mask *mask)
+{
+       /* Animation. */
+       build_animdata(&mask->id);
+}
+
+void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
+{
+       /* Animation. */
+       build_animdata(&clip->id);
+}
+
 }  // namespace DEG
index 28dd63a7c1772393a9a8f7bd8d9fc296da367c8e..2326e212feb4c9227c4a9e4fc50989ceb19a9049 100644 (file)
@@ -47,6 +47,7 @@
 
 struct Base;
 struct bGPdata;
+struct CacheFile;
 struct ListBase;
 struct GHash;
 struct ID;
@@ -54,8 +55,10 @@ struct FCurve;
 struct Group;
 struct Key;
 struct Main;
+struct Mask;
 struct Material;
 struct MTex;
+struct MovieClip;
 struct bNodeTree;
 struct Object;
 struct bPoseChannel;
@@ -220,6 +223,9 @@ struct DepsgraphRelationBuilder
        void build_texture_stack(ID *owner, MTex **texture_stack);
        void build_compositor(Scene *scene);
        void build_gpencil(ID *owner, bGPdata *gpd);
+       void build_cachefile(CacheFile *cache_file);
+       void build_mask(Mask *mask);
+       void build_movieclip(MovieClip *clip);
 
        void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name);
        void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, EffectorWeights *eff, bool add_absorption, const char *name);
index 7ada04e8f74254d40d8dfeca3ab1c1e387efd9b4..feae8bca303afe0be0dafd447f6269223731954f 100644 (file)
@@ -24,7 +24,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/depsgraph/intern/builder/deg_builder_relations.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
  *  \ingroup depsgraph
  *
  * Methods for constructing depsgraph
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
new file mode 100644 (file)
index 0000000..2b4c000
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+ *  \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include "intern/builder/deg_builder_relations.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstring>  /* required for STREQ later on. */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_pchanmap.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "intern/depsgraph_types.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+/* IK Solver Eval Steps */
+void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
+                                             bPoseChannel *pchan,
+                                             bConstraint *con,
+                                             RootPChanMap *root_map)
+{
+       bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+
+       /* attach owner to IK Solver too
+        * - assume that owner is always part of chain
+        * - see notes on direction of rel below...
+        */
+       bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
+
+       /* IK target */
+       // XXX: this should get handled as part of the constraint code
+       if (data->tar != NULL) {
+               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
+                * we create dependency between target object and pose eval component.
+                *
+                * This way we ensuring the whole subtree is updated from scratch without
+                * need of intermediate matricies. This is an overkill, but good enough for
+                * testing IK solver.
+                */
+               // FIXME: geometry targets...
+               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+               if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
+                       /* TODO(sergey): This is only for until granular update stores intermediate result. */
+                       if (data->tar != ob) {
+                               /* different armature - can just read the results */
+                               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
+                               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+                       }
+                       else {
+                               /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
+                               OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
+                               add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+                       }
+               }
+               else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
+                       /* vertex group target */
+                       /* NOTE: for now, we don't need to represent vertex groups separately... */
+                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
+                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+
+                       if (data->tar->type == OB_MESH) {
+                               OperationDepsNode *node2 = find_operation_node(target_key);
+                               if (node2 != NULL) {
+                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+                               }
+                       }
+               }
+               else {
+                       /* Standard Object Target */
+                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
+                       add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
+               }
+
+               if ((data->tar == ob) && (data->subtarget[0])) {
+                       /* Prevent target's constraints from linking to anything from same
+                        * chain that it controls.
+                        */
+                       root_map->add_bone(data->subtarget, rootchan->name);
+               }
+       }
+
+       /* Pole Target */
+       // XXX: this should get handled as part of the constraint code
+       if (data->poletar != NULL) {
+               if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
+                       // XXX: same armature issues - ready vs done?
+                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
+                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+               }
+               else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
+                       /* vertex group target */
+                       /* NOTE: for now, we don't need to represent vertex groups separately... */
+                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
+                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
+
+                       if (data->poletar->type == OB_MESH) {
+                               OperationDepsNode *node2 = find_operation_node(target_key);
+                               if (node2 != NULL) {
+                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+                               }
+                       }
+               }
+               else {
+                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
+                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
+               }
+       }
+
+       DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
+                        pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
+
+       bPoseChannel *parchan = pchan;
+       /* exclude tip from chain? */
+       if (!(data->flag & CONSTRAINT_IK_TIP)) {
+               OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+                                               parchan->name, DEG_OPCODE_BONE_LOCAL);
+               add_relation(solver_key, tip_transforms_key,
+                            DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+               parchan = pchan->parent;
+       }
+
+       root_map->add_bone(parchan->name, rootchan->name);
+
+       OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
+                                           parchan->name, DEG_OPCODE_BONE_READY);
+       add_relation(parchan_transforms_key, solver_key,
+                    DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
+
+       /* Walk to the chain's root */
+       //size_t segcount = 0;
+       int segcount = 0;
+
+       while (parchan) {
+               /* Make IK-solver dependent on this bone's result,
+                * since it can only run after the standard results
+                * of the bone are know. Validate links step on the
+                * bone will ensure that users of this bone only
+                * grab the result with IK solver results...
+                */
+               if (parchan != pchan) {
+                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
+
+                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+               }
+               else {
+                       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+                       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
+               }
+               parchan->flag |= POSE_DONE;
+
+
+               root_map->add_bone(parchan->name, rootchan->name);
+
+               /* continue up chain, until we reach target number of items... */
+               DEG_DEBUG_PRINTF("  %d = %s\n", segcount, parchan->name);
+               segcount++;
+               if ((segcount == data->rootbone) || (segcount > 255)) break;  /* 255 is weak */
+
+               parchan  = parchan->parent;
+       }
+
+       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+}
+
+/* Spline IK Eval Steps */
+void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
+                                                   bPoseChannel *pchan,
+                                                   bConstraint *con,
+                                                   RootPChanMap *root_map)
+{
+       bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+       bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+       OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
+
+       /* attach owner to IK Solver too
+        * - assume that owner is always part of chain
+        * - see notes on direction of rel below...
+        */
+       add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
+
+       /* attach path dependency to solver */
+       if (data->tar) {
+               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
+                * we create dependency between target object and pose eval component.
+                * See IK pose for a bit more information.
+                */
+               // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
+               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
+               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
+       }
+
+       pchan->flag |= POSE_DONE;
+       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
+
+       root_map->add_bone(pchan->name, rootchan->name);
+
+       /* Walk to the chain's root */
+       //size_t segcount = 0;
+       int segcount = 0;
+
+       for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) {
+               /* Make Spline IK solver dependent on this bone's result,
+                * since it can only run after the standard results
+                * of the bone are know. Validate links step on the
+                * bone will ensure that users of this bone only
+                * grab the result with IK solver results...
+                */
+               if (parchan != pchan) {
+                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
+                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
+
+                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+               }
+               parchan->flag |= POSE_DONE;
+
+               OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+               add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
+
+               root_map->add_bone(parchan->name, rootchan->name);
+
+               /* continue up chain, until we reach target number of items... */
+               segcount++;
+               if ((segcount == data->chainlen) || (segcount > 255)) break;  /* 255 is weak */
+       }
+
+       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+}
+
+/* Pose/Armature Bones Graph */
+void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
+{
+       /* Armature-Data */
+       bArmature *arm = (bArmature *)ob->data;
+
+       // TODO: selection status?
+
+       /* attach links between pose operations */
+       OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+
+       add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
+
+       /* Make sure pose is up-to-date with armature updates. */
+       OperationKey armature_key(&arm->id,
+                                 DEPSNODE_TYPE_PARAMETERS,
+                                 DEG_OPCODE_PLACEHOLDER,
+                                 "Armature Eval");
+       add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
+
+       if (needs_animdata_node(&ob->id)) {
+               ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
+               add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
+       }
+
+       /* IK Solvers...
+        * - These require separate processing steps are pose-level
+        *   to be executed between chains of bones (i.e. once the
+        *   base transforms of a bunch of bones is done)
+        *
+        * - We build relations for these before the dependencies
+        *   between ops in the same component as it is necessary
+        *   to check whether such bones are in the same IK chain
+        *   (or else we get weird issues with either in-chain
+        *   references, or with bones being parented to IK'd bones)
+        *
+        * Unsolved Issues:
+        * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
+        * - Animated chain-lengths are a problem...
+        */
+       RootPChanMap root_map;
+       bool pose_depends_on_local_transform = false;
+       LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+               LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
+                       switch (con->type) {
+                               case CONSTRAINT_TYPE_KINEMATIC:
+                                       build_ik_pose(ob, pchan, con, &root_map);
+                                       pose_depends_on_local_transform = true;
+                                       break;
+
+                               case CONSTRAINT_TYPE_SPLINEIK:
+                                       build_splineik_pose(ob, pchan, con, &root_map);
+                                       pose_depends_on_local_transform = true;
+                                       break;
+
+                               /* Constraints which needs world's matrix for transform.
+                                * TODO(sergey): More constraints here?
+                                */
+                               case CONSTRAINT_TYPE_ROTLIKE:
+                               case CONSTRAINT_TYPE_SIZELIKE:
+                               case CONSTRAINT_TYPE_LOCLIKE:
+                               case CONSTRAINT_TYPE_TRANSLIKE:
+                                       /* TODO(sergey): Add used space check. */
+                                       pose_depends_on_local_transform = true;
+                                       break;
+
+                               default:
+                                       break;
+                       }
+               }
+       }
+       //root_map.print_debug();
+
+       if (pose_depends_on_local_transform) {
+               /* TODO(sergey): Once partial updates are possible use relation between
+                * object transform and solver itself in it's build function.
+                */
+               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+               ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
+               add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
+       }
+
+
+       /* links between operations for each bone */
+       LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+               OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
+               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+
+               pchan->flag &= ~POSE_DONE;
+
+               /* pose init to bone local */
+               add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
+
+               /* local to pose parenting operation */
+               add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
+
+               /* parent relation */
+               if (pchan->parent != NULL) {
+                       eDepsOperation_Code parent_key_opcode;
+
+                       /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */
+                       if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
+                               parent_key_opcode = DEG_OPCODE_BONE_READY;
+                       }
+                       else {
+                               parent_key_opcode = DEG_OPCODE_BONE_DONE;
+                       }
+
+                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
+                       add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
+               }
+
+               /* constraints */
+               if (pchan->constraints.first != NULL) {
+                       /* constraints stack and constraint dependencies */
+                       build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+
+                       /* pose -> constraints */
+                       OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
+                       add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
+
+                       /* constraints -> ready */
+                       // TODO: when constraint stack is exploded, this step should occur before the first IK solver
+                       add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
+               }
+               else {
+                       /* pose -> ready */
+                       add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
+               }
+
+               /* bone ready -> done
+                * NOTE: For bones without IK, this is all that's needed.
+                *       For IK chains however, an additional rel is created from IK to done,
+                *       with transitive reduction removing this one...
+                */
+               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+
+               /* assume that all bones must be done for the pose to be ready (for deformers) */
+               add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
+       }
+}
+
+void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
+{
+       OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
+       OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
+       LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
+               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
+               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
+               add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
+               add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
+               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
+               add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
+       }
+}
+
+}  // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
new file mode 100644 (file)
index 0000000..6b51a95
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+ *  \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include "intern/builder/deg_builder_relations.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstring>  /* required for STREQ later on. */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_pchanmap.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "intern/depsgraph_types.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
+{
+       /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
+        * created or not.
+        */
+       BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+       /* XXX nested node trees are not included in tag-clearing above,
+        * so we need to do this manually.
+        */
+       FOREACH_NODETREE(bmain, nodetree, id) {
+               if (id != (ID *)nodetree)
+                       nodetree->id.tag &= ~LIB_TAG_DOIT;
+       } FOREACH_NODETREE_END
+
+       if (scene->set) {
+               // TODO: link set to scene, especially our timesource...
+       }
+
+       /* scene objects */
+       LINKLIST_FOREACH (Base *, base, &scene->base) {
+               Object *ob = base->object;
+
+               /* object itself */
+               build_object(bmain, scene, ob);
+
+               /* object that this is a proxy for */
+               if (ob->proxy) {
+                       ob->proxy->proxy_from = ob;
+                       build_object(bmain, scene, ob->proxy);
+                       /* TODO(sergey): This is an inverted relation, matches old depsgraph
+                        * behavior and need to be investigated if it still need to be inverted.
+                        */
+                       ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+                       ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
+                       add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
+               }
+
+               /* Object dupligroup. */
+               if (ob->dup_group) {
+                       build_group(bmain, scene, ob, ob->dup_group);
+               }
+       }
+
+       /* rigidbody */
+       if (scene->rigidbody_world) {
+               build_rigidbody(scene);
+       }
+
+       /* scene's animation and drivers */
+       if (scene->adt) {
+               build_animdata(&scene->id);
+       }
+
+       /* world */
+       if (scene->world) {
+               build_world(scene->world);
+       }
+
+       /* compo nodes */
+       if (scene->nodetree) {
+               build_compositor(scene);
+       }
+
+       /* grease pencil */
+       if (scene->gpd) {
+               build_gpencil(&scene->id, scene->gpd);
+       }
+
+       /* Masks. */
+       LINKLIST_FOREACH (Mask *, mask, &bmain->mask) {
+               build_mask(mask);
+       }
+
+       /* Movie clips. */
+       LINKLIST_FOREACH (MovieClip *, clip, &bmain->movieclip) {
+               build_movieclip(clip);
+       }
+
+       for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
+            it_op != m_graph->operations.end();
+            ++it_op)
+       {
+               OperationDepsNode *node = *it_op;
+               IDDepsNode *id_node = node->owner->owner;
+               ID *id = id_node->id;
+               if (GS(id->name) == ID_OB) {
+                       Object *object = (Object *)id;
+                       object->customdata_mask |= node->customdata_mask;
+               }
+       }
+}
+
+}  // namespace DEG
index 14cf4fc11eda27aaaab42c55d4e0cd05a947ceb8..87d37168d51647f5dc60ce579a4e0bed91676710 100644 (file)
@@ -66,3 +66,8 @@
 #define GSET_FOREACH_END() \
                } \
        } while(0)
+
+#define LINKLIST_FOREACH(type, var, list)          \
+       for (type var = (type)((list)->first);     \
+            var != NULL;                          \
+            var = (type)(((Link*)(var))->next))
index 991cd54fecf948f942a6b8aced6d801646336c96..5da294302e9b1e4414816a2f9e2ff1e79f93e933 100644 (file)
@@ -99,6 +99,10 @@ void ui_but_anim_flag(uiBut *but, float cfra)
        }
 }
 
+/**
+ * \a str can be NULL to only perform check if \a but has an expression at all.
+ * \return if button has an expression.
+ */
 bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
 {
        FCurve *fcu;
@@ -111,7 +115,9 @@ bool ui_but_anim_expression_get(uiBut *but, char *str, size_t maxlen)
                driver = fcu->driver;
 
                if (driver && driver->type == DRIVER_TYPE_PYTHON) {
-                       BLI_strncpy(str, driver->expression, maxlen);
+                       if (str) {
+                               BLI_strncpy(str, driver->expression, maxlen);
+                       }
                        return true;
                }
        }
index f3eeadb66043e9d3032f94baeb6d7ebf1a595ef0..fc511d61e2b9c5d483ff4669bc4ba77928f2517d 100644 (file)
@@ -3067,7 +3067,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
                data->str = ui_but_string_get_dynamic(but, &data->maxlen);
        }
 
-       if (ui_but_is_float(but) && !ui_but_is_unit(but)) {
+       if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0)) {
                BLI_str_rstrip_float_zero(data->str, '\0');
        }
 
index 16842efb4366955a27fa7b08b3cef318a19e1dcf..9097432a251f0fef38ca638346f413a1838ee1e0 100644 (file)
@@ -552,8 +552,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
                BLI_assert(view_id < oglrender->views_len);
                RE_SetActiveRenderView(oglrender->re, rv->name);
                oglrender->view_id = view_id;
-               /* add grease pencil passes */
-               add_gpencil_renderpass(oglrender, rr, rv);
+               /* add grease pencil passes. For sequencer, the render does not include renderpasses
+                * TODO: The sequencer render of grease pencil should be rethought */
+               if (!oglrender->is_sequencer) {
+                       add_gpencil_renderpass(oglrender, rr, rv);
+               }
                /* render composite */
                screen_opengl_render_doit(oglrender, rr);
        }
index 9474a46d716e1b6633afc4629729efaeaa2a51d3..4f93c12385d97cb74b4b1beaa538c5e22c9f556e 100644 (file)
@@ -1489,7 +1489,8 @@ void paint_2d_bucket_fill(
                float image_init[2];
                int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
                float pixel_color[4];
-               float threshold_sq = br->fill_threshold * br->fill_threshold;
+               /* We are comparing to sum of three squared values (assumed in range [0,1]), so need to multiply... */
+               float threshold_sq = br->fill_threshold * br->fill_threshold * 3;
 
                UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
 
index 4ef703c899414ff8c65473ad6ce898a1a0e772b1..bbdf6feef01268a8f231e1e33127040857f9f026 100644 (file)
@@ -855,6 +855,42 @@ static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
                        id_us_plus(new_id);
                }
        }
+       else if (GS(old_id->name) == ID_NT) {
+               bNodeTreePath *path, *path_next;
+
+               for (path = snode->treepath.first; path; path = path->next) {
+                       if ((ID *)path->nodetree == old_id) {
+                               path->nodetree = (bNodeTree *)new_id;
+                               id_us_min(old_id);
+                               id_us_plus(new_id);
+                       }
+                       if (path == snode->treepath.first) {
+                               /* first nodetree in path is same as snode->nodetree */
+                               snode->nodetree = path->nodetree;
+                       }
+                       if (path->nodetree == NULL) {
+                               break;
+                       }
+               }
+
+               /* remaining path entries are invalid, remove */
+               for (; path; path = path_next) {
+                       path_next = path->next;
+
+                       BLI_remlink(&snode->treepath, path);
+                       MEM_freeN(path);
+               }
+
+               /* edittree is just the last in the path,
+                * set this directly since the path may have been shortened above */
+               if (snode->treepath.last) {
+                       path = snode->treepath.last;
+                       snode->edittree = path->nodetree;
+               }
+               else {
+                       snode->edittree = NULL;
+               }
+       }
 }
 
 /* only called once, from space/spacetypes.c */
index 4ae5bdff5086a95b759f8344bb188f074b3e51ca..45041620fea64ea866bbe0f73b4216e5acdb987f 100644 (file)
@@ -972,7 +972,7 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const
 
 
 /* Function to draw an Image on an empty Object */
-static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
+static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], StereoViews sview)
 {
        Image *ima = ob->data;
 
@@ -982,13 +982,22 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
        int bindcode = 0;
 
        if (ima) {
+               ImageUser iuser = *ob->iuser;
+
+               /* Support multi-view */
+               if (ima && (sview == STEREO_RIGHT_ID)) {
+                       iuser.multiview_eye = sview;
+                       iuser.flag |= IMA_SHOW_STEREO;
+                       BKE_image_multiview_index(ima, &iuser);
+               }
+
                if (ob_alpha > 0.0f) {
-                       bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false);
+                       bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false);
                        /* don't bother drawing the image if alpha = 0 */
                }
 
                int w, h;
-               BKE_image_get_size(ima, ob->iuser, &w, &h);
+               BKE_image_get_size(ima, &iuser, &w, &h);
                width = w;
                height = h;
        }
@@ -7685,7 +7694,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                        case OB_EMPTY:
                                if (!render_override) {
                                        if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
-                                               draw_empty_image(ob, dflag, ob_wire_col);
+                                               draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye);
                                        }
                                        else {
                                                drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col);
@@ -8420,7 +8429,7 @@ void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
                case OB_EMPTY:
                        if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
                                /* CONSTCOLOR == no wire outline */
-                               draw_empty_image(ob, DRAW_CONSTCOLOR, NULL);
+                               draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye);
                        }
                        else {
                                drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, NULL); /* TODO: use proper color */
index d25e8e38de3b5e74fef87ba3a0e246f221aa1738..72644d56323fdf837f4fa31e3b367ce723c4b0bf 100644 (file)
@@ -114,6 +114,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                                               mcmd->reader,
                                                               ob,
                                                               mcmd->object_path);
+               if (!mcmd->reader) {
+                       modifier_setError(md, "Could not create Alembic reader for file %s", cache_file->filepath);
+                       return dm;
+               }
        }
 
        DerivedMesh *result = ABC_read_mesh(mcmd->reader,
index fbc036435f0d43282c25bb4fe6a1109f7529bc88..736f17f1d700d4a97526ed590d85c0049086db2a 100644 (file)
@@ -178,9 +178,14 @@ void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *i
 {
        /* check inputs and outputs, and remove or insert them */
        if (id == node->id) {
-               bNodeTree *ngroup = (bNodeTree *)node->id;
-               group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
-               group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
+               if (id == NULL) {
+                       nodeRemoveAllSockets(ntree, node);
+               }
+               else {
+                       bNodeTree *ngroup = (bNodeTree *)node->id;
+                       group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
+                       group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
+               }
        }
 }
 
index fe257cc4c415e3fc2cf5c544ef336d2eacc20592..05d6386907413caf04423cc8efd6ba0c32ec9b98 100644 (file)
@@ -1144,6 +1144,9 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
                for (handler = win->modalhandlers.first; handler; handler = handler->next) {
                        if (handler->op) {
                                wm->autosavetimer = WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, 10.0);
+                               if (G.debug) {
+                                       printf("Skipping auto-save, modal operator running, retrying in ten seconds...\n");
+                               }
                                return;
                        }
                }
@@ -1161,7 +1164,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
 
                ED_editors_flush_edits(C, false);
 
-               /* no error reporting to console */
+               /* Error reporting into console */
                BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
        }
        /* do timer after file write, just in case file write takes a long time */
index 10af0d5489eaae85498f21cdcd4e9f2a2a7bc2d6..aa0a213cf64aad8688ee2aa9b4947c74548baaed 100644 (file)
@@ -714,7 +714,7 @@ elseif(WIN32)
 
                        if(WITH_PYTHON_INSTALL_NUMPY)
                                set(PYTHON_NUMPY_VERSION 1.9)
-                               if(MSVC_VERSION EQUAL 1900)
+                               if((MSVC_VERSION EQUAL 1900) OR (MSVC_VERSION EQUAL 1910))
                                        set(PYTHON_NUMPY_VERSION 1.11)
                                endif()
                                add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages