UV Warp Modifier:
authorCampbell Barton <ideasman42@gmail.com>
Fri, 14 Dec 2012 04:07:30 +0000 (04:07 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 14 Dec 2012 04:07:30 +0000 (04:07 +0000)
Based on patch [#30837] UV Offset Modifier
by Pawel Kowal (pkowal)

- Allows you to setup a transformation between objects to apply to UV coords.
- Option to select which axis apply to U/V.
- Option to select the UV center (needed for transformations that scale or rotate).
- Uses from/to objects in a similar way to the Warp modifier.
- Vertex group can be used to adjust influence.

release/scripts/startup/bl_ui/properties_data_modifier.py
source/blender/editors/space_outliner/outliner_draw.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/MOD_modifiertypes.h
source/blender/modifiers/intern/MOD_util.c
source/blender/modifiers/intern/MOD_uvwarp.c [new file with mode: 0644]

index 62461d800f61ac5f104cc5d7d0b22bba012662db..e90d1616929642f9306394845fd1cb9a88c7536a 100644 (file)
@@ -1032,5 +1032,47 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
     def TRIANGULATE(self, layout, ob, md):
         layout.prop(md, "use_beauty")
 
+    def UV_WARP(self, layout, ob, md):
+        split = layout.split()
+        col = split.column()
+        col.prop(md, "center");
+
+        col = split.column()
+        col.label(text="UV Axis:")
+        col.prop(md, "axis_u", text="");
+        col.prop(md, "axis_v", text="");
+
+        split = layout.split()
+        col = split.column()
+        col.label(text="From:")
+        col.prop(md, "object_from", text="")
+
+        col = split.column()
+        col.label(text="To:")
+        col.prop(md, "object_to", text="")
+
+        split = layout.split()
+        col = split.column()
+        obj = md.object_from
+        if obj and obj.type == 'ARMATURE':
+            col.label(text="Bone:")
+            col.prop_search(md, "bone_from", obj.data, "bones", text="")
+
+        col = split.column()
+        obj = md.object_to
+        if obj and obj.type == 'ARMATURE':
+            col.label(text="Bone:")
+            col.prop_search(md, "bone_to", obj.data, "bones", text="")
+
+        split = layout.split()
+
+        col = split.column()
+        col.label(text="Vertex Group:")
+        col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+
+        col = split.column()
+        col.label(text="UV Map:")
+        col.prop_search(md, "uv_layer", ob.data, "uv_textures", text="")
+
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)
index abe0ef253f97e6158e661bc5576c25340b942f73..186a3432ab1081f5a8554d7bf78ce15df3bc93df 100644 (file)
@@ -996,6 +996,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
                                        case eModifierType_Array:
                                                UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
                                        case eModifierType_UVProject:
+                                       case eModifierType_UVWarp:  /* TODO, get own icon */
                                                UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
                                        case eModifierType_Displace:
                                                UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
index 68aa7600cd1d681147058d2674b936b40d28b709..089103c66e58cfb33fd3c544f2e25f32a29adbdd 100644 (file)
@@ -76,7 +76,8 @@ typedef enum ModifierType {
        eModifierType_Remesh            = 41,
        eModifierType_Skin              = 42,
        eModifierType_LaplacianSmooth   = 43,
-       eModifierType_Triangulate               = 44,
+       eModifierType_Triangulate       = 44,
+       eModifierType_UVWarp          = 45,
        NUM_MODIFIER_TYPES
 } ModifierType;
 
@@ -1140,4 +1141,20 @@ typedef struct LaplacianSmoothModifierData {
        short flag, repeat;
 } LaplacianSmoothModifierData;
 
-#endif
+typedef struct UVWarpModifierData {
+       ModifierData modifier;
+
+       char axis_u, axis_v;
+       char pad[6];
+       float center[2];       /* used for rotate/scale */
+
+       struct Object *object_src;  /* source */
+       char bone_src[64];     /* optional name of bone target, MAX_ID_NAME-2 */
+       struct Object *object_dst;  /* target */
+       char bone_dst[64];     /* optional name of bone target, MAX_ID_NAME-2 */
+
+       char vgroup_name[64];   /* optional vertexgroup name, MAX_VGROUP_NAME */
+       char uvlayer_name[64];  /* MAX_CUSTOMDATA_LAYER_NAME */
+} UVWarpModifierData;
+
+#endif  /* __DNA_MODIFIER_TYPES_H__ */
index 0e5f9c5fa5fd8fe68260b2dbffcfa5fffb2ce113..4795338c85c1c6ec715f660906996fad06394f1b 100644 (file)
@@ -587,6 +587,7 @@ extern StructRNA RNA_TransformConstraint;
 extern StructRNA RNA_TransformSequence;
 extern StructRNA RNA_UILayout;
 extern StructRNA RNA_UIListItem;
+extern StructRNA RNA_UVWarpModifier;
 extern StructRNA RNA_UVProjectModifier;
 extern StructRNA RNA_UVProjector;
 extern StructRNA RNA_UnitSettings;
index a2b0945fb46115d93912e14bbc880be78fd55d4a..e1489d821a09df408d581ffe829a8e4ff454dbef 100644 (file)
@@ -59,6 +59,7 @@
 EnumPropertyItem modifier_type_items[] = {
        {0, "", 0, N_("Modify"), ""},
        {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
+       {eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""},
        {eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Edit", ""},
        {eModifierType_WeightVGMix, "VERTEX_WEIGHT_MIX", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Mix", ""},
        {eModifierType_WeightVGProximity, "VERTEX_WEIGHT_PROXIMITY", ICON_MOD_VERTEX_WEIGHT,
@@ -129,7 +130,7 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
 {
        ModifierData *md = (ModifierData *)ptr->data;
 
-       switch (md->type) {
+       switch ((ModifierType)md->type) {
                case eModifierType_Subsurf:
                        return &RNA_SubsurfModifier;
                case eModifierType_Lattice:
@@ -216,9 +217,16 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
                        return &RNA_LaplacianSmoothModifier;
                case eModifierType_Triangulate:
                        return &RNA_TriangulateModifier;
-               default:
+               case eModifierType_UVWarp:
+                       return &RNA_UVWarpModifier;
+               /* Default */
+               case eModifierType_None:
+               case eModifierType_ShapeKey:
+               case NUM_MODIFIER_TYPES:
                        return &RNA_Modifier;
        }
+
+       return &RNA_Modifier;
 }
 
 static void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
@@ -738,6 +746,18 @@ static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value)
        md->bevel_angle = (int)value;
 }
 
+static void rna_UVWarpModifier_vgroup_set(PointerRNA *ptr, const char *value)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData*)ptr->data;
+       rna_object_vgroup_name_set(ptr, value, umd->vgroup_name, sizeof(umd->vgroup_name));
+}
+
+static void rna_UVWarpModifier_uvlayer_set(PointerRNA *ptr, const char *value)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData*)ptr->data;
+       rna_object_uvlayer_name_set(ptr, value, umd->uvlayer_name, sizeof(umd->uvlayer_name));
+}
+
 #else
 
 static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -2773,6 +2793,75 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
 #endif
 }
 
+static void rna_def_modifier_uvwarp(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       static EnumPropertyItem uvwarp_axis[] = {
+               {0, "X", 0, "X", ""},
+               {1, "Y", 0, "Y", ""},
+               {2, "Z", 0, "Z", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       srna = RNA_def_struct(brna, "UVWarpModifier", "Modifier");
+       RNA_def_struct_ui_text(srna, "UVWarp Modifier", "Add target position to uv coordinates");
+       RNA_def_struct_sdna(srna, "UVWarpModifierData");
+       RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
+
+       prop = RNA_def_property(srna, "axis_u", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "axis_u");
+       RNA_def_property_enum_items(prop, uvwarp_axis);
+       RNA_def_property_ui_text(prop, "U-Axis", "Pole axis for rotation");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "axis_v", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "axis_v");
+       RNA_def_property_enum_items(prop, uvwarp_axis);
+       RNA_def_property_ui_text(prop, "V-Axis", "Pole axis for rotation");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "center");
+       RNA_def_property_ui_text(prop, "UV Center", "Center point for rotate/scale");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "object_src");
+       RNA_def_property_ui_text(prop, "Target", "Object defining offset");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+       prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "bone_src");
+       RNA_def_property_ui_text(prop, "Sub-Target", "Bone defining offset");
+       RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+       prop = RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "object_dst");
+       RNA_def_property_ui_text(prop, "Target", "Object defining offset");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+       prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "bone_dst");
+       RNA_def_property_ui_text(prop, "Sub-Target", "Bone defining offset");
+       RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+       prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "vgroup_name");
+       RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_vgroup_set");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
+       RNA_def_property_ui_text(prop, "UV Layer", "UV Layer name");
+       RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_uvlayer_set");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+}
+
 static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), StructRNA *srna)
 {
        static EnumPropertyItem weightvg_mask_tex_map_items[] = {
@@ -3480,6 +3569,7 @@ void RNA_def_modifier(BlenderRNA *brna)
        rna_def_modifier_smoke(brna);
        rna_def_modifier_solidify(brna);
        rna_def_modifier_screw(brna);
+       rna_def_modifier_uvwarp(brna);
        rna_def_modifier_weightvgedit(brna);
        rna_def_modifier_weightvgmix(brna);
        rna_def_modifier_weightvgproximity(brna);
index cf3bb05849ae741389eb76ffda0cae9e05e7807a..332090951646bfb1e030c70bc981479ee1a9756e 100644 (file)
@@ -64,8 +64,8 @@ set(SRC
        intern/MOD_fluidsim.c
        intern/MOD_fluidsim_util.c
        intern/MOD_hook.c
-       intern/MOD_lattice.c
        intern/MOD_laplaciansmooth.c
+       intern/MOD_lattice.c
        intern/MOD_mask.c
        intern/MOD_meshdeform.c
        intern/MOD_mirror.c
@@ -86,7 +86,9 @@ set(SRC
        intern/MOD_solidify.c
        intern/MOD_subsurf.c
        intern/MOD_surface.c
+       intern/MOD_triangulate.c
        intern/MOD_util.c
+       intern/MOD_uvwarp.c
        intern/MOD_uvproject.c
        intern/MOD_warp.c
        intern/MOD_wave.c
@@ -94,7 +96,6 @@ set(SRC
        intern/MOD_weightvgedit.c
        intern/MOD_weightvgmix.c
        intern/MOD_weightvgproximity.c
-       intern/MOD_triangulate.c
 
        MOD_modifiertypes.h
        intern/MOD_boolean_util.h
index 290ba193567584feee3d3846c8958c53f9102205..17e903e9ebb5a4c3b39c414d1bcdf46331e605db 100644 (file)
@@ -77,6 +77,7 @@ extern ModifierTypeInfo modifierType_Remesh;
 extern ModifierTypeInfo modifierType_Skin;
 extern ModifierTypeInfo modifierType_LaplacianSmooth;
 extern ModifierTypeInfo modifierType_Triangulate;
+extern ModifierTypeInfo modifierType_UVWarp;
 
 /* MOD_util.c */
 void modifier_type_init(ModifierTypeInfo *types[]);
index a27d5e5e03b331ba5fce7883097fc87c3cfa4572..6c2f68891afece3829c5a5556b83bc7fd2bff034 100644 (file)
@@ -279,5 +279,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
        INIT_TYPE(Skin);
        INIT_TYPE(LaplacianSmooth);
        INIT_TYPE(Triangulate);
+       INIT_TYPE(UVWarp);
 #undef INIT_TYPE
 }
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
new file mode 100644 (file)
index 0000000..05e8d0d
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Pawel Kowal, Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_uvwarp.c
+ *  \ingroup modifiers
+ */
+
+#include <string.h>
+
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_action.h"  /* BKE_pose_channel_find_name */
+#include "BKE_cdderivedmesh.h"
+#include "BKE_deform.h"
+#include "BKE_modifier.h"
+
+#include "depsgraph_private.h"
+
+#include "MOD_util.h"
+
+
+static void uv_warp_from_mat4_pair(float uv_dst[2], const float uv_src[2], float warp_mat[4][4],
+                                     int axis_u, int axis_v)
+{
+       float tuv[3] = {0.0f};
+
+       tuv[axis_u] = uv_src[0];
+       tuv[axis_v] = uv_src[1];
+
+       mul_m4_v3(warp_mat, tuv);
+
+       uv_dst[0] = tuv[axis_u];
+       uv_dst[1] = tuv[axis_v];
+}
+
+static void initData(ModifierData *md)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData *) md;
+       umd->axis_u = 0;
+       umd->axis_v = 1;
+       copy_v2_fl(umd->center, 0.5f);
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+       UVWarpModifierData *umd  = (UVWarpModifierData *)md;
+       UVWarpModifierData *tumd = (UVWarpModifierData *)target;
+
+       tumd->axis_u = umd->axis_u;
+       tumd->axis_v = umd->axis_v;
+       copy_v2_v2(tumd->center, umd->center);
+       tumd->object_src = umd->object_src;
+       BLI_strncpy(tumd->bone_src, umd->bone_src, sizeof(tumd->bone_src));
+       tumd->object_dst = umd->object_dst;
+       BLI_strncpy(tumd->bone_dst, umd->bone_dst, sizeof(tumd->bone_dst));
+       BLI_strncpy(tumd->vgroup_name, umd->vgroup_name, sizeof(tumd->vgroup_name));
+       BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name));
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData *)md;
+       CustomDataMask dataMask = 0;
+
+       /* ask for vertexgroups if we need them */
+       if (umd->vgroup_name[0])
+               dataMask |= CD_MASK_MDEFORMVERT;
+
+       return dataMask;
+}
+
+static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename)
+{
+       bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename);
+       if (pchan) {
+               mult_m4_m4m4(mat, ob->obmat, pchan->pose_mat);
+       }
+       else {
+               copy_m4_m4(mat, ob->obmat);
+       }
+}
+
+#define OMP_LIMIT 1000
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+                                  DerivedMesh *dm,
+                                  ModifierApplyFlag UNUSED(flag))
+{
+       UVWarpModifierData *umd = (UVWarpModifierData *) md;
+       int i, numPolys, numLoops;
+       MPoly *mpoly;
+       MLoop *mloop;
+       MLoopUV *mloopuv;
+       MDeformVert *dvert;
+       int defgrp_index;
+       char uvname[MAX_CUSTOMDATA_LAYER_NAME];
+       float mat_src[4][4];
+       float mat_dst[4][4];
+       float imat_dst[4][4];
+       float warp_mat[4][4];
+       const int axis_u = umd->axis_u;
+       const int axis_v = umd->axis_v;
+
+       /* make sure there are UV Maps available */
+       if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
+               return dm;
+       }
+       else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
+               modifier_setError(md, "from/to objects must be set");
+               return dm;
+       }
+
+       /* make sure anything moving UVs is available */
+       matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
+       matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);
+
+       invert_m4_m4(imat_dst, mat_dst);
+       mult_m4_m4m4(warp_mat, imat_dst, mat_src);
+
+       /* apply warp */
+       if (!is_zero_v2(umd->center)) {
+               float mat_cent[4][4];
+               float imat_cent[4][4];
+
+               unit_m4(mat_cent);
+               mat_cent[3][axis_u] = umd->center[0];
+               mat_cent[3][axis_v] = umd->center[1];
+
+               invert_m4_m4(imat_cent, mat_cent);
+
+               mult_m4_m4m4(warp_mat, warp_mat, imat_cent);
+               mult_m4_m4m4(warp_mat, mat_cent, warp_mat);
+       }
+
+       /* make sure we're using an existing layer */
+       CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);
+
+       numPolys = dm->getNumPolys(dm);
+       numLoops = dm->getNumLoops(dm);
+
+       mpoly = dm->getPolyArray(dm);
+       mloop = dm->getLoopArray(dm);
+       /* make sure we are not modifying the original UV map */
+       mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops);
+       modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index);
+
+       if (dvert) {
+#pragma omp parallel for if (numPolys > OMP_LIMIT)
+               for (i = 0; i < numPolys; i++) {
+                       float uv[2];
+                       MPoly *mp     = &mpoly[i];
+                       MLoop *ml     = &mloop[mp->loopstart];
+                       MLoopUV *mluv = &mloopuv[mp->loopstart];
+                       int l;
+                       for (l = 0; l < mp->totloop; l++, ml++, mluv++) {
+                               const float weight = defvert_find_weight(&dvert[ml->v], defgrp_index);
+                               uv_warp_from_mat4_pair(uv, mluv->uv, warp_mat, axis_u, axis_v);
+                               interp_v2_v2v2(mluv->uv, mluv->uv, uv, weight);
+                       }
+               }
+       }
+       else {
+#pragma omp parallel for if (numPolys > OMP_LIMIT)
+               for (i = 0; i < numPolys; i++) {
+                       MPoly *mp     = &mpoly[i];
+                       // MLoop *ml     = &mloop[mp->loopstart];
+                       MLoopUV *mluv = &mloopuv[mp->loopstart];
+                       int l;
+                       for (l = 0; l < mp->totloop; l++, /* ml++, */ mluv++) {
+                               uv_warp_from_mat4_pair(mluv->uv, mluv->uv, warp_mat, axis_u, axis_v);
+                       }
+               }
+       }
+
+       dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+
+       return dm;
+}
+
+static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
+                                    struct BMEditMesh *UNUSED(editData),
+                                    DerivedMesh *derivedData)
+{
+       return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE);
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData *) md;
+
+       walk(userData, ob, &umd->object_dst);
+       walk(userData, ob, &umd->object_src);
+}
+
+static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
+                                Object *obj, const char *bonename)
+{
+       if (obj) {
+               DagNode *curNode = dag_get_node(forest, obj);
+
+               if (bonename[0])
+                       dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "UVWarp Modifier");
+               else
+                       dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "UVWarp Modifier");
+       }
+}
+
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+                           struct Scene *UNUSED(scene),
+                           Object *UNUSED(ob),
+                           DagNode *obNode)
+{
+       UVWarpModifierData *umd = (UVWarpModifierData *) md;
+
+       uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
+       uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
+}
+
+ModifierTypeInfo modifierType_UVWarp = {
+       /* name */              "UVWarp",
+       /* structName */        "UVWarpModifierData",
+       /* structSize */        sizeof(UVWarpModifierData),
+       /* type */              eModifierTypeType_NonGeometrical,
+       /* flags */             eModifierTypeFlag_AcceptsMesh |
+                               eModifierTypeFlag_SupportsEditmode |
+                               eModifierTypeFlag_EnableInEditmode,
+       /* copyData */          copyData,
+       /* deformVerts */       NULL,
+       /* deformMatrices */    NULL,
+       /* deformVertsEM */     NULL,
+       /* deformMatricesEM */  NULL,
+       /* applyModifier */     applyModifier,
+       /* applyModifierEM */   applyModifierEM,
+       /* initData */          initData,
+       /* requiredDataMask */  requiredDataMask,
+       /* freeData */          NULL,
+       /* isDisabled */        NULL,
+       /* updateDepgraph */    updateDepgraph,
+       /* dependsOnTime */     NULL,
+       /* dependsOnNormals */  NULL,
+       /* foreachObjectLink */ foreachObjectLink,
+       /* foreachIDLink */     NULL,
+       /* foreachTexLink */    NULL,
+};