Camera tracking integration
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 1 Jul 2011 17:12:08 +0000 (17:12 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 1 Jul 2011 17:12:08 +0000 (17:12 +0000)
===========================

- Removed unneeded checking of marker==NULL
- Tracks could be named now.
- Implemented "Follow Track" constraint to "parent"
  objects to tracks from movie clip.
- Added operator to create such constraint for active object
  using clip and track from current context.

15 files changed:
release/scripts/startup/bl_ui/properties_object_constraint.py
release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/tracking.c
source/blender/editors/object/object_constraint.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_constraint.c
source/blender/makesrna/intern/rna_tracking.c

index 5f79dd3127ad15f9366776006df8533a5c90b4e6..f75f0fdd56cd21e80a1c2665ce4fc521b9d95511 100644 (file)
@@ -751,6 +751,10 @@ class ConstraintButtonsPanel():
         col = layout.column()
         col.prop(con, "rotation_range", text="Pivot When")
 
+    def FOLLOW_TRACK(self, context, layout, con):
+        layout.prop(con, "clip")
+        layout.prop(con, "track")
+
     def SCRIPT(self, context, layout, con):
         layout.label("Blender 2.5 has no py-constraints")
 
index 353103ac507da371f5787041f1592ec7340b9fa9..ddc2d14b4d261fef75b02248bc27e9ba0e21c29a 100644 (file)
 import bpy
 
 
+class CLIP_OT_apply_follow_track(bpy.types.Operator):
+    bl_idname = "clip.apply_follow_track"
+    bl_label = "Apply Follow Track"
+    bl_options = {'UNDO', 'REGISTER'}
+
+    @classmethod
+    def poll(cls, context):
+        if context.space_data.type != 'CLIP_EDITOR':
+            return False
+
+        sc = context.space_data
+        clip = sc.clip
+
+        return clip and clip.tracking.active_track and context.active_object
+
+    def execute(self, context):
+        ob = context.active_object
+        sc = context.space_data
+        clip = sc.clip
+        track = clip.tracking.active_track
+        constraint = None
+
+        for con in ob.constraints:
+            if con.type == 'FOLLOW_TRACK':
+                constraint = con
+                break
+
+        if constraint is None:
+            constraint = ob.constraints.new(type='FOLLOW_TRACK')
+
+        constraint.clip = sc.clip
+        constraint.track = track.name
+
+        return {'FINISHED'}
+
+
 class CLIP_HT_header(bpy.types.Header):
     bl_space_type = 'CLIP_EDITOR'
 
@@ -96,16 +132,17 @@ class CLIP_PT_track(bpy.types.Panel):
         sc = context.space_data
         clip = sc.clip
 
-        return clip and clip.tracking.act_track
+        return clip and clip.tracking.active_track
 
     def draw(self, context):
         layout = self.layout
         sc = context.space_data
         clip = context.space_data.clip
+        act_track = clip.tracking.active_track
 
-        layout.template_track(clip.tracking, "act_track", sc.clip_user, clip)
+        layout.prop(act_track, "name")
 
-        act_track = clip.tracking.act_track
+        layout.template_track(clip.tracking, "active_track", sc.clip_user, clip)
 
         if act_track:
             row = layout.row()
@@ -190,6 +227,7 @@ class CLIP_PT_test(bpy.types.Panel):
         layout = self.layout
         sc = context.space_data
 
+        layout.operator("clip.apply_follow_track")
         layout.operator("clip.track_to_fcurves")
 
 
index e1aa2baa948386d90d0078194d227026633c84f6..f30b459d6a07ea377103561758d0ba2c7544b6c4 100644 (file)
@@ -64,6 +64,9 @@ void BKE_tracking_sync(struct MovieTrackingContext *context);
 void BKE_tracking_sync_user(struct MovieClipUser *user, struct MovieTrackingContext *context);
 int BKE_tracking_next(struct MovieTrackingContext *context);
 
+void BKE_track_unique_name(struct MovieTracking *tracking, struct MovieTrackingTrack *track);
+struct MovieTrackingTrack *BKE_find_track_by_name(struct MovieTracking *tracking, const char *name);
+
 #define TRACK_SELECTED(track) ((track)->flag&SELECT || (track)->pat_flag&SELECT || (track)->search_flag&SELECT)
 #define TRACK_AREA_SELECTED(track, area) ((area)==TRACK_AREA_POINT?(track)->flag&SELECT : ((area)==TRACK_AREA_PAT?(track)->pat_flag&SELECT:(track)->search_flag&SELECT))
 
index 7be4744a224ba1c1494502d8b37633d9ffbae575..c16516f841e7e2a379b9a3e288ce7f7cd3f19dfe 100644 (file)
@@ -57,6 +57,8 @@
 #include "DNA_lattice_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_text_types.h"
+#include "DNA_tracking_types.h"
+#include "DNA_movieclip_types.h"
 
 
 #include "BKE_action.h"
@@ -75,6 +77,8 @@
 #include "BKE_idprop.h"
 #include "BKE_shrinkwrap.h"
 #include "BKE_mesh.h"
+#include "BKE_tracking.h"
+#include "BKE_movieclip.h"
 
 #ifdef WITH_PYTHON
 #include "BPY_extern.h"
@@ -3929,6 +3933,62 @@ static bConstraintTypeInfo CTI_PIVOT = {
        pivotcon_evaluate /* evaluate */
 };
 
+/* ----------- Follow Track ------------- */
+
+static void followtrack_new_data (void *cdata)
+{
+       bFollowTrackConstraint *data= (bFollowTrackConstraint *)cdata;
+
+       data->clip= NULL;
+}
+
+static void followtrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+       bFollowTrackConstraint *data= con->data;
+
+       func(con, (ID**)&data->clip, userdata);
+}
+
+static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
+{
+       bFollowTrackConstraint *data= con->data;
+       MovieClipUser user;
+       MovieTrackingTrack *track;
+       MovieTrackingMarker *marker;
+       float tx, ty;
+       int width, height;
+
+       if(!data->clip || !data->track[0])
+               return;
+
+       user.framenr= cob->scene->r.cfra;
+       BKE_movieclip_acquire_size(data->clip, &user, &width, &height);
+
+       track= BKE_find_track_by_name(&data->clip->tracking, data->track);
+       marker= BKE_tracking_get_marker(track, user.framenr);
+
+       tx= marker->pos[0]*width;
+       ty= marker->pos[1]*height;
+
+       translate_m4(cob->matrix, tx, ty, 0);
+}
+
+static bConstraintTypeInfo CTI_FOLLOWTRACK = {
+       CONSTRAINT_TYPE_FOLLOWTRACK, /* type */
+       sizeof(bFollowTrackConstraint), /* size */
+       "Follow Track", /* name */
+       "bFollowTrackConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       followtrack_id_looper, /* id looper */
+       NULL, /* copy data */
+       followtrack_new_data, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       followtrack_evaluate /* evaluate */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specific code.
@@ -3966,6 +4026,7 @@ static void constraints_init_typeinfo (void) {
        constraintsTypeInfo[23]= &CTI_TRANSLIKE;                /* Copy Transforms Constraint */
        constraintsTypeInfo[24]= &CTI_SAMEVOL;                  /* Maintain Volume Constraint */
        constraintsTypeInfo[25]= &CTI_PIVOT;                    /* Pivot Constraint */
+       constraintsTypeInfo[26]= &CTI_FOLLOWTRACK;              /* Follow Track Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only
index c2800410657a83a602c6309cf34a502321f33e11..9adbc35da5cd281ad612b7ca765e53e0c3ce468d 100644 (file)
@@ -51,6 +51,7 @@
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_windowmanager_types.h"
+#include "DNA_movieclip_types.h"
 
 #include "BKE_animsys.h"
 #include "BKE_action.h"
@@ -639,7 +640,15 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
                ListBase targets = {NULL, NULL};
                bConstraintTarget *ct;
                
-               if (cti && cti->get_constraint_targets) {
+               if(!cti)
+                       continue;
+
+               /* special case for FollowTrack -- it doesn't use targets to define relations */
+               if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
+                       dag_add_relation(dag,scenenode,node,DAG_RL_SCENE, "Scene Relation");
+                       addtoroot = 0;
+               }
+               else if (cti->get_constraint_targets) {
                        cti->get_constraint_targets(con, &targets);
                        
                        for (ct= targets.first; ct; ct= ct->next) {
@@ -2073,18 +2082,25 @@ static void dag_object_time_update_flags(Object *ob)
                        ListBase targets = {NULL, NULL};
                        bConstraintTarget *ct;
                        
-                       if (cti && cti->get_constraint_targets) {
-                               cti->get_constraint_targets(con, &targets);
-                               
-                               for (ct= targets.first; ct; ct= ct->next) {
-                                       if (ct->tar) {
-                                               ob->recalc |= OB_RECALC_OB;
-                                               break;
+                       if (cti) {
+                               /* special case for FollowTrack -- it doesn't use targets to define relations */
+                               if(cti->type==CONSTRAINT_TYPE_FOLLOWTRACK) {
+                                       ob->recalc |= OB_RECALC_OB;
+                               }
+                               else if (cti->get_constraint_targets) {
+                                       cti->get_constraint_targets(con, &targets);
+                                       
+                                       for (ct= targets.first; ct; ct= ct->next) {
+                                               if (ct->tar) {
+                                                       ob->recalc |= OB_RECALC_OB;
+                                                       break;
+                                               }
                                        }
+                                       
+                                       if (cti->flush_constraint_targets)
+                                               cti->flush_constraint_targets(con, &targets, 1);
                                }
                                
-                               if (cti->flush_constraint_targets)
-                                       cti->flush_constraint_targets(con, &targets, 1);
                        }
                }
        }
@@ -2442,6 +2458,19 @@ static void dag_id_flush_update(Scene *sce, ID *id)
                                                BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
                }
 
+               if(idtype == ID_MC) {
+                       for(obt=bmain->object.first; obt; obt= obt->id.next){
+                               bConstraint *con;
+                               for (con = obt->constraints.first; con; con=con->next) {
+                                       bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+                                       if(cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+                                               obt->recalc |= OB_RECALC_OB;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
                /* update editors */
                dag_editors_update(bmain, id);
        }
index 9a2b548d9283964b7fd2f63d6fed5265246f3f75..12a711962583692ef27a514b6df049514155e425 100644 (file)
@@ -30,6 +30,8 @@
  *  \ingroup bke
  */
 
+#include <stddef.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_movieclip_types.h"
@@ -663,3 +665,22 @@ int BKE_tracking_next(MovieTrackingContext *context)
 
        return ok;
 }
+
+void BKE_track_unique_name(MovieTracking *tracking, MovieTrackingTrack *track)
+{
+       BLI_uniquename(&tracking->tracks, track, "Track", '.', offsetof(MovieTrackingTrack, name), sizeof(track->name));
+}
+
+MovieTrackingTrack *BKE_find_track_by_name(MovieTracking *tracking, const char *name)
+{
+       MovieTrackingTrack *track= tracking->tracks.first;
+
+       while(track) {
+               if(!strcmp(track->name, name))
+                       return track;
+
+               track= track->next;
+       }
+
+       return NULL;
+}
index 450bd70a568f18e3644d1ea9c8720e4138421505..3b04cb28f0b060816c5096d9aac0cfcf3099ea56 100644 (file)
@@ -57,6 +57,7 @@
 #include "BKE_main.h"
 #include "BKE_object.h"
 #include "BKE_report.h"
+#include "BKE_tracking.h"
 #include "BIK_api.h"
 
 #ifdef WITH_PYTHON
@@ -404,6 +405,15 @@ static void test_constraints (Object *owner, bPoseChannel *pchan)
                                        data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
                                }
                        }
+                       else if (curcon->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+                               bFollowTrackConstraint *data = curcon->data;
+
+                               if(data->clip != NULL && data->track[0]) {
+                                       if (!BKE_find_track_by_name(&data->clip->tracking, data->track))
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                               }
+                               else curcon->flag |= CONSTRAINT_DISABLE;
+                       }
                        
                        /* Check targets for constraints */
                        if (cti && cti->get_constraint_targets) {
index 31cbae96cf7e06723f541cbf1e95555b4f71f4af..199a35e24fedfb5e414d3d0d53f38fae5e66cf80 100644 (file)
@@ -180,7 +180,7 @@ static void draw_track_path(SpaceClip *sc, MovieClip *clip, MovieTrackingTrack *
                return;
 
        marker= BKE_tracking_get_marker(track, sc->user.framenr);
-       if(marker==NULL || marker->flag&MARKER_DISABLED)
+       if(marker->flag&MARKER_DISABLED)
                return;
 
        framenr= marker->framenr;
@@ -432,10 +432,8 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl
        while(track) {
                marker= BKE_tracking_get_marker(track, sc->user.framenr);
 
-               if(marker) {
-                       draw_marker_outline(sc, track, marker);
-                       draw_marker_areas(sc, track, marker, 0, 0);
-               }
+               draw_marker_outline(sc, track, marker);
+               draw_marker_areas(sc, track, marker, 0, 0);
 
                track= track->next;
        }
@@ -448,8 +446,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl
 
                if(!act) {
                        marker= BKE_tracking_get_marker(track, sc->user.framenr);
-                       if(marker)
-                               draw_marker_areas(sc, track, marker, 0, 1);
+                       draw_marker_areas(sc, track, marker, 0, 1);
                }
 
                track= track->next;
@@ -458,9 +455,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, fl
        /* active marker would be displayed on top of everything else */
        if(sel_type==MCLIP_SEL_TRACK) {
                marker= BKE_tracking_get_marker(sel, sc->user.framenr);
-
-               if(marker)
-                       draw_marker_areas(sc, sel, marker, 1, 1);
+               draw_marker_areas(sc, sel, marker, 1, 1);
        }
 
        glPopMatrix();
@@ -510,14 +505,14 @@ void draw_clip_track_widget(const bContext *C, void *trackp, void *userp, void *
        if(track) {
                MovieTrackingMarker *marker= BKE_tracking_get_marker(track, user->framenr);
 
-               if(marker && marker->flag&MARKER_DISABLED) {
+               if(marker->flag&MARKER_DISABLED) {
                        glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
                        uiSetRoundBox(15);
                        uiDrawBox(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 3.0f);
 
                        ok= 1;
                }
-               else if(marker) {
+               else {
                        ImBuf* ibuf= BKE_movieclip_acquire_ibuf(clip, user);
 
                        if(ibuf && ibuf->rect) {
index 8bd0dfc16ee2347ad84c00237bfdf9df5f2e0374..bcfee08133d620be05e5df893a4303ae3105024e 100644 (file)
@@ -115,6 +115,7 @@ static void add_marker(SpaceClip *sc, float x, float y)
        search[1] /= (float)height;
 
        track= MEM_callocN(sizeof(MovieTrackingTrack), "add_marker_exec track");
+       strcpy(track->name, "Track");
 
        memset(&marker, 0, sizeof(marker));
        marker.pos[0]= x;
@@ -130,6 +131,7 @@ static void add_marker(SpaceClip *sc, float x, float y)
        BKE_tracking_insert_marker(track, &marker);
 
        BLI_addtail(&clip->tracking.tracks, track);
+       BKE_track_unique_name(&clip->tracking, track);
 
        BKE_movieclip_select_track(clip, track, TRACK_AREA_ALL, 0);
        BKE_movieclip_set_selection(clip, MCLIP_SEL_TRACK, track);
@@ -376,19 +378,17 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, MovieClip *clip, fl
                MovieTrackingMarker *marker= BKE_tracking_get_marker(cur, sc->user.framenr);
                float dist, d1, d2, d3;
 
-               if(marker) {
-                       d1= sqrtf((co[0]-marker->pos[0])*(co[0]-marker->pos[0])+
-                                         (co[1]-marker->pos[1])*(co[1]-marker->pos[1])); /* distance to marker point */
-                       d2= dist_to_rect(co, marker->pos, cur->pat_min, cur->pat_max); /* distance to search boundbox */
-                       d3= dist_to_rect(co, marker->pos, cur->search_min, cur->search_max); /* distance to search boundbox */
+               d1= sqrtf((co[0]-marker->pos[0])*(co[0]-marker->pos[0])+
+                                 (co[1]-marker->pos[1])*(co[1]-marker->pos[1])); /* distance to marker point */
+               d2= dist_to_rect(co, marker->pos, cur->pat_min, cur->pat_max); /* distance to search boundbox */
+               d3= dist_to_rect(co, marker->pos, cur->search_min, cur->search_max); /* distance to search boundbox */
 
-                       /* choose minimal distance. useful for cases of overlapped markers. */
-                       dist= MIN3(d1, d2, d3);
+               /* choose minimal distance. useful for cases of overlapped markers. */
+               dist= MIN3(d1, d2, d3);
 
-                       if(track==NULL || dist<mindist) {
-                               track= cur;
-                               mindist= dist;
-                       }
+               if(track==NULL || dist<mindist) {
+                       track= cur;
+                       mindist= dist;
                }
 
                cur= cur->next;
@@ -501,12 +501,10 @@ static int border_select_exec(bContext *C, wmOperator *op)
        while(track) {
                MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
 
-               if(marker) {
-                       if(BLI_in_rctf(&rectf, marker->pos[0], marker->pos[1])) {
-                               BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
+               if(BLI_in_rctf(&rectf, marker->pos[0], marker->pos[1])) {
+                       BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
 
-                               change= 1;
-                       }
+                       change= 1;
                }
 
                track= track->next;
@@ -586,12 +584,10 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        while(track) {
                MovieTrackingMarker *marker= BKE_tracking_get_marker(track, sc->user.framenr);
 
-               if(marker) {
-                       if(marker_inside_ellipse(marker, offset, ellipse)) {
-                               BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
+               if(marker_inside_ellipse(marker, offset, ellipse)) {
+                       BKE_tracking_track_flag(track, TRACK_AREA_ALL, SELECT, mode!=GESTURE_MODAL_SELECT);
 
-                               change= 1;
-                       }
+                       change= 1;
                }
 
                track= track->next;
@@ -1089,7 +1085,7 @@ static int track_to_fcurves_exec(bContext *C, wmOperator *op)
        while(fra<EFRA) {
                MovieTrackingMarker *marker= BKE_tracking_get_marker(track, fra);
 
-               if(marker && (marker->framenr&MARKER_DISABLED)==0) {
+               if((marker->framenr&MARKER_DISABLED)==0) {
                        FCurve *fcu;
 
                        fcu= verify_fcurve(act, ks->name, "location", 0, 1);
index 5c712e7c4ae0f7552606366cc6f149a249a9e8b6..d7366ed08d98ad3f547bdd72ba22409e10a84c3c 100644 (file)
@@ -352,6 +352,9 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
                SpaceClip *sc= (SpaceClip*)t->sa->spacedata.first;
                MovieClip *clip= ED_space_clip(sc);
 
+               /* objects could be parented to tracking data, so send this for viewport refresh */
+               WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
                WM_event_add_notifier(C, NC_MOVIECLIP|NA_EDITED, clip);
        }
 }
index b9afa00cb755e5e44a0a23706ff95db4ed55d032..8410bc45b65f80d195a9859b1444b94e479fff1a 100644 (file)
@@ -869,6 +869,8 @@ void recalcData(TransInfo *t)
 
                        track= track->next;
                }
+
+               DAG_id_tag_update(&clip->id, 0);
        }
 }
 
index 1d752fce4ef66aa4f7c2d2eab5723ffe5e504a6a..56ca39855791ebfa9c162ebbe7b40381f043ebd5 100644 (file)
@@ -408,6 +408,11 @@ typedef struct bShrinkwrapConstraint {
        char            pad[9];
 } bShrinkwrapConstraint;
 
+/* Follow Track constraints */
+typedef struct bFollowTrackConstraint {
+       struct MovieClip        *clip;
+       char    track[24];
+} bFollowTrackConstraint;
 
 /* ------------------------------------------ */
 
@@ -442,6 +447,7 @@ typedef enum eBConstraint_Types {
        CONSTRAINT_TYPE_TRANSLIKE,                      /* Copy transform matrix */
        CONSTRAINT_TYPE_SAMEVOL,                        /* Maintain volume during scaling */
        CONSTRAINT_TYPE_PIVOT,                          /* Pivot Constraint */
+       CONSTRAINT_TYPE_FOLLOWTRACK,            /* Follow Track Constraint */
        
        /* NOTE: no constraints are allowed to be added after this */
        NUM_CONSTRAINT_TYPES
index 933831419f52406567a60d8f61df133110dc904f..7abb521554c8d27050b18a8f20e9ef2398406e28 100644 (file)
@@ -70,6 +70,8 @@ typedef struct MovieTrackingBundle {
 typedef struct MovieTrackingTrack {
        struct MovieTrackingTrack *next, *prev;
 
+       char name[24];
+
        /* ** setings ** */
        float pat_min[2], pat_max[2];           /* positions of left-bottom and right-top corners of pattern (in unified 0..1 space) */
        float search_min[2], search_max[2];     /* positions of left-bottom and right-top corners of search area (in unified 0..1 space) */
index a75ff601d0859a24f126e7a30c238726d7e7c2d9..069b45773670a6959cad3d8c3cc69b12945b2b84 100644 (file)
@@ -69,6 +69,7 @@ EnumPropertyItem constraint_type_items[] ={
        {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", ""},
        {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", ""},
        {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", ""},
+       {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""},
        {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", ""},
        {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", ""},
        {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", ""},
@@ -158,6 +159,8 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
                        return &RNA_CopyTransformsConstraint;
                case CONSTRAINT_TYPE_PIVOT:
                        return &RNA_PivotConstraint;
+               case CONSTRAINT_TYPE_FOLLOWTRACK:
+                       return &RNA_FollowTrackConstraint;
                default:
                        return &RNA_UnknownType;
        }
@@ -1997,6 +2000,29 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
 }
 
+static void rna_def_constraint_follow_track(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna= RNA_def_struct(brna, "FollowTrackConstraint", "Constraint");
+       RNA_def_struct_ui_text(srna, "Follow Track Constraint", "Locks motion to the target motion track");
+       RNA_def_struct_sdna_from(srna, "bFollowTrackConstraint", "data");
+
+       /* movie clip */
+       prop= RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "clip");
+       RNA_def_property_ui_text(prop, "Movie Clip", "Movie Clip to get tracking data from");
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+       /* track */
+       prop= RNA_def_property(srna, "track", PROP_STRING, PROP_NONE);
+       RNA_def_property_string_sdna(prop, NULL, "track");
+       RNA_def_property_ui_text(prop, "Track", "Movie tracking track to follow");
+       RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
+}
+
 /* base struct for constraints */
 void RNA_def_constraint(BlenderRNA *brna)
 {
@@ -2107,6 +2133,7 @@ void RNA_def_constraint(BlenderRNA *brna)
        rna_def_constraint_damped_track(brna);
        rna_def_constraint_spline_ik(brna);
        rna_def_constraint_pivot(brna);
+       rna_def_constraint_follow_track(brna);
 }
 
 #endif
index 86d194f7184c265172b34ac4479b42c96536ee4f..120411d775cbe2cfd92e3b981777131e9e0f0e21 100644 (file)
@@ -55,6 +55,27 @@ static void rna_tracking_tracks_begin(CollectionPropertyIterator *iter, PointerR
        rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
 }
 
+void rna_trackingTrack_name_get(PointerRNA *ptr, char *value)
+{
+       MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+       BLI_strncpy(value, track->name, sizeof(track->name));
+}
+
+int rna_trackingTrack_name_length(PointerRNA *ptr)
+{
+       MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+       return strlen(track->name);
+}
+
+void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
+{
+       MovieClip *clip= (MovieClip *)ptr->id.data;
+       MovieTrackingTrack *track= (MovieTrackingTrack *)ptr->data;
+       BLI_strncpy(track->name, value, sizeof(track->name));
+
+       BKE_track_unique_name(&clip->tracking, track);
+}
+
 static void rna_tracking_trackerPattern_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
        MovieClip *clip= (MovieClip*)ptr->id.data;
@@ -194,6 +215,14 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
        srna= RNA_def_struct(brna, "MovieTrackingTrack", NULL);
        RNA_def_struct_ui_text(srna, "Movie tracking track data", "Match-moving track data for tracking");
 
+       /* name */
+       prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Name", "Unique name of track");
+       RNA_def_property_string_funcs(prop, "rna_trackingTrack_name_get", "rna_trackingTrack_name_length", "rna_trackingTrack_name_set");
+       RNA_def_property_string_maxlength(prop, MAX_ID_NAME);
+       RNA_def_property_update(prop, NC_MOVIECLIP|NA_EDITED, NULL);
+       RNA_def_struct_name_property(srna, prop);
+
        /* Pattern */
        prop= RNA_def_property(srna, "pattern_min", PROP_FLOAT, PROP_TRANSLATION);
        RNA_def_property_array(prop, 2);
@@ -282,7 +311,7 @@ static void rna_def_tracking(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
 
        /* active tracks */
-       prop= RNA_def_property(srna, "act_track", PROP_POINTER, PROP_NONE);
+       prop= RNA_def_property(srna, "active_track", PROP_POINTER, PROP_NONE);
        RNA_def_property_struct_type(prop, "MovieTrackingTrack");
        RNA_def_property_pointer_funcs(prop, "rna_tracking_active_track_get", NULL, NULL, NULL);
        RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");