Merged revision(s) 59108-59184 from trunk/blender into soc-2013-dingto.
authorThomas Dinges <blender@dingto.org>
Fri, 16 Aug 2013 12:50:13 +0000 (12:50 +0000)
committerThomas Dinges <blender@dingto.org>
Fri, 16 Aug 2013 12:50:13 +0000 (12:50 +0000)
112 files changed:
build_files/scons/tools/Blender.py
doc/python_api/rst/bge.logic.rst
doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
extern/libmv/libmv-capi.cc
extern/libmv/libmv-capi.h
extern/libmv/libmv-capi_stub.cc
extern/libmv/libmv/multiview/euclidean_resection.cc
extern/libmv/libmv/multiview/euclidean_resection.h
extern/libmv/libmv/tracking/track_region.cc
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/Python/AUD_PyAPI.cpp
intern/audaspace/intern/AUD_IHandle.h
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
intern/audaspace/intern/AUD_Space.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/osl/osl_closures.h
intern/guardedalloc/intern/mallocn.c
release/scripts/modules/bpy_extras/image_utils.py
release/scripts/startup/bl_operators/add_mesh_torus.py
release/scripts/startup/bl_ui/properties_mask_common.py
release/scripts/startup/bl_ui/space_clip.py
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenlib/BLI_array.h
source/blender/blenlib/BLI_linklist.h
source/blender/blenlib/BLI_math_base.h
source/blender/blenlib/intern/BLI_array.c
source/blender/blenlib/intern/BLI_linklist.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_marking.c
source/blender/bmesh/intern/bmesh_marking.h
source/blender/bmesh/intern/bmesh_queries.c
source/blender/bmesh/operators/bmo_edgenet.c
source/blender/bmesh/tools/bmesh_edgesplit.c
source/blender/compositor/CMakeLists.txt
source/blender/compositor/intern/COM_Converter.cpp
source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp [new file with mode: 0644]
source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h [new file with mode: 0644]
source/blender/compositor/operations/COM_ImageOperation.cpp
source/blender/compositor/operations/COM_ImageOperation.h
source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp [new file with mode: 0644]
source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h [new file with mode: 0644]
source/blender/editors/include/ED_transform.h
source/blender/editors/mask/mask_relationships.c
source/blender/editors/mask/mask_shapekey.c
source/blender/editors/mesh/editmesh_rip.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_graph_ops.c
source/blender/editors/space_clip/clip_intern.h
source/blender/editors/space_clip/clip_utils.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_clip/tracking_select.c
source/blender/editors/space_file/file_panels.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_mask_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesrna/intern/rna_ID.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/makesrna/intern/rna_curve.c
source/blender/makesrna/intern/rna_mask.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_tracking.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_composite.h
source/blender/nodes/NOD_static_types.h
source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c [new file with mode: 0644]
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ActionActuator.h
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_ArmatureObject.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/BL_Action.cpp
source/gameengine/Ketsji/BL_Action.h
source/gameengine/Ketsji/BL_ActionManager.cpp
source/gameengine/Ketsji/BL_ActionManager.h
source/gameengine/Ketsji/KX_Dome.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp

index 24bdd32ed2623c1f240bc227f6c4a8a38bc6fa10..ee2399500d03a6bfc1dae9de63211166adedc00c 100644 (file)
@@ -151,12 +151,6 @@ def setup_staticlibs(lenv):
         libincs += Split(lenv['BF_JACK_LIBPATH'])
     if lenv['WITH_BF_SNDFILE']:
         libincs += Split(lenv['BF_SNDFILE_LIBPATH'])
-    if lenv['WITH_BF_OPENEXR']:
-        libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
-        if lenv['WITH_BF_STATICOPENEXR']:
-            statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
-    if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
-        statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
     if lenv['WITH_BF_TIFF']:
         libincs += Split(lenv['BF_TIFF_LIBPATH'])
         if lenv['WITH_BF_STATICTIFF']:
@@ -212,6 +206,12 @@ def setup_staticlibs(lenv):
         libincs += Split(lenv['BF_OIIO_LIBPATH'])
         if lenv['WITH_BF_STATICOIIO']:
             statlibs += Split(lenv['BF_OIIO_LIB_STATIC'])
+    if lenv['WITH_BF_OPENEXR']:
+        libincs += Split(lenv['BF_OPENEXR_LIBPATH'])
+        if lenv['WITH_BF_STATICOPENEXR']:
+            statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC'])
+    if lenv['WITH_BF_ZLIB'] and lenv['WITH_BF_STATICZLIB']:
+        statlibs += Split(lenv['BF_ZLIB_LIB_STATIC'])
 
     if lenv['WITH_BF_OCIO']:
         libincs += Split(lenv['BF_OCIO_LIBPATH'])
index c7915ee5279d60f5a0d42f096513c571f6d6ca5d..3a79d32d91799bcb2f231e44277d5263fa61bc37 100644 (file)
@@ -1114,6 +1114,19 @@ See :class:`bge.types.KX_GameObject.playAction`
    
    :value: 2
 
+.. _gameobject-playaction-blend:
+
+.. data:: KX_ACTION_BLEND_BLEND
+
+   Blend layers using linear interpolation
+
+   :value: 0
+
+.. data:: KX_ACTION_BLEND_ADD
+
+   Adds the layers together
+
+   :value: 1
 
 -------------
 Mouse Buttons
index a9c91735f917bd6a10e3ab4a7a9c955abc459968..3be148556ef36e97231b7f5d855ecb664aa7afab 100644 (file)
@@ -776,7 +776,7 @@ base class --- :class:`SCA_IObject`
       Return the value matching key, or the default value if its not found.
       :return: The key value or a default.
 
-   .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)
+   .. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=KX_ACTION_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0, blend_mode=KX_ACTION_BLEND_BLEND)
 
       Plays an action.
       
@@ -794,12 +794,14 @@ base class --- :class:`SCA_IObject`
       :type blendin: float
       :arg play_mode: the play mode
       :type play_mode: one of :ref:`these constants <gameobject-playaction-mode>`
-      :arg layer_weight: how much of the previous layer to use for blending (0 = add)
+      :arg layer_weight: how much of the previous layer to use for blending
       :type layer_weight: float
       :arg ipo_flags: flags for the old IPO behaviors (force, etc)
       :type ipo_flags: int bitfield
       :arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
       :type speed: float
+         :arg blend_mode: how to blend this layer with previous layers
+         :type blend_mode: one of :ref:`these constants <gameobject-playaction-blend>`
 
    .. method:: stopAction(layer=0)
       
index 063c63f9266b59eb9b3be8288c7bbef1632c6dd6..e1fd509d581c43fe7442db539757d01f912d23a9 100644 (file)
@@ -58,6 +58,8 @@
 #include "libmv/simple_pipeline/reconstruction_scale.h"
 #include "libmv/simple_pipeline/keyframe_selection.h"
 
+#include "libmv/multiview/homography.h"
+
 #ifdef _MSC_VER
 #  define snprintf _snprintf
 #endif
@@ -1080,4 +1082,28 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
        }
 }
 
+void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
+                                                 double H[3][3], double expected_precision)
+{
+       libmv::Mat x1_mat, x2_mat;
+       libmv::Mat3 H_mat;
+
+       x1_mat.resize(2, num_points);
+       x2_mat.resize(2, num_points);
+
+       for (int i = 0; i < num_points; i++) {
+               x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]);
+               x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]);
+       }
+
+       LG << "x1: " << x1_mat;
+       LG << "x2: " << x2_mat;
+
+       libmv::Homography2DFromCorrespondencesLinear(x1_mat, x2_mat, &H_mat, expected_precision);
+
+       LG << "H: " << H_mat;
+
+       memcpy(H, H_mat.data(), 9 * sizeof(double));
+}
+
 #endif
index 7c91881fe71638c0fc539ca12d7ddaedc9f4ace7..37aab2465ed76480cc7046cdf8240df3cdc5f5df 100644 (file)
@@ -159,6 +159,9 @@ void libmv_cameraIntrinsicsApply(const libmv_CameraIntrinsicsOptions *libmv_came
 void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options,
                                   double x, double y, double *x1, double *y1);
 
+void libmv_homography2DFromCorrespondencesLinear(double (*x1)[2], double (*x2)[2], int num_points,
+                                                 double H[3][3], double expected_precision);
+
 #ifdef __cplusplus
 }
 #endif
index 36977eb58bab11f64b21260448ce41bc9b1da60c..59a3fe89398029354da9fad22471222219ad3ae2 100644 (file)
@@ -277,4 +277,13 @@ void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_cam
        *y1 = (y - principal_y) / focal_length;
 }
 
+void libmv_homography2DFromCorrespondencesLinear(double (* /* x1 */)[2], double (* /* x2 */)[2], int /* num_points */,
+                                                 double H[3][3], double /* expected_precision */)
+{
+       memset(H, 0, sizeof(H));
+       H[0][0] = 1.0f;
+       H[1][1] = 1.0f;
+       H[2][2] = 1.0f;
+}
+
 #endif  // ifndef WITH_LIBMV
index 10c7330770f6480bb4d5a5243eb6ad670ccf6b77..d5421b9691ee0b4c9e8478bd9fbb866f49fc0b35 100644 (file)
@@ -34,6 +34,11 @@ namespace libmv {
 namespace euclidean_resection {
 
 typedef unsigned int uint;
+  
+bool EuclideanResectionPPnP(const Mat2X &x_camera,
+                            const Mat3X &X_world,
+                            Mat3 *R, Vec3 *t,
+                            double tolerance);
 
 bool EuclideanResection(const Mat2X &x_camera,
                         const Mat3X &X_world,
@@ -47,6 +52,9 @@ bool EuclideanResection(const Mat2X &x_camera,
     case RESECTION_EPNP:
       return EuclideanResectionEPnP(x_camera, X_world, R, t, success_threshold);
       break;
+    case RESECTION_PPNP:
+      return EuclideanResectionPPnP(x_camera, X_world, R, t, success_threshold);
+      break;
     default:
       LOG(FATAL) << "Unknown resection method.";
   }
@@ -674,6 +682,107 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera,
   // TODO(julien): Improve the solutions with non-linear refinement.
   return true;
 }
+  
+/*
+ Straight from the paper:
+ http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
+ function [R T] = ppnp(P,S,tol)
+ % input
+ % P  : matrix (nx3) image coordinates in camera reference [u v 1]
+ % S  : matrix (nx3) coordinates in world reference [X Y Z]
+ % tol: exit threshold
+ %
+ % output
+ % R : matrix (3x3) rotation (world-to-camera)
+ % T : vector (3x1) translation (world-to-camera)
+ %
+ n = size(P,1);
+ Z = zeros(n);
+ e = ones(n,1);
+ A = eye(n)-((e*e’)./n);
+ II = e./n;
+ err = +Inf;
+ E_old = 1000*ones(n,3);
+ while err>tol
+   [U,˜,V] = svd(P’*Z*A*S);
+   VT = V’;
+   R=U*[1 0 0; 0 1 0; 0 0 det(U*VT)]*VT;
+   PR = P*R;
+   c = (S-Z*PR)’*II;
+   Y = S-e*c’;
+   Zmindiag = diag(PR*Y’)./(sum(P.*P,2));
+   Zmindiag(Zmindiag<0)=0;
+   Z = diag(Zmindiag);
+   E = Y-Z*PR;
+   err = norm(E-E_old,’fro’);
+   E_old = E;
+ end
+ T = -R*c;
+ end
+ */
+// TODO(keir): Re-do all the variable names and add comments matching the paper.
+// This implementation has too much of the terseness of the original. On the
+// other hand, it did work on the first try.
+bool EuclideanResectionPPnP(const Mat2X &x_camera,
+                            const Mat3X &X_world,
+                            Mat3 *R, Vec3 *t,
+                            double tolerance) {
+  int n = x_camera.cols();
+  Mat Z = Mat::Zero(n, n);
+  Vec e = Vec::Ones(n);
+  Mat A = Mat::Identity(n, n) - (e * e.transpose() / n);
+  Vec II = e / n;
+  
+  Mat P(n, 3);
+  P.col(0) = x_camera.row(0);
+  P.col(1) = x_camera.row(1);
+  P.col(2).setConstant(1.0);
+  
+  Mat S = X_world.transpose();
+  
+  double error = std::numeric_limits<double>::infinity();
+  Mat E_old = 1000 * Mat::Ones(n, 3);
+  
+  Vec3 c;
+  Mat E(n, 3);
+  
+  int iteration = 0;
+  tolerance = 1e-5;
+  // TODO(keir): The limit of 100 can probably be reduced, but this will require
+  // some investigation.
+  while (error > tolerance && iteration < 100) {
+    Mat3 tmp = P.transpose() * Z * A * S;
+    Eigen::JacobiSVD<Mat3> svd(tmp, Eigen::ComputeFullU | Eigen::ComputeFullV);
+    Mat3 U = svd.matrixU();
+    Mat3 VT = svd.matrixV().transpose();
+    Vec3 s;
+    s << 1, 1, (U * VT).determinant();
+    *R = U * s.asDiagonal() * VT;
+    Mat PR = P * *R;  // n x 3
+    c = (S - Z*PR).transpose() * II;
+    Mat Y = S - e*c.transpose();  // n x 3
+    Vec Zmindiag = (PR * Y.transpose()).diagonal()
+        .cwiseQuotient(P.rowwise().squaredNorm());
+    for (int i = 0; i < n; ++i) {
+      Zmindiag[i] = std::max(Zmindiag[i], 0.0);
+    }
+    Z = Zmindiag.asDiagonal();
+    E = Y - Z*PR;
+    error = (E - E_old).norm();
+    LOG(INFO) << "PPnP error(" << (iteration++) << "): " << error;
+    E_old = E;
+  }
+  *t = -*R*c;
+
+  // TODO(keir): Figure out what the failure cases are. Is it too many
+  // iterations? Spend some time going through the math figuring out if there
+  // is some way to detect that the algorithm is going crazy, and return false.
+  return true;
+}
+
 
 }  // namespace resection
 }  // namespace libmv
index 1a329702c2a6e5aff465140ffc9cc5729e7772bb..ff9bccdd5c9fb51333d6b9f66fc266b7af14670f 100644 (file)
@@ -33,6 +33,10 @@ enum ResectionMethod {
   // The "EPnP" algorithm by Lepetit et al.
   // http://cvlab.epfl.ch/~lepetit/papers/lepetit_ijcv08.pdf
   RESECTION_EPNP,
+  
+  // The Procrustes PNP algorithm ("PPnP")
+  // http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
+  RESECTION_PPNP
 };
 
 /**
index 6e9fb95654d34e5ef2d1df9c1a591855de04dd55..349d84b381764802202c851a870e0aee0ac4133f 100644 (file)
@@ -796,7 +796,7 @@ struct TranslationRotationWarp {
     parameters[1] = t[1];
 
     // Obtain the rotation via orthorgonal procrustes.
-    Mat2 correlation_matrix;
+    Mat2 correlation_matrix = Mat2::Zero();
     for (int i = 0; i < 4; ++i) {
       correlation_matrix += q1.CornerRelativeToCentroid(i) *
                             q2.CornerRelativeToCentroid(i).transpose();
@@ -864,7 +864,7 @@ struct TranslationRotationScaleWarp {
     parameters[2] = 1.0 - q2.Scale() / q1.Scale();
 
     // Obtain the rotation via orthorgonal procrustes.
-    Mat2 correlation_matrix;
+    Mat2 correlation_matrix = Mat2::Zero();
     for (int i = 0; i < 4; ++i) {
       correlation_matrix += q1.CornerRelativeToCentroid(i) *
                             q2.CornerRelativeToCentroid(i).transpose();
index 371e0007bd31303e1768768a34e29d429beb3b77..676a86e88fe21f7128b58dd04425abf9ec8ae29f 100644 (file)
@@ -67,6 +67,35 @@ static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
 static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
                                                                          "filled with data.";
 
+bool AUD_OpenALDevice::AUD_OpenALHandle::pause(bool keep)
+{
+       if(m_status)
+       {
+               AUD_MutexLock lock(*m_device);
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
+                       {
+                               if(it->get() == this)
+                               {
+                                       boost::shared_ptr<AUD_OpenALHandle> This = *it;
+
+                                       m_device->m_playingSounds.erase(it);
+                                       m_device->m_pausedSounds.push_back(This);
+
+                                       alSourcePause(m_source);
+
+                                       m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED;
+
+                                       return true;
+                               }
+                       }
+               }
+       }
+
+       return false;}
+
 AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep) :
        m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
        m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
@@ -124,32 +153,7 @@ AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, A
 
 bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
 {
-       if(m_status)
-       {
-               AUD_MutexLock lock(*m_device);
-
-               if(m_status == AUD_STATUS_PLAYING)
-               {
-                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
-                       {
-                               if(it->get() == this)
-                               {
-                                       boost::shared_ptr<AUD_OpenALHandle> This = *it;
-
-                                       m_device->m_playingSounds.erase(it);
-                                       m_device->m_pausedSounds.push_back(This);
-
-                                       alSourcePause(m_source);
-
-                                       m_status = AUD_STATUS_PAUSED;
-
-                                       return true;
-                               }
-                       }
-               }
-       }
-
-       return false;
+       return pause(false);
 }
 
 bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
@@ -302,6 +306,9 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
                }
        }
 
+       if(m_status == AUD_STATUS_STOPPED)
+               m_status = AUD_STATUS_PAUSED;
+
        return true;
 }
 
@@ -409,7 +416,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
 {
        if(!m_status)
                return false;
+
+       if(m_status == AUD_STATUS_STOPPED && (count > m_loopcount || count < 0))
+               m_status = AUD_STATUS_PAUSED;
+
        m_loopcount = count;
+
        return true;
 }
 
@@ -987,7 +999,7 @@ void AUD_OpenALDevice::updateStreams()
                        }
 
                        for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
-                               (*it)->pause();
+                               (*it)->pause(true);
 
                        for(it = stopSounds.begin(); it != stopSounds.end(); it++)
                                (*it)->stop();
index d2a4be227bafd5d365bb669f4082432a57bf1cb8..f0e478249671dd2eb9ec7a2cd64a33d0cb4d3cf1 100644 (file)
@@ -96,6 +96,8 @@ private:
                /// Own device.
                AUD_OpenALDevice* m_device;
 
+               bool pause(bool keep);
+
        public:
 
                /**
index 9beba2eb0a0d6eea9085646496c25b34693e826e..b00289b3fae80de4e98a6e3e53922c72eea3df8e 100644 (file)
@@ -2908,6 +2908,7 @@ PyInit_aud(void)
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
        PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
+       PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_STOPPED);
        // distance model constants
        PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
        PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
index 9dcb743693e58eb295cf01aeb52cba8d16a649e1..c80fb4027b80528c6127eebc5d3f0cc858c42aa1 100644 (file)
@@ -113,6 +113,8 @@ public:
         *.         invalid
         *        - AUD_STATUS_PLAYING if the sound is currently played back.
         *        - AUD_STATUS_PAUSED if the sound is currently paused.
+        *        - AUD_STATUS_STOPPED if the sound finished playing and is still
+        *          kept in the device.
         * \see AUD_Status
         */
        virtual AUD_Status getStatus()=0;
index a7e5b25664bfc4bc78f1d9a32a11cf60ed858874..7bf59cd6f31a1beb261e7e39630c7da40868859e 100644 (file)
@@ -57,6 +57,37 @@ typedef enum
 /********************** AUD_SoftwareHandle Handle Code ************************/
 /******************************************************************************/
 
+bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause(bool keep)
+{
+       if(m_status)
+       {
+               AUD_MutexLock lock(*m_device);
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
+                       {
+                               if(it->get() == this)
+                               {
+                                       boost::shared_ptr<AUD_SoftwareHandle> This = *it;
+
+                                       m_device->m_playingSounds.erase(it);
+                                       m_device->m_pausedSounds.push_back(This);
+
+                                       if(m_device->m_playingSounds.empty())
+                                               m_device->playing(m_device->m_playback = false);
+
+                                       m_status = keep ? AUD_STATUS_STOPPED : AUD_STATUS_PAUSED;
+
+                                       return true;
+                               }
+                       }
+               }
+       }
+
+       return false;
+}
+
 AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) :
        m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0),
        m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
@@ -225,33 +256,7 @@ void AUD_SoftwareDevice::AUD_SoftwareHandle::setSpecs(AUD_Specs specs)
 
 bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause()
 {
-       if(m_status)
-       {
-               AUD_MutexLock lock(*m_device);
-
-               if(m_status == AUD_STATUS_PLAYING)
-               {
-                       for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
-                       {
-                               if(it->get() == this)
-                               {
-                                       boost::shared_ptr<AUD_SoftwareHandle> This = *it;
-
-                                       m_device->m_playingSounds.erase(it);
-                                       m_device->m_pausedSounds.push_back(This);
-
-                                       if(m_device->m_playingSounds.empty())
-                                               m_device->playing(m_device->m_playback = false);
-
-                                       m_status = AUD_STATUS_PAUSED;
-
-                                       return true;
-                               }
-                       }
-               }
-       }
-
-       return false;
+       return pause(false);
 }
 
 bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume()
@@ -360,6 +365,9 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position)
 
        m_reader->seek((int)(position * m_reader->getSpecs().rate));
 
+       if(m_status == AUD_STATUS_STOPPED)
+               m_status = AUD_STATUS_PAUSED;
+
        return true;
 }
 
@@ -429,7 +437,12 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count)
 {
        if(!m_status)
                return false;
+
+       if(m_status == AUD_STATUS_STOPPED && (count > m_loopcount || count < 0))
+               m_status = AUD_STATUS_PAUSED;
+
        m_loopcount = count;
+
        return true;
 }
 
@@ -793,19 +806,14 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
                m_mixer->read(buffer, m_volume);
 
                // cleanup
-               while(!stopSounds.empty())
-               {
-                       sound = stopSounds.front();
-                       stopSounds.pop_front();
-                       sound->stop();
-               }
+               for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
+                       (*it)->pause(true);
 
-               while(!pauseSounds.empty())
-               {
-                       sound = pauseSounds.front();
-                       pauseSounds.pop_front();
-                       sound->pause();
-               }
+               for(it = stopSounds.begin(); it != stopSounds.end(); it++)
+                       (*it)->stop();
+
+               pauseSounds.clear();
+               stopSounds.clear();
        }
 }
 
index 8675a5ce2b890eeb7705a22833889245bc09b833..3c8c1e438a370aa24ea588cff81b5b70db722177 100644 (file)
@@ -139,6 +139,8 @@ protected:
                /// Own device.
                AUD_SoftwareDevice* m_device;
 
+               bool pause(bool keep);
+
        public:
 
                /**
index f42cb1ab018005776da11b235e983d269c7bb763..ec2c06900ace0a742dca0ba38d9dda73ce47ae67 100644 (file)
@@ -125,7 +125,8 @@ typedef enum
 {
        AUD_STATUS_INVALID = 0,                 /// Invalid handle. Maybe due to stopping.
        AUD_STATUS_PLAYING,                             /// Sound is playing.
-       AUD_STATUS_PAUSED                               /// Sound is being paused.
+       AUD_STATUS_PAUSED,                              /// Sound is being paused.
+       AUD_STATUS_STOPPED                              /// Sound is stopped but kept in the device.
 } AUD_Status;
 
 /// Error codes for exceptions (C++ library) or for return values (C API).
index d8ff662c505a0d80482958e1553a1be7b6ef3829..5dd12f98b9ce8a5be95af7fc554514e85fa996fc 100644 (file)
@@ -498,7 +498,7 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
 #ifdef __MULTI_CLOSURE__
        bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
 
-       return _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
+       _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
 #else
        const ShaderClosure *sc = &sd->closure;
 
@@ -720,7 +720,7 @@ __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_facto
                        eval += sc->weight*ao_factor;
                        *N += sc->N*average(sc->weight);
                }
-               if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
+               else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
                        eval += sc->weight;
                        *N += sd->N*average(sc->weight);
                }
index 17d7260c191bc8c7273115eb3235151053bfd7b9..ca5f441aa2d0d15c9da468bbe619d40dad09ac2d 100644 (file)
 #ifndef __OSL_CLOSURES_H__
 #define __OSL_CLOSURES_H__
 
+#include "util_types.h"
+#include "kernel_types.h"
+
 #include <OSL/oslclosure.h>
 #include <OSL/oslexec.h>
 #include <OSL/genclosure.h>
 
-#include "kernel_types.h"
-
-#include "util_types.h"
-
 CCL_NAMESPACE_BEGIN
 
 OSL::ClosureParam *closure_emission_params();
index 08ac2ce6effefea7cecc91346ccd6b185722dfbf..06ae2ee864d5470ed0abb008a239ed916fc8a4ff 100644 (file)
@@ -1142,12 +1142,12 @@ void *MEM_dupallocN(const void *vmemh)
        return newp;
 }
 
-void *MEM_reallocN(void *vmemh, size_t len)
+void *MEM_reallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
 {
        return realloc(vmemh, len);
 }
 
-void *MEM_recallocN(void *vmemh, size_t len)
+void *MEM_recallocN_id(void *vmemh, size_t len, const char *UNUSED(str))
 {
        void *newp = NULL;
 
index 551689c5a75c7708ceabfaa685867888887e045a..ff6d23badb6943972540944e71f7ce42ebc15bc3 100644 (file)
@@ -105,7 +105,15 @@ def load_image(imagepath,
             if relpath is not None:
                 # make relative
                 from bpy.path import relpath as relpath_fn
-                image.filepath_raw = relpath_fn(path, start=relpath)
+                # can't always find the relative path
+                # (between drive letters on windows)
+                try:
+                    filepath_rel = relpath_fn(path, start=relpath)
+                except ValueError:
+                    filepath_rel = None
+
+                if filepath_rel is not None:
+                    image.filepath_raw = filepath_rel
 
         return image
 
index 08dfc2bf8b545a09702c909546acbac850f6b25c..692787ce281724b45db0df61a3cdc3361ea59448 100644 (file)
@@ -105,11 +105,11 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
             default=12,
             )
     mode = bpy.props.EnumProperty(
-            name="Torus Dimentions",
+            name="Torus Dimensions",
             items=(("MAJOR_MINOR", "Major/Minor", 
-                    "Use the major/minor radiuses for torus dimensions"),
+                    "Use the major/minor radii for torus dimensions"),
                    ("EXT_INT", "Exterior/Interior", 
-                    "Use the exterior/interior radiuses for torus dimensions")),
+                    "Use the exterior/interior radii for torus dimensions")),
             update=mode_update_callback,
             )
     major_radius = FloatProperty(
index d38f5f934b41d6bc2fe6a19ae78bc04d61bb0ce2..9f72d7a6d888771792a499bf1488ee29891aac65 100644 (file)
@@ -190,16 +190,21 @@ class MASK_PT_point():
             clip = parent.id
             tracking = clip.tracking
 
+            row = col.row()
+            row.prop(parent, "type", expand=True)
+
             col.prop_search(parent, "parent", tracking,
                             "objects", icon='OBJECT_DATA', text="Object:")
 
+            tracks_list = "tracks" if parent.type == 'POINT_TRACK' else 'plane_tracks'
+
             if parent.parent in tracking.objects:
                 object = tracking.objects[parent.parent]
                 col.prop_search(parent, "sub_parent", object,
-                                "tracks", icon='ANIM_DATA', text="Track:")
+                                tracks_list, icon='ANIM_DATA', text="Track:")
             else:
                 col.prop_search(parent, "sub_parent", tracking,
-                                "tracks", icon='ANIM_DATA', text="Track:")
+                                tracks_list, icon='ANIM_DATA', text="Track:")
 
 
 class MASK_PT_display():
index 5048a93d56534f41dc8e43e4ded8d654a28702ad..04584855ed325d1368021ddc15a11780f3116112 100644 (file)
@@ -311,6 +311,16 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
         layout.operator("clip.join_tracks", text="Join")
 
 
+class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'TOOLS'
+    bl_label = "Plane Track"
+
+    def draw(self, context):
+        layout = self.layout
+        layout.operator("clip.create_plane_track")
+
+
 class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'TOOLS'
@@ -579,6 +589,26 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
             layout.label(text=label_text)
 
 
+class CLIP_PT_plane_track(CLIP_PT_tracking_panel, Panel):
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "Plane Track"
+
+    def draw(self, context):
+        layout = self.layout
+
+        sc = context.space_data
+        clip = context.space_data.clip
+        active_track = clip.tracking.plane_tracks.active
+
+        if not active_track:
+            layout.active = False
+            layout.label(text="No active plane track")
+            return
+
+        layout.prop(active_track, "name")
+
+
 class CLIP_PT_track_settings(CLIP_PT_tracking_panel, Panel):
     bl_space_type = 'CLIP_EDITOR'
     bl_region_type = 'UI'
index 91090dc2c75dbd59a261281b8b792629c7113d21..6a5dccaed884b8513744c0bc5c246f8639b61270 100644 (file)
@@ -342,6 +342,7 @@ compositor_node_categories = [
         NodeItem("CompositorNodeMapUV"),
         NodeItem("CompositorNodeTransform"),
         NodeItem("CompositorNodeStabilize"),
+        NodeItem("CompositorNodePlaneTrackDeform"),
         ]),
     CompositorNodeCategory("CMP_GROUP", "Group", items=node_group_items),
     CompositorNodeCategory("CMP_LAYOUT", "Layout", items=[
index 93f9ec276aa483516fe8c1badff07c2269413c72..baa90e7a856752be9f9f7ad9d59336da011f4be4 100644 (file)
@@ -69,7 +69,8 @@ bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]);
 bool BKE_curve_center_median(struct Curve *cu, float cent[3]);
 bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]);
 void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys);
-void BKE_curve_delete_material_index(struct Curve *cu, int index);
+void BKE_curve_material_index_remove(struct Curve *cu, int index);
+void BKE_curve_material_index_clear(struct Curve *cu);
 
 ListBase *BKE_curve_nurbs_get(struct Curve *cu);
 
index 92332116ba65dcdb26e78cf27e79535fe00357fd..14ceba42aff3d297455fd99143006f91558cf609 100644 (file)
@@ -53,9 +53,11 @@ void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay);
 void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay);
 
 void BKE_mask_layer_free_shapes(struct MaskLayer *masklay);
+void BKE_mask_layer_free_deform(struct MaskLayer *mask_layer);
 void BKE_mask_layer_free(struct MaskLayer *masklay);
 void BKE_mask_layer_free_list(struct ListBase *masklayers);
 void BKE_mask_spline_free(struct MaskSpline *spline);
+void BKE_mask_spline_free_list(struct ListBase *splines);
 struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline);
 void BKE_mask_point_free(struct MaskSplinePoint *point);
 
index 7c47380f8381cd29b5b8639b740b77de27d1dccc..91c1715cca666b8c23a198b9a07a40f1efd54860 100644 (file)
@@ -50,7 +50,7 @@ void init_def_material(void);
 void BKE_material_free(struct Material *sc); 
 void BKE_material_free_ex(struct Material *ma, int do_id_user);
 void test_object_materials(struct Main *bmain, struct ID *id);
-void resize_object_material(struct Object *ob, const short totcol);
+void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
 void init_material(struct Material *ma);
 struct Material *BKE_material_add(struct Main *bmain, const char *name);
 struct Material *BKE_material_copy(struct Material *ma);
@@ -87,9 +87,10 @@ int object_add_material_slot(struct Object *ob);
 int object_remove_material_slot(struct Object *ob);
 
 /* rna api */
-void material_append_id(struct ID *id, struct Material *ma);
-struct Material *material_pop_id(struct ID *id, int index, int remove_material_slot); /* index is an int because of RNA */
-
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
+void BKE_material_append_id(struct ID *id, struct Material *ma);
+struct Material *BKE_material_pop_id(struct ID *id, int index, bool update_data); /* index is an int because of RNA */
+void BKE_material_clear_id(struct ID *id, bool update_data);
 /* rendering */
 
 void init_render_material(struct Material *, int, float *);
index 1c88a5c45dd06706ba2d18b97da2a719adb7acd5..e582af77d61798112d7433b02d34818a98771499 100644 (file)
@@ -188,7 +188,8 @@ void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
 void BKE_mesh_from_nurbs(struct Object *ob);
 void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
 void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
-void BKE_mesh_delete_material_index(struct Mesh *me, short index);
+void BKE_mesh_material_index_remove(struct Mesh *me, short index);
+void BKE_mesh_material_index_clear(struct Mesh *me);
 void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
 void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
 void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
index 4e9e18d43e329706f3f5ec0a08611c9e6efb31d7..27192437c89a1d313729ced16df2f84e8f33881d 100644 (file)
@@ -898,6 +898,7 @@ void            ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
 #define CMP_NODE_PIXELATE       318
 
 #define CMP_NODE_MAP_RANGE     319
+#define CMP_NODE_PLANETRACKDEFORM      320
 
 /* channel toggles */
 #define CMP_CHAN_RGB           1
index 84bca0bd3ba7f7bc8a9e638998d3735241a44d0f..0d148e557533d18241fe4e60940c49d852a5ab26 100644 (file)
@@ -38,6 +38,8 @@ struct ListBase;
 struct MovieReconstructContext;
 struct MovieTrackingTrack;
 struct MovieTrackingMarker;
+struct MovieTrackingPlaneTrack;
+struct MovieTrackingPlaneMarker;
 struct MovieTracking;
 struct MovieTrackingContext;
 struct MovieTrackingObject;
@@ -55,6 +57,7 @@ void BKE_tracking_free(struct MovieTracking *tracking);
 void BKE_tracking_settings_init(struct MovieTracking *tracking);
 
 struct ListBase *BKE_tracking_get_active_tracks(struct MovieTracking *tracking);
+struct ListBase *BKE_tracking_get_active_plane_tracks(struct MovieTracking *tracking);
 struct MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(struct MovieTracking *tracking);
 
 /* matrices for constraints and drawing */
@@ -97,6 +100,7 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height, struct Mov
 /* selection */
 void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend);
 void BKE_tracking_track_deselect(struct MovieTrackingTrack *track, int area);
+void BKE_tracking_tracks_deselect_all(struct ListBase *tracksbase);
 
 /* **** Marker **** */
 struct MovieTrackingMarker *BKE_tracking_marker_insert(struct MovieTrackingTrack *track,
@@ -113,6 +117,32 @@ void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker
 
 void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, float framenr, float pos[2]);
 
+/* **** Plane Track **** */
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(struct MovieTracking *tracking, struct ListBase *plane_tracks_base,
+                                                             struct ListBase *tracks, int framenr);
+void BKE_tracking_plane_track_unique_name(struct ListBase *plane_tracks_base, struct MovieTrackingPlaneTrack *plane_track);
+void BKE_tracking_plane_track_free(struct MovieTrackingPlaneTrack *plane_track);
+
+bool BKE_tracking_plane_track_has_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+bool BKE_tracking_plane_track_has_enabled_marker_at_frame(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(struct MovieTracking *tracking,
+                                                                   struct MovieTrackingObject *object,
+                                                                   const char *name);
+
+struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking);
+
+void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base);
+
+/* **** Plane Marker **** */
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track,
+                                                                  struct MovieTrackingPlaneMarker *plane_marker);
+void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr);
+
 /* **** Object **** */
 struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name);
 int BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object);
@@ -125,6 +155,7 @@ struct MovieTrackingObject *BKE_tracking_object_get_active(struct MovieTracking
 struct MovieTrackingObject *BKE_tracking_object_get_camera(struct MovieTracking *tracking);
 
 struct ListBase *BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
+struct ListBase *BKE_tracking_object_get_plane_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object);
 struct MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(struct MovieTracking *tracking,
                                                                            struct MovieTrackingObject *object);
 
@@ -182,6 +213,11 @@ void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context,
 int BKE_tracking_context_step(struct MovieTrackingContext *context);
 void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int backwards);
 
+/* **** Plane tracking **** */
+
+void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame);
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3]);
+
 /* **** Camera solving **** */
 int BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object,
                                       char *error_msg, int error_size);
index eca607c08df4731e0936531c9d388d9d7b0bbb7e..f006710dc21e70b20ebd6fb85e25329bdb4bfa5d 100644 (file)
@@ -1605,7 +1605,10 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        pchanw.next = pchan->next;
                        pchanw.parent = pchan->parent;
                        pchanw.child = pchan->child;
-                       
+
+                       pchanw.mpath = pchan->mpath;
+                       pchan->mpath = NULL;
+
                        /* this is freed so copy a copy, else undo crashes */
                        if (pchanw.prop) {
                                pchanw.prop = IDP_CopyProperty(pchanw.prop);
index 26ae1b94aeea27f13cbb11ecb70afb832124aa8d..801ed4f00a58b5ae269671d3e8681dd6cb3aea42 100644 (file)
@@ -2242,15 +2242,18 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
                }
        }
        else {
-               /* Need to correct quat for the last point,
+               /* Need to correct quat for the first/last point,
                 * this is so because previously it was only calculated
                 * using it's own direction, which might not correspond
-                * the twist of previous point.
+                * the twist of neighbor point.
                 */
+               bevp1 = (BevPoint *)(bl + 1);
+               bevp0 = bevp1 + 1;
+               minimum_twist_between_two_points(bevp1, bevp0);
+
                bevp2 = (BevPoint *)(bl + 1);
                bevp1 = bevp2 + (bl->nr - 1);
                bevp0 = bevp1 - 1;
-
                minimum_twist_between_two_points(bevp1, bevp0);
        }
 }
@@ -2369,12 +2372,23 @@ static void make_bevel_list_2D(BevList *bl)
        /* note: bevp->dir and bevp->quat are not needed for beveling but are
         * used when making a path from a 2D curve, therefor they need to be set - Campbell */
 
-       BevPoint *bevp2 = (BevPoint *)(bl + 1);
-       BevPoint *bevp1 = bevp2 + (bl->nr - 1);
-       BevPoint *bevp0 = bevp1 - 1;
+       BevPoint *bevp0, *bevp1, *bevp2;
        int nr;
 
-       nr = bl->nr;
+       if (bl->poly != -1) {
+               bevp2 = (BevPoint *)(bl + 1);
+               bevp1 = bevp2 + (bl->nr - 1);
+               bevp0 = bevp1 - 1;
+               nr = bl->nr;
+       }
+       else {
+               bevp0 = (BevPoint *)(bl + 1);
+               bevp1 = bevp0 + 1;
+               bevp2 = bevp1 + 1;
+
+               nr = bl->nr - 2;
+       }
+
        while (nr--) {
                const float x1 = bevp1->vec[0] - bevp0->vec[0];
                const float x2 = bevp1->vec[0] - bevp2->vec[0];
@@ -2396,15 +2410,23 @@ static void make_bevel_list_2D(BevList *bl)
 
        /* correct non-cyclic cases */
        if (bl->poly == -1) {
-               BevPoint *bevp = (BevPoint *)(bl + 1);
-               bevp1 = bevp + 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               BevPoint *bevp;
+               float angle;
+
+               /* first */
+               bevp = (BevPoint *)(bl + 1);
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
+
+               /* last */
                bevp = (BevPoint *)(bl + 1);
                bevp += (bl->nr - 1);
-               bevp1 = bevp - 1;
-               bevp->sina = bevp1->sina;
-               bevp->cosa = bevp1->cosa;
+               angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0;
+               bevp->sina = sinf(angle);
+               bevp->cosa = cosf(angle);
+               vec_to_quat(bevp->quat, bevp->dir, 5, 1);
        }
 }
 
@@ -3816,7 +3838,7 @@ void BKE_curve_translate(Curve *cu, float offset[3], int do_keys)
        }
 }
 
-void BKE_curve_delete_material_index(Curve *cu, int index)
+void BKE_curve_material_index_remove(Curve *cu, int index)
 {
        const int curvetype = BKE_curve_type_get(cu);
 
@@ -3835,8 +3857,32 @@ void BKE_curve_delete_material_index(Curve *cu, int index)
                for (nu = cu->nurb.first; nu; nu = nu->next) {
                        if (nu->mat_nr && nu->mat_nr >= index) {
                                nu->mat_nr--;
-                               if (curvetype == OB_CURVE)
+                               if (curvetype == OB_CURVE) {
                                        nu->charidx--;
+                               }
+                       }
+               }
+       }
+}
+
+void BKE_curve_material_index_clear(Curve *cu)
+{
+       const int curvetype = BKE_curve_type_get(cu);
+
+       if (curvetype == OB_FONT) {
+               struct CharInfo *info = cu->strinfo;
+               int i;
+               for (i = cu->len - 1; i >= 0; i--, info++) {
+                       info->mat_nr = 0;
+               }
+       }
+       else {
+               Nurb *nu;
+
+               for (nu = cu->nurb.first; nu; nu = nu->next) {
+                       nu->mat_nr = 0;
+                       if (curvetype == OB_CURVE) {
+                               nu->charidx = 0;
                        }
                }
        }
index e3f30bad5cf3981dd5961c86d849d742313dc0e0..a7bfb15c99df82111dc5de7edc10047a8f1fba36 100644 (file)
@@ -817,6 +817,19 @@ void BKE_mask_spline_free(MaskSpline *spline)
        MEM_freeN(spline);
 }
 
+void BKE_mask_spline_free_list(ListBase *splines)
+{
+       MaskSpline *spline = splines->first;
+       while (spline) {
+               MaskSpline *next_spline = spline->next;
+
+               BLI_remlink(splines, spline);
+               BKE_mask_spline_free(spline);
+
+               spline = next_spline;
+       }
+}
+
 static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point)
 {
        MaskSplinePoint *npoints;
@@ -891,20 +904,30 @@ void BKE_mask_layer_free_shapes(MaskLayer *masklay)
        }
 }
 
-void BKE_mask_layer_free(MaskLayer *masklay)
+void BKE_mask_layer_free_deform(MaskLayer *mask_layer)
 {
-       MaskSpline *spline;
-
-       /* free splines */
-       spline = masklay->splines.first;
-       while (spline) {
-               MaskSpline *next_spline = spline->next;
+       MaskSpline *mask_spline;
 
-               BLI_remlink(&masklay->splines, spline);
-               BKE_mask_spline_free(spline);
-
-               spline = next_spline;
+       for (mask_spline = mask_layer->splines.first;
+            mask_spline;
+            mask_spline = mask_spline->next)
+       {
+               if (mask_spline->points_deform) {
+                       int i;
+                       MaskSplinePoint *points_deform = mask_spline->points_deform;
+                       for (i = 0; i < mask_spline->tot_point; i++) {
+                               BKE_mask_point_free(&points_deform[i]);
+                       }
+                       MEM_freeN(points_deform);
+                       mask_spline->points_deform = NULL;
+               }
        }
+}
+
+void BKE_mask_layer_free(MaskLayer *masklay)
+{
+       /* free splines */
+       BKE_mask_spline_free_list(&masklay->splines);
 
        /* free animation data */
        BKE_mask_layer_free_shapes(masklay);
@@ -1072,7 +1095,7 @@ void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], cons
        BKE_mask_coord_to_frame(r_co, co, frame_size);
 }
 
-static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[2])
+static int mask_evaluate_parent(MaskParent *parent, float ctime, float orig_co[2], float r_co[2])
 {
        if (!parent)
                return FALSE;
@@ -1084,18 +1107,38 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[
                        MovieTrackingObject *ob = BKE_tracking_object_get_named(tracking, parent->parent);
 
                        if (ob) {
-                               MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
+                               MovieClipUser user = {0};
                                float clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
+                               BKE_movieclip_user_set_frame(&user, ctime);
 
-                               MovieClipUser user = {0};
-                               user.framenr = ctime;
+                               if (parent->type == MASK_PARENT_POINT_TRACK) {
+                                       MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, ob, parent->sub_parent);
 
-                               if (track) {
-                                       float marker_pos_ofs[2];
-                                       BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_pos_ofs);
-                                       BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs);
+                                       if (track) {
+                                               float marker_pos_ofs[2];
+                                               BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_pos_ofs);
+                                               BKE_mask_coord_from_movieclip(clip, &user, r_co, marker_pos_ofs);
 
-                                       return TRUE;
+                                               return TRUE;
+                                       }
+                               }
+                               else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+                                       MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent);
+
+                                       if (plane_track) {
+                                               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+                                               float H[3][3], vec[3], warped[3];
+
+                                               BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H);
+
+                                               BKE_mask_coord_to_movieclip(clip, &user, vec, orig_co);
+                                               vec[2] = 1.0f;
+                                               mul_v3_m3v3(warped, H, vec);
+                                               warped[0] /= warped[2];
+                                               warped[1] /= warped[2];
+
+                                               BKE_mask_coord_from_movieclip(clip, &user, r_co, warped);
+                                       }
                                }
                        }
                }
@@ -1104,17 +1147,26 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[
        return FALSE;
 }
 
-/* could make external but for now its only used internally */
-static int mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2])
+static void mask_evaluate_apply_point_parent(MaskSplinePoint *point, float ctime)
 {
-       float parent_co[2];
+       MaskParent *parent = &point->parent;
+
+       if (parent->type == MASK_PARENT_POINT_TRACK) {
+               float parent_co[2];
 
-       if (BKE_mask_evaluate_parent(parent, ctime, parent_co)) {
-               sub_v2_v2v2(r_delta, parent_co, parent->parent_orig);
-               return TRUE;
+               if (mask_evaluate_parent(parent, ctime, NULL, parent_co)) {
+                       float delta[2];
+                       sub_v2_v2v2(delta, parent_co, parent->parent_orig);
+
+                       add_v2_v2(point->bezt.vec[0], delta);
+                       add_v2_v2(point->bezt.vec[1], delta);
+                       add_v2_v2(point->bezt.vec[2], delta);
+               }
        }
-       else {
-               return FALSE;
+       else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[0], point->bezt.vec[0]);
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[1], point->bezt.vec[1]);
+               mask_evaluate_parent(parent, ctime, point->bezt.vec[2], point->bezt.vec[2]);
        }
 }
 
@@ -1438,18 +1490,13 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do
                        for (i = 0; i < spline->tot_point; i++) {
                                MaskSplinePoint *point = &spline->points[i];
                                MaskSplinePoint *point_deform = &spline->points_deform[i];
-                               float delta[2];
 
                                BKE_mask_point_free(point_deform);
 
                                *point_deform = *point;
                                point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL;
 
-                               if (mask_evaluate_parent_delta(&point->parent, ctime, delta)) {
-                                       add_v2_v2(point_deform->bezt.vec[0], delta);
-                                       add_v2_v2(point_deform->bezt.vec[1], delta);
-                                       add_v2_v2(point_deform->bezt.vec[2], delta);
-                               }
+                               mask_evaluate_apply_point_parent(point_deform, ctime);
 
                                if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) {
                                        need_handle_recalc = TRUE;
index 6dc3c6d7bc63c83930c2d7a2bce5611a9654f0e9..c23b4ac4408bf79dd4409983c42bafa6fa41215b 100644 (file)
@@ -537,17 +537,17 @@ short *give_totcolp_id(ID *id)
        return NULL;
 }
 
-static void data_delete_material_index_id(ID *id, short index)
+static void material_data_index_remove_id(ID *id, short index)
 {
        /* ensure we don't try get materials from non-obdata */
        BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
 
        switch (GS(id->name)) {
                case ID_ME:
-                       BKE_mesh_delete_material_index((Mesh *)id, index);
+                       BKE_mesh_material_index_remove((Mesh *)id, index);
                        break;
                case ID_CU:
-                       BKE_curve_delete_material_index((Curve *)id, index);
+                       BKE_curve_material_index_remove((Curve *)id, index);
                        break;
                case ID_MB:
                        /* meta-elems don't have materials atm */
@@ -555,7 +555,53 @@ static void data_delete_material_index_id(ID *id, short index)
        }
 }
 
-void material_append_id(ID *id, Material *ma)
+static void material_data_index_clear_id(ID *id)
+{
+       /* ensure we don't try get materials from non-obdata */
+       BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+
+       switch (GS(id->name)) {
+               case ID_ME:
+                       BKE_mesh_material_index_clear((Mesh *)id);
+                       break;
+               case ID_CU:
+                       BKE_curve_material_index_clear((Curve *)id);
+                       break;
+               case ID_MB:
+                       /* meta-elems don't have materials atm */
+                       break;
+       }
+}
+
+void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user)
+{
+       Material ***matar = give_matarar_id(id);
+       short *totcolp = give_totcolp_id(id);
+
+       if (matar == NULL) {
+               return;
+       }
+
+       if (do_id_user && totcol < (*totcolp)) {
+               short i;
+               for (i = totcol; i < (*totcolp); i++) {
+                       id_us_min((ID *)(*matar)[i]);
+               }
+       }
+
+       if (totcol == 0) {
+               if (*totcolp) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+       }
+       else {
+               *matar = MEM_recallocN(*matar, sizeof(void *) * totcol);
+       }
+       *totcolp = totcol;
+}
+
+void BKE_material_append_id(ID *id, Material *ma)
 {
        Material ***matar;
        if ((matar = give_matarar_id(id))) {
@@ -572,7 +618,7 @@ void material_append_id(ID *id, Material *ma)
        }
 }
 
-Material *material_pop_id(ID *id, int index_i, int remove_material_slot)
+Material *BKE_material_pop_id(ID *id, int index_i, bool update_data)
 {
        short index = (short)index_i;
        Material *ret = NULL;
@@ -583,40 +629,48 @@ Material *material_pop_id(ID *id, int index_i, int remove_material_slot)
                        ret = (*matar)[index];
                        id_us_min((ID *)ret);
 
-                       if (remove_material_slot) {
-                               if (*totcol <= 1) {
-                                       *totcol = 0;
-                                       MEM_freeN(*matar);
-                                       *matar = NULL;
-                               }
-                               else {
-                                       Material **mat;
-                                       if (index + 1 != (*totcol))
-                                               memmove((*matar) + index, (*matar) + (index + 1), sizeof(void *) * ((*totcol) - (index + 1)));
-
-                                       (*totcol)--;
-                                       
-                                       mat = MEM_callocN(sizeof(void *) * (*totcol), "newmatar");
-                                       memcpy(mat, *matar, sizeof(void *) * (*totcol));
-                                       MEM_freeN(*matar);
-
-                                       *matar = mat;
-                                       test_object_materials(G.main, id);
-                               }
+                       if (*totcol <= 1) {
+                               *totcol = 0;
+                               MEM_freeN(*matar);
+                               *matar = NULL;
+                       }
+                       else {
+                               if (index + 1 != (*totcol))
+                                       memmove((*matar) + index, (*matar) + (index + 1), sizeof(void *) * ((*totcol) - (index + 1)));
 
-                               /* decrease mat_nr index */
-                               data_delete_material_index_id(id, index);
+                               (*totcol)--;
+                               *matar = MEM_reallocN(*matar, sizeof(void *) * (*totcol));
+                               test_object_materials(G.main, id);
                        }
 
-                       /* don't remove material slot, only clear it*/
-                       else
-                               (*matar)[index] = NULL;
+                       if (update_data) {
+                               /* decrease mat_nr index */
+                               material_data_index_remove_id(id, index);
+                       }
                }
        }
        
        return ret;
 }
 
+void BKE_material_clear_id(struct ID *id, bool update_data)
+{
+       Material ***matar;
+       if ((matar = give_matarar_id(id))) {
+               short *totcol = give_totcolp_id(id);
+               *totcol = 0;
+               if (*matar) {
+                       MEM_freeN(*matar);
+                       *matar = NULL;
+               }
+
+               if (update_data) {
+                       /* decrease mat_nr index */
+                       material_data_index_clear_id(id);
+               }
+       }
+}
+
 Material *give_current_material(Object *ob, short act)
 {
        Material ***matarar, *ma;
@@ -682,11 +736,18 @@ Material *give_node_material(Material *ma)
        return NULL;
 }
 
-void resize_object_material(Object *ob, const short totcol)
+void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user)
 {
        Material **newmatar;
        char *newmatbits;
 
+       if (do_id_user && totcol < ob->totcol) {
+               short i;
+               for (i = totcol; i < ob->totcol; i++) {
+                       id_us_min((ID *)ob->mat[i]);
+               }
+       }
+
        if (totcol == 0) {
                if (ob->totcol) {
                        MEM_freeN(ob->mat);
@@ -707,6 +768,8 @@ void resize_object_material(Object *ob, const short totcol)
                ob->mat = newmatar;
                ob->matbits = newmatbits;
        }
+       /* XXX, why not realloc on shrink? - campbell */
+
        ob->totcol = totcol;
        if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
        if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
@@ -724,7 +787,7 @@ void test_object_materials(Main *bmain, ID *id)
 
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->data == id) {
-                       resize_object_material(ob, *totcol);
+                       BKE_material_resize_object(ob, *totcol, false);
                }
        }
 }
@@ -1227,7 +1290,7 @@ int object_remove_material_slot(Object *ob)
 
        /* check indices from mesh */
        if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
-               data_delete_material_index_id((ID *)ob->data, actcol - 1);
+               material_data_index_remove_id((ID *)ob->data, actcol - 1);
                BKE_displist_free(&ob->disp);
        }
 
@@ -1703,7 +1766,7 @@ static short mesh_getmaterialnumber(Mesh *me, Material *ma)
 /* append material */
 static short mesh_addmaterial(Mesh *me, Material *ma)
 {
-       material_append_id(&me->id, NULL);
+       BKE_material_append_id(&me->id, NULL);
        me->mat[me->totcol - 1] = ma;
 
        id_us_plus(&ma->id);
@@ -1840,8 +1903,14 @@ static void convert_tfacematerial(Main *main, Material *ma)
                        mf->mat_nr = mat_nr;
                }
                /* remove material from mesh */
-               for (a = 0; a < me->totcol; )
-                       if (me->mat[a] == ma) material_pop_id(&me->id, a, 1); else a++;
+               for (a = 0; a < me->totcol; ) {
+                       if (me->mat[a] == ma) {
+                               BKE_material_pop_id(&me->id, a, true);
+                       }
+                       else {
+                               a++;
+                       }
+               }
        }
 }
 
index 095957b40d5a83788f08544922ffda35674c1823..0db1f92f70f86c168981672215faf370b1dc4fac 100644 (file)
@@ -1852,20 +1852,37 @@ void BKE_mesh_to_curve(Scene *scene, Object *ob)
        }
 }
 
-void BKE_mesh_delete_material_index(Mesh *me, short index)
+void BKE_mesh_material_index_remove(Mesh *me, short index)
 {
+       MPoly *mp;
+       MFace *mf;
        int i;
 
-       for (i = 0; i < me->totpoly; i++) {
-               MPoly *mp = &((MPoly *) me->mpoly)[i];
-               if (mp->mat_nr && mp->mat_nr >= index)
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               if (mp->mat_nr && mp->mat_nr >= index) {
                        mp->mat_nr--;
+               }
        }
-       
-       for (i = 0; i < me->totface; i++) {
-               MFace *mf = &((MFace *) me->mface)[i];
-               if (mf->mat_nr && mf->mat_nr >= index)
+
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               if (mf->mat_nr && mf->mat_nr >= index) {
                        mf->mat_nr--;
+               }
+       }
+}
+
+void BKE_mesh_material_index_clear(Mesh *me)
+{
+       MPoly *mp;
+       MFace *mf;
+       int i;
+
+       for (mp = me->mpoly, i = 0; i < me->totpoly; i++, mp++) {
+               mp->mat_nr = 0;
+       }
+
+       for (mf = me->mface, i = 0; i < me->totface; i++, mf++) {
+               mf->mat_nr = 0;
        }
 }
 
index 5001aa01653e5b06dd75287db4bd448c50d3c387..1349c4dc8d4f73312deb33e75e0d5f8c7372ffaa 100644 (file)
@@ -3391,6 +3391,7 @@ static void registerCompositNodes(void)
 
        register_node_type_cmp_mask();
        register_node_type_cmp_trackpos();
+       register_node_type_cmp_planetrackdeform();
 }
 
 static void registerShaderNodes(void) 
index feff8f95fd7ef3b096da976b8992d3e8f591f2fd..2f8eb7d9931f54ea304d4c84db932c97334a2134 100644 (file)
 #include "BKE_sequencer.h"
 #include "BKE_scene.h"
 
-// evil quiet NaN definition
-static const int NAN_INT = 0x7FC00000;
-#define NAN_FLT *((float *)(&NAN_INT))
-
 #ifdef WITH_AUDASPACE
 // evil global ;-)
 static int sound_cfra;
index 4c3632928984804bb8b3fb6ac037a923b8be717d..54ba9ea56d7101904ddf1a22ecc4922a791799b3 100644 (file)
@@ -103,6 +103,18 @@ static void tracking_tracks_free(ListBase *tracks)
        BLI_freelistN(tracks);
 }
 
+/* Free the whole list of plane tracks, list's head and tail are set to NULL. */
+static void tracking_plane_tracks_free(ListBase *plane_tracks)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks->first; plane_track; plane_track = plane_track->next) {
+               BKE_tracking_plane_track_free(plane_track);
+       }
+
+       BLI_freelistN(plane_tracks);
+}
+
 /* Free reconstruction structures, only frees contents of a structure,
  * (if structure is allocated in heap, it shall be handled outside).
  *
@@ -122,6 +134,7 @@ static void tracking_reconstruction_free(MovieTrackingReconstruction *reconstruc
 static void tracking_object_free(MovieTrackingObject *object)
 {
        tracking_tracks_free(&object->tracks);
+       tracking_plane_tracks_free(&object->plane_tracks);
        tracking_reconstruction_free(&object->reconstruction);
 }
 
@@ -173,6 +186,7 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet)
 void BKE_tracking_free(MovieTracking *tracking)
 {
        tracking_tracks_free(&tracking->tracks);
+       tracking_plane_tracks_free(&tracking->plane_tracks);
        tracking_reconstruction_free(&tracking->reconstruction);
        tracking_objects_free(&tracking->objects);
 
@@ -221,6 +235,18 @@ ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
        return &tracking->tracks;
 }
 
+/* Get list base of active object's plane tracks. */
+ListBase *BKE_tracking_get_active_plane_tracks(MovieTracking *tracking)
+{
+       MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
+
+       if (object && (object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+               return &object->plane_tracks;
+       }
+
+       return &tracking->plane_tracks;
+}
+
 /* Get reconstruction data of active object. */
 MovieTrackingReconstruction *BKE_tracking_get_active_reconstruction(MovieTracking *tracking)
 {
@@ -1025,6 +1051,17 @@ void BKE_tracking_track_deselect(MovieTrackingTrack *track, int area)
        BKE_tracking_track_flag_clear(track, area, SELECT);
 }
 
+void BKE_tracking_tracks_deselect_all(ListBase *tracksbase)
+{
+       MovieTrackingTrack *track;
+
+       for (track = tracksbase->first; track; track = track->next) {
+               if ((track->flag & TRACK_HIDDEN) == 0) {
+                       BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+               }
+       }
+}
+
 /*********************** Marker *************************/
 
 MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, MovieTrackingMarker *marker)
@@ -1264,6 +1301,296 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float
        add_v2_v2(pos, track->offset);
 }
 
+/*********************** Plane Track *************************/
+
+/* Creates new plane track out of selected point tracks */
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base,
+                                                      ListBase *tracks, int framenr)
+{
+       MovieTrackingPlaneTrack *plane_track;
+       MovieTrackingPlaneMarker plane_marker;
+       MovieTrackingTrack *track;
+       float tracks_min[2], tracks_max[2];
+       int track_index, num_selected_tracks = 0;
+
+       (void) tracking;  /* Ignored. */
+
+       /* Use bounding box of selected markers as an initial size of plane. */
+       INIT_MINMAX2(tracks_min, tracks_max);
+       for (track = tracks->first; track; track = track->next) {
+               if (TRACK_SELECTED(track)) {
+                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+                       float pattern_min[2], pattern_max[2];
+                       BKE_tracking_marker_pattern_minmax(marker, pattern_min, pattern_max);
+                       add_v2_v2(pattern_min, marker->pos);
+                       add_v2_v2(pattern_max, marker->pos);
+                       minmax_v2v2_v2(tracks_min, tracks_max, pattern_min);
+                       minmax_v2v2_v2(tracks_min, tracks_max, pattern_max);
+                       num_selected_tracks++;
+               }
+       }
+
+       if (num_selected_tracks < 4) {
+               return NULL;
+       }
+
+       /* Allocate new plane track. */
+       plane_track = MEM_callocN(sizeof(MovieTrackingPlaneTrack), "new plane track");
+
+       /* Use some default name. */
+       strcpy(plane_track->name, "Plane Track");
+
+       /* Use selected tracks from given list as a plane. */
+       plane_track->point_tracks = MEM_mallocN(sizeof(MovieTrackingTrack *) * num_selected_tracks, "new plane tracks array");
+       for (track = tracks->first, track_index = 0; track; track = track->next) {
+               if (TRACK_SELECTED(track)) {
+                       plane_track->point_tracks[track_index] = track;
+                       track_index++;
+               }
+       }
+       plane_track->point_tracksnr = num_selected_tracks;
+
+       /* Setup new plane marker and add it to the track. */
+       plane_marker.framenr = framenr;
+       plane_marker.flag = 0;
+
+       copy_v2_v2(plane_marker.corners[0], tracks_min);
+       copy_v2_v2(plane_marker.corners[2], tracks_max);
+
+       plane_marker.corners[1][0] = tracks_max[0];
+       plane_marker.corners[1][1] = tracks_min[1];
+       plane_marker.corners[3][0] = tracks_min[0];
+       plane_marker.corners[3][1] = tracks_max[1];
+
+       BKE_tracking_plane_marker_insert(plane_track, &plane_marker);
+
+       /* Put new plane track to the list, ensure it's name is unique. */
+       BLI_addtail(plane_tracks_base, plane_track);
+       BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+
+       return plane_track;
+}
+
+void BKE_tracking_plane_track_unique_name(ListBase *plane_tracks_base, MovieTrackingPlaneTrack *plane_track)
+{
+       BLI_uniquename(plane_tracks_base, plane_track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Plane Track"), '.',
+                      offsetof(MovieTrackingPlaneTrack, name), sizeof(plane_track->name));
+}
+
+/* Free specified plane track, only frees contents of a structure
+ * (if track is allocated in heap, it shall be handled outside).
+ *
+ * All the pointers inside track becomes invalid after this call.
+ */
+void BKE_tracking_plane_track_free(MovieTrackingPlaneTrack *plane_track)
+{
+       if (plane_track->markers) {
+               MEM_freeN(plane_track->markers);
+       }
+
+       MEM_freeN(plane_track->point_tracks);
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_named(MovieTracking *tracking,
+                                                            MovieTrackingObject *object,
+                                                            const char *name)
+{
+       ListBase *plane_tracks_base = BKE_tracking_object_get_plane_tracks(tracking, object);
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (!strcmp(plane_track->name, name)) {
+                       return plane_track;
+               }
+       }
+
+       return NULL;
+}
+
+MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct MovieTracking *tracking)
+{
+       ListBase *plane_tracks_base;
+
+       if (tracking->act_plane_track == NULL) {
+               return NULL;
+       }
+
+       plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+
+       /* Check that active track is in current plane tracks list */
+       if (BLI_findindex(plane_tracks_base, tracking->act_plane_track) >= 0) {
+               return tracking->act_plane_track;
+       }
+
+       return NULL;
+}
+
+void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) {
+               plane_track->flag &= ~SELECT;
+       }
+}
+
+/*********************** Plane Marker *************************/
+
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track,
+                                                           MovieTrackingPlaneMarker *plane_marker)
+{
+       MovieTrackingPlaneMarker *old_plane_marker = NULL;
+
+       if (plane_track->markersnr)
+               old_plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, plane_marker->framenr);
+
+       if (old_plane_marker) {
+               /* Simply replace settings in existing marker. */
+               *old_plane_marker = *plane_marker;
+
+               return old_plane_marker;
+       }
+       else {
+               int a = plane_track->markersnr;
+
+               /* Find position in array where to add new marker. */
+               /* TODO(sergey): we coud use bisect to speed things up. */
+               while (a--) {
+                       if (plane_track->markers[a].framenr < plane_marker->framenr) {
+                               break;
+                       }
+               }
+
+               plane_track->markersnr++;
+               plane_track->markers = MEM_reallocN(plane_track->markers,
+                                                   sizeof(MovieTrackingPlaneMarker) * plane_track->markersnr);
+
+               /* Shift array to "free" space for new marker. */
+               memmove(plane_track->markers + a + 2, plane_track->markers + a + 1,
+                       (plane_track->markersnr - a - 2) * sizeof(MovieTrackingPlaneMarker));
+
+               /* Put new marker to an array. */
+               plane_track->markers[a + 1] = *plane_marker;
+               plane_track->last_marker = a + 1;
+
+               return &plane_track->markers[a + 1];
+       }
+}
+
+void BKE_tracking_plane_marker_delete(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       int a = 0;
+
+       while (a < plane_track->markersnr) {
+               if (plane_track->markers[a].framenr == framenr) {
+                       if (plane_track->markersnr > 1) {
+                               memmove(plane_track->markers + a, plane_track->markers + a + 1,
+                                       (plane_track->markersnr - a - 1) * sizeof(MovieTrackingPlaneMarker));
+                               plane_track->markersnr--;
+                               plane_track->markers = MEM_reallocN(plane_track->markers,
+                                                                   sizeof(MovieTrackingMarker) * plane_track->markersnr);
+                       }
+                       else {
+                               MEM_freeN(plane_track->markers);
+                               plane_track->markers = NULL;
+                               plane_track->markersnr = 0;
+                       }
+
+                       break;
+               }
+
+               a++;
+       }
+}
+
+/* TODO(sergey): The next couple of functions are really quite the same as point marker version,
+ *               would be nice to de-duplicate them somehow..
+ */
+
+/* Get a plane marker at given frame,
+ * If there's no such marker, closest one from the left side will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       int a = plane_track->markersnr - 1;
+
+       if (!plane_track->markersnr)
+               return NULL;
+
+       /* Approximate pre-first framenr marker with first marker. */
+       if (framenr < plane_track->markers[0].framenr) {
+               return &plane_track->markers[0];
+       }
+
+       if (plane_track->last_marker < plane_track->markersnr) {
+               a = plane_track->last_marker;
+       }
+
+       if (plane_track->markers[a].framenr <= framenr) {
+               while (a < plane_track->markersnr && plane_track->markers[a].framenr <= framenr) {
+                       if (plane_track->markers[a].framenr == framenr) {
+                               plane_track->last_marker = a;
+
+                               return &plane_track->markers[a];
+                       }
+                       a++;
+               }
+
+               /* If there's no marker for exact position, use nearest marker from left side. */
+               return &plane_track->markers[a - 1];
+       }
+       else {
+               while (a >= 0 && plane_track->markers[a].framenr >= framenr) {
+                       if (plane_track->markers[a].framenr == framenr) {
+                               plane_track->last_marker = a;
+
+                               return &plane_track->markers[a];
+                       }
+
+                       a--;
+               }
+
+               /* If there's no marker for exact position, use nearest marker from left side. */
+               return &plane_track->markers[a];
+       }
+
+       return NULL;
+}
+
+/* Get a plane marker at exact given frame, if there's no marker at the frame,
+ * NULL will be returned.
+ */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       if (plane_marker->framenr != framenr) {
+               return NULL;
+       }
+
+       return plane_marker;
+}
+
+/* Ensure there's a marker for the given frame. */
+MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTrack *plane_track, int framenr)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       if (plane_marker->framenr != framenr) {
+               MovieTrackingPlaneMarker plane_marker_new;
+
+               plane_marker_new = *plane_marker;
+               plane_marker_new.framenr = framenr;
+
+               plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker_new);
+       }
+
+       return plane_marker;
+}
+
 /*********************** Object *************************/
 
 MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name)
@@ -1379,6 +1706,15 @@ ListBase *BKE_tracking_object_get_tracks(MovieTracking *tracking, MovieTrackingO
        return &object->tracks;
 }
 
+ListBase *BKE_tracking_object_get_plane_tracks(MovieTracking *tracking, MovieTrackingObject *object)
+{
+       if (object->flag & TRACKING_OBJECT_CAMERA) {
+               return &tracking->plane_tracks;
+       }
+
+       return &object->plane_tracks;
+}
+
 MovieTrackingReconstruction *BKE_tracking_object_get_reconstruction(MovieTracking *tracking,
                                                                     MovieTrackingObject *object)
 {
@@ -2528,7 +2864,7 @@ static bool track_context_update_reference(MovieTrackingContext *context, TrackC
 }
 
 /* Fill in libmv tracker options structure with settings need to be used to perform track. */
-static void tracking_configure_tracker(MovieTrackingTrack *track, float *mask,
+static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
                                        libmv_TrackRegionOptions *options)
 {
        options->motion_model = track->motion_model;
@@ -2863,6 +3199,147 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi
        IMB_freeImBuf(destination_ibuf);
 }
 
+/*********************** Plane tracking *************************/
+
+typedef double Vec2[2];
+
+static int point_markers_correspondences_on_both_image(MovieTrackingPlaneTrack *plane_track, int frame1, int frame2,
+                                                       Vec2 **x1_r, Vec2 **x2_r)
+{
+       int i, correspondence_index;
+       Vec2 *x1, *x2;
+
+       *x1_r = x1 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x1");
+       *x2_r = x2 = MEM_mallocN(sizeof(*x1) * plane_track->point_tracksnr, "point correspondences x2");
+
+       for (i = 0, correspondence_index = 0; i < plane_track->point_tracksnr; i++) {
+               MovieTrackingTrack *point_track = plane_track->point_tracks[i];
+               MovieTrackingMarker *point_marker1, *point_marker2;
+
+               point_marker1 = BKE_tracking_marker_get_exact(point_track, frame1);
+               point_marker2 = BKE_tracking_marker_get_exact(point_track, frame2);
+
+               if (point_marker1 != NULL && point_marker2 != NULL) {
+                       /* Here conversion from float to double happens. */
+                       x1[correspondence_index][0] = point_marker1->pos[0];
+                       x1[correspondence_index][1] = point_marker1->pos[1];
+
+                       x2[correspondence_index][0] = point_marker2->pos[0];
+                       x2[correspondence_index][1] = point_marker2->pos[1];
+
+                       correspondence_index++;
+               }
+       }
+
+       return correspondence_index;
+}
+
+/* TODO(sergey): Make it generic function available for everyone. */
+BLI_INLINE void mat3f_from_mat3d(float mat_float[3][3], double mat_double[3][3])
+{
+       /* Keep it stupid simple for better data flow in CPU. */
+       mat_float[0][0] = mat_double[0][0];
+       mat_float[0][1] = mat_double[0][1];
+       mat_float[0][2] = mat_double[0][2];
+
+       mat_float[1][0] = mat_double[1][0];
+       mat_float[1][1] = mat_double[1][1];
+       mat_float[1][2] = mat_double[1][2];
+
+       mat_float[2][0] = mat_double[2][0];
+       mat_float[2][1] = mat_double[2][1];
+       mat_float[2][2] = mat_double[2][2];
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame, int direction)
+{
+       MovieTrackingPlaneMarker *start_plane_marker = BKE_tracking_plane_marker_get(plane_track, start_frame);
+       MovieTrackingPlaneMarker new_plane_marker;
+       int current_frame, frame_delta = direction > 0 ? 1 : -1;
+
+       new_plane_marker = *start_plane_marker;
+       new_plane_marker.flag |= PLANE_MARKER_TRACKED;
+
+       for (current_frame = start_frame; ; current_frame += frame_delta) {
+               MovieTrackingPlaneMarker *next_plane_marker =
+                       BKE_tracking_plane_marker_get_exact(plane_track, current_frame + frame_delta);
+               Vec2 *x1, *x2;
+               int i, num_correspondences;
+               double H_double[3][3];
+               float H[3][3];
+
+               /* As soon as we meet keyframed plane, we stop updating the sequence. */
+               if (next_plane_marker && (next_plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
+                       break;
+               }
+
+               num_correspondences =
+                       point_markers_correspondences_on_both_image(plane_track, current_frame, current_frame + frame_delta,
+                                                                   &x1, &x2);
+
+               if (num_correspondences < 4) {
+                       MEM_freeN(x1);
+                       MEM_freeN(x2);
+
+                       break;
+               }
+
+               libmv_homography2DFromCorrespondencesLinear(x1, x2, num_correspondences, H_double, 1e-8);
+
+               mat3f_from_mat3d(H, H_double);
+
+               for (i = 0; i < 4; i++) {
+                       float vec[3] = {0.0f, 0.0f, 1.0f}, vec2[3];
+                       copy_v2_v2(vec, new_plane_marker.corners[i]);
+
+                       /* Apply homography */
+                       mul_v3_m3v3(vec2, H, vec);
+
+                       /* Normalize. */
+                       vec2[0] /= vec2[2];
+                       vec2[1] /= vec2[2];
+
+                       copy_v2_v2(new_plane_marker.corners[i], vec2);
+               }
+
+               new_plane_marker.framenr = current_frame + frame_delta;
+
+               BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+
+               MEM_freeN(x1);
+               MEM_freeN(x2);
+       }
+}
+
+/* NOTE: frame number should be in clip space, not scene space */
+void BKE_tracking_track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_track, int start_frame)
+{
+       track_plane_from_existing_motion(plane_track, start_frame, 1);
+       track_plane_from_existing_motion(plane_track, start_frame, -1);
+}
+
+BLI_INLINE void float_corners_to_double(/*const*/ float corners[4][2], double double_corners[4][2])
+{
+       copy_v2db_v2fl(double_corners[0], corners[0]);
+       copy_v2db_v2fl(double_corners[1], corners[1]);
+       copy_v2db_v2fl(double_corners[2], corners[2]);
+       copy_v2db_v2fl(double_corners[3], corners[3]);
+}
+
+void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3])
+{
+       Vec2 x1[4], x2[4];
+       double H_double[3][3];
+
+       float_corners_to_double(reference_corners, x1);
+       float_corners_to_double(corners, x2);
+
+       libmv_homography2DFromCorrespondencesLinear(x1, x2, 4, H_double, 1e-8);
+
+       mat3f_from_mat3d(H, H_double);
+}
+
 /*********************** Camera solving *************************/
 
 typedef struct MovieReconstructContext {
@@ -3264,7 +3741,6 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const
 
        BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message);
 }
-
 /* FIll in camera intrinsics structure from reconstruction context. */
 static void camraIntrincicsOptionsFromContext(libmv_CameraIntrinsicsOptions *camera_intrinsics_options,
                                               MovieReconstructContext *context)
index ef5cb8bde04f7660cba0d7374836feee1956eaf2..566fc95eb4f20ed31db21f214e616c1202acf132 100644 (file)
@@ -173,4 +173,14 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
                MEM_freeN(arr);                                                       \
        } (void)0
 
+
+void _bli_array_reverse(void *arr, unsigned int arr_len, size_t arr_stride);
+#define BLI_array_reverse(arr, arr_len) \
+       _bli_array_reverse(arr, arr_len, sizeof(*(arr)))
+
+void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir);
+#define BLI_array_wrap(arr, arr_len, dir) \
+       _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir)
+
+
 #endif  /* __BLI_ARRAY_H__ */
index 3e7fdc8bf751bf1c166b0c7605c25c6b7ab4968c..9c1e1f88bab1395012830556806bccd0c3ed199d 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 struct MemArena;
+struct BLI_mempool;
 
 typedef void (*LinkNodeFreeFP)(void *link);
 typedef void (*LinkNodeApplyFP)(void *link, void *userdata);
@@ -56,10 +57,14 @@ void    BLI_linklist_reverse(struct LinkNode **listp);
 void    BLI_linklist_prepend(struct LinkNode **listp, void *ptr);
 void    BLI_linklist_append(struct LinkNode **listp, void *ptr);
 void    BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct MemArena *ma);
+void    BLI_linklist_prepend_pool(struct LinkNode **listp, void *ptr, struct BLI_mempool *mempool);
+void   *BLI_linklist_pop(struct LinkNode **listp);
+void   *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool);
 void    BLI_linklist_insert_after(struct LinkNode **listp, void *ptr);
 
 void    BLI_linklist_free(struct LinkNode *list, LinkNodeFreeFP freefunc);
 void    BLI_linklist_freeN(struct LinkNode *list);
+void    BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool);
 void    BLI_linklist_apply(struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
 
 #endif
index 4b71babdba18589849cd8202f095e815ff803843..69dbd3253f00258201f93d781c19f877b03e6199 100644 (file)
 #define MAXFLOAT  ((float)3.40282347e+38)
 #endif
 
+#if defined(__GNUC__)
+#  define NAN_FLT __builtin_nanf("")
+#else
+/* evil quiet NaN definition */
+static const int NAN_INT = 0x7FC00000;
+#  define NAN_FLT  (*((float *)(&NAN_INT)))
+#endif
+
 /* do not redefine functions from C99 or POSIX.1-2001 */
 #if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L))
 
index 5823b7db3f1991f48123721f1b1d3e26d409a8a1..510bf072513d1cc358b2064e5b15008dd4d9f034 100644 (file)
  */
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "BLI_array.h"
 
+#include "BLI_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+
 #include "MEM_guardedalloc.h"
 
 /**
@@ -95,3 +100,40 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static,
        arr_count += num;
 #endif
 }
+
+void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride)
+{
+       const unsigned int arr_half_stride = (arr_len / 2) * arr_stride;
+       unsigned int i, i_end;
+       char *arr = arr_v;
+       char *buf = BLI_array_alloca(buf, arr_stride);
+
+       for (i = 0, i_end = (arr_len - 1) * arr_stride;
+            i < arr_half_stride;
+            i += arr_stride, i_end -= arr_stride)
+       {
+               memcpy(buf, &arr[i], arr_stride);
+               memcpy(&arr[i], &arr[i_end], arr_stride);
+               memcpy(&arr[i_end], buf, arr_stride);
+       }
+}
+
+void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int dir)
+{
+       char *arr = arr_v;
+       char *buf = BLI_array_alloca(buf, arr_stride);
+
+       if (dir == -1) {
+               memcpy(buf, arr, arr_stride);
+               memmove(arr, arr + arr_stride, arr_stride * (arr_len - 1));
+               memcpy(arr + (arr_stride * (arr_len - 1)), buf, arr_stride);
+       }
+       else if (dir == 1) {
+               memcpy(buf, arr + (arr_stride * (arr_len - 1)), arr_stride);
+               memmove(arr + arr_stride, arr, arr_stride * (arr_len - 1));
+               memcpy(arr, buf, arr_stride);
+       }
+       else {
+               BLI_assert(0);
+       }
+}
index b08fbe17a43d9d71e83cc36621bd835213a69bdd..99fc5f27726139b9c903afc301c8a9dd71fe0fdb 100644 (file)
@@ -34,6 +34,7 @@
 #include "MEM_guardedalloc.h"
 #include "BLI_linklist.h"
 #include "BLI_memarena.h"
+#include "BLI_mempool.h"
 
 int BLI_linklist_length(LinkNode *list)
 {
@@ -125,6 +126,39 @@ void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma)
        *listp = nlink;
 }
 
+void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool)
+{
+       LinkNode *nlink = BLI_mempool_alloc(mempool);
+       nlink->link = ptr;
+
+       nlink->next = *listp;
+       *listp = nlink;
+}
+
+void *BLI_linklist_pop(struct LinkNode **listp)
+{
+       /* intentionally no NULL check */
+       void *link = (*listp)->link;
+       void *next = (*listp)->next;
+
+       MEM_freeN((*listp));
+
+       *listp = next;
+       return link;
+}
+
+void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool)
+{
+       /* intentionally no NULL check */
+       void *link = (*listp)->link;
+       void *next = (*listp)->next;
+
+       BLI_mempool_free(mempool, (*listp));
+
+       *listp = next;
+       return link;
+}
+
 void BLI_linklist_insert_after(LinkNode **listp, void *ptr)
 {
        LinkNode *nlink = MEM_mallocN(sizeof(*nlink), "nlink");
@@ -155,6 +189,19 @@ void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc)
        }
 }
 
+void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool)
+{
+       while (list) {
+               LinkNode *next = list->next;
+
+               if (freefunc)
+                       freefunc(list->link);
+               BLI_mempool_free(mempool, list);
+
+               list = next;
+       }
+}
+
 void BLI_linklist_freeN(LinkNode *list)
 {
        while (list) {
index 1f8bbfbec8894fec25360e81b20fb698d8e48f8a..37cebc3063d82adac465505a534a37fd064a6dbb 100644 (file)
@@ -4345,7 +4345,7 @@ static void lib_link_object(FileData *fd, Main *main)
                                /* Only expand so as not to loose any object materials that might be set. */
                                if (totcol_data && (*totcol_data > ob->totcol)) {
                                        /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
-                                       resize_object_material(ob, *totcol_data);
+                                       BKE_material_resize_object(ob, *totcol_data, false);
                                }
                        }
                        
@@ -6687,6 +6687,28 @@ static void direct_link_movieTracks(FileData *fd, ListBase *tracksbase)
        }
 }
 
+static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       link_list(fd, plane_tracks_base);
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               int i;
+
+               plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks);
+
+               for (i = 0; i < plane_track->point_tracksnr; i++) {
+                       plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]);
+               }
+
+               plane_track->markers = newdataadr(fd, plane_track->markers);
+       }
+}
+
 static void direct_link_movieclip(FileData *fd, MovieClip *clip)
 {
        MovieTracking *tracking = &clip->tracking;
@@ -6701,9 +6723,11 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        else clip->tracking.camera.intrinsics = NULL;
 
        direct_link_movieTracks(fd, &tracking->tracks);
+       direct_link_moviePlaneTracks(fd, &tracking->plane_tracks);
        direct_link_movieReconstruction(fd, &tracking->reconstruction);
 
        clip->tracking.act_track = newdataadr(fd, clip->tracking.act_track);
+       clip->tracking.act_plane_track = newdataadr(fd, clip->tracking.act_plane_track);
 
        clip->anim = NULL;
        clip->tracking_context = NULL;
@@ -6720,6 +6744,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        
        for (object = tracking->objects.first; object; object = object->next) {
                direct_link_movieTracks(fd, &object->tracks);
+               direct_link_moviePlaneTracks(fd, &object->plane_tracks);
                direct_link_movieReconstruction(fd, &object->reconstruction);
        }
 }
index 4f0ccd3c62652fb7acdb181286bf1dea43835765..f3d58c42bc8d8126015968fba40d1447d7bae904 100644 (file)
@@ -2920,6 +2920,21 @@ static void write_movieTracks(WriteData *wd, ListBase *tracks)
        }
 }
 
+static void write_moviePlaneTracks(WriteData *wd, ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               writestruct(wd, DATA, "MovieTrackingPlaneTrack", 1, plane_track);
+
+               writedata(wd, DATA, sizeof(MovieTrackingTrack *) * plane_track->point_tracksnr, plane_track->point_tracks);
+               writestruct(wd, DATA, "MovieTrackingPlaneMarker", plane_track->markersnr, plane_track->markers);
+       }
+}
+
 static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction *reconstruction)
 {
        if (reconstruction->camnr)
@@ -2944,6 +2959,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
                                write_animdata(wd, clip->adt);
 
                        write_movieTracks(wd, &tracking->tracks);
+                       write_moviePlaneTracks(wd, &tracking->plane_tracks);
                        write_movieReconstruction(wd, &tracking->reconstruction);
 
                        object= tracking->objects.first;
@@ -2951,6 +2967,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
                                writestruct(wd, DATA, "MovieTrackingObject", 1, object);
 
                                write_movieTracks(wd, &object->tracks);
+                               write_moviePlaneTracks(wd, &object->plane_tracks);
                                write_movieReconstruction(wd, &object->reconstruction);
 
                                object= object->next;
index bec301acaa91d82d8d9f1521b5ae161da048ed27..0a6c0f4b2934d89961fd8e791f1188b35c71c4cf 100644 (file)
@@ -816,6 +816,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
        }
 }
 
+static BMEditSelection *bm_select_history_create(BMHeader *ele)
+{
+       BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection");
+       ese->htype = ele->htype;
+       ese->ele = (BMElem *)ele;
+       return ese;
+}
 
 /* --- macro wrapped funcs --- */
 bool _bm_select_history_check(BMesh *bm, const BMHeader *ele)
@@ -837,9 +844,7 @@ bool _bm_select_history_remove(BMesh *bm, BMHeader *ele)
 
 void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele)
 {
-       BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection");
-       ese->htype = ele->htype;
-       ese->ele = (BMElem *)ele;
+       BMEditSelection *ese = bm_select_history_create(ele);
        BLI_addtail(&(bm->selected), ese);
 }
 
@@ -849,6 +854,20 @@ void _bm_select_history_store(BMesh *bm, BMHeader *ele)
                BM_select_history_store_notest(bm, (BMElem *)ele);
        }
 }
+
+
+void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele)
+{
+       BMEditSelection *ese = bm_select_history_create(ele);
+       BLI_insertlinkafter(&(bm->selected), ese_ref, ese);
+}
+
+void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele)
+{
+       if (!BM_select_history_check(bm, (BMElem *)ele)) {
+               BM_select_history_store_after_notest(bm, ese_ref, (BMElem *)ele);
+       }
+}
 /* --- end macro wrapped funcs --- */
 
 
@@ -861,16 +880,13 @@ void BM_select_history_clear(BMesh *bm)
 
 void BM_select_history_validate(BMesh *bm)
 {
-       BMEditSelection *ese, *nextese;
-
-       ese = bm->selected.first;
+       BMEditSelection *ese, *ese_next;
 
-       while (ese) {
-               nextese = ese->next;
+       for (ese = bm->selected.first; ese; ese = ese_next) {
+               ese_next = ese->next;
                if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
                        BLI_freelinkN(&(bm->selected), ese);
                }
-               ese = nextese;
        }
 }
 
index 062de4f69e1fafe2b16fceb6b2ba8637ed10c8ea..f23eac61278f1b8c81385e14c2e2e371a11a6ca9 100644 (file)
@@ -87,11 +87,15 @@ void    BM_editselection_plane(BMEditSelection *ese,  float r_plane[3]);
 #define BM_select_history_remove(bm, ele)       _bm_select_history_remove(bm,       &(ele)->head)
 #define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head)
 #define BM_select_history_store(bm, ele)        _bm_select_history_store(bm,        &(ele)->head)
+#define BM_select_history_store_after_notest(bm, ese_ref, ele) _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head)
+#define BM_select_history_store_after(bm, ese, ese_ref)        _bm_select_history_store_after(bm,        ese_ref, &(ele)->head)
 
 bool _bm_select_history_check(BMesh *bm,  const BMHeader *ele);
 bool _bm_select_history_remove(BMesh *bm,       BMHeader *ele);
 void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele);
 void _bm_select_history_store(BMesh *bm,        BMHeader *ele);
+void _bm_select_history_store_after(BMesh *bm,  BMEditSelection *ese_ref, BMHeader *ele);
+void _bm_select_history_store_after_notest(BMesh *bm,  BMEditSelection *ese_ref, BMHeader *ele);
 
 void BM_select_history_validate(BMesh *bm);
 void BM_select_history_clear(BMesh *em);
index 0eb3b0a6443b5bc91983921a20c16d9258c2df37..6eab3c625fa0ba4da47b27a75f956c05679fb186 100644 (file)
@@ -1986,7 +1986,7 @@ int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde
 
                BM_elem_index_set(e, i); /* set_inline */
        }
-       bm->elem_index_dirty &= ~BM_FACE;
+       bm->elem_index_dirty &= ~BM_EDGE;
 
        /* detect groups */
        stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__);
index 4e78d1dc494aed3e13353bf71521360394f50a55..923b877b82209b18a09a9c7932dc65e09b626555 100644 (file)
@@ -31,6 +31,7 @@
 #include "BLI_listbase.h"
 #include "BLI_math.h"
 #include "BLI_array.h"
+#include "BLI_alloca.h"
 #include "BLI_smallhash.h"
 #include "BLI_rand.h"
 #include "BLI_heap.h"
@@ -885,27 +886,82 @@ BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int wind
        winding[(test_v1 == node->v)]++;
 }
 
+static BMFace *bm_face_from_path(BMesh *bm, EPath *path,
+                                 EdgeData *edata,
+                                 const bool use_fill_check)
+{
+       /* accumulte winding directions for each edge which has a face */
+       const unsigned int path_len = BLI_countlist(&path->nodes);
+       unsigned int winding[2] = {0, 0};
+       unsigned int i;
+
+       EPathNode *node;
+
+       BMVert **verts = BLI_array_alloca(verts, path_len);
+       BMEdge **edges = BLI_array_alloca(edges, path_len);
+       BMEdge *e;
+       BMVert *v;
+
+       for (node = path->nodes.first, i = 0; node; node = node->next, i++) {
+
+               v = node->v;
+               e = BM_edge_exists(v, node->next ?
+                                     node->next->v :
+                                     ((EPathNode *)path->nodes.first)->v);
+
+               /* check on the winding */
+               if (e->l) {
+                       if (UNLIKELY(count_edge_faces(bm, e) >= 2)) {
+                               return NULL;
+                       }
+
+                       vote_on_winding(e, node, winding);
+               }
+
+               verts[i] = v;
+               edges[i] = e;
+       }
+
+       /* do after incase we bail early, above */
+       for (i = 0; i < path_len; i++) {
+               edata[BM_elem_index_get(edges[i])].ftag++;
+       }
+
+
+       /* if these are even it doesn't really matter what to do,
+        * with consistent geometry one will be zero, the choice is clear */
+       if (winding[0] > winding[1]) {
+               BLI_array_wrap(verts, path_len, -1);
+               BLI_array_reverse(verts, path_len);
+               BLI_array_reverse(edges, path_len);
+       }
+
+       if ((use_fill_check == false) ||
+           /* fairly expensive check - see if there are already faces filling this area */
+           (BM_face_exists_multi(verts, edges, path_len) == false))
+       {
+               return BM_face_create(bm, verts, edges, path_len, BM_CREATE_NO_DOUBLE);
+       }
+       else {
+               return NULL;
+       }
+}
+
 void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
 {
        BMIter iter;
        BMOIter siter;
        BMFace *f;
        BMEdge *e;
-       BMVert **verts = NULL;
-       BLI_array_declare(verts);
        EPath *path;
-       EPathNode *node;
        EdgeData *edata;
        VertData *vdata;
-       BMEdge **edges = NULL;
        PathBase *pathbase;
-       BLI_array_declare(edges);
        const bool use_restrict   = BMO_slot_bool_get(op->slots_in, "use_restrict");
        const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
        const short mat_nr        = BMO_slot_int_get(op->slots_in,  "mat_nr");
        const bool use_smooth     = BMO_slot_bool_get(op->slots_in, "use_smooth");
-       int i, j;
-       unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
+       int i;
        BMOpSlot *slot_restrict          = BMO_slot_get(op->slots_in, "restrict");
        BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
 
@@ -978,99 +1034,28 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
                edata[BM_elem_index_get(edge)].tag += 1;
 
                path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
-               if (!path)
-                       continue;
-
-               winding[0] = winding[1] = 0;
-
-               BLI_array_empty(edges);
-               BLI_array_empty(verts);
-               i = 0;
-               for (node = path->nodes.first; node; node = node->next) {
-                       if (!node->next)
-                               continue;
-
-                       e = BM_edge_exists(node->v, node->next->v);
-
-                       /* this should never happe */
-                       if (!e)
-                               break;
-
-                       /* check on the winding */
-                       if (e->l) {
-                               vote_on_winding(e, node, winding);
-                       }
-
-                       edata[BM_elem_index_get(e)].ftag++;
-                       BLI_array_grow_one(edges);
-                       edges[i++] = e;
-
-                       BLI_array_append(verts, node->v);
-               }
-
-               if (edge->l) {
-                       vote_on_winding(edge, path->nodes.last, winding);
-               }
-
-               BLI_array_grow_one(edges);
-               edges[i++] = edge;
-               edata[BM_elem_index_get(edge)].ftag++;
-
-               for (j = 0; j < i; j++) {
-                       if (count_edge_faces(bm, edges[j]) >= 2) {
-                               edge_free_path(pathbase, path);
-                               break;
+               if (path && path->nodes.first) {
+                       BMFace *f = bm_face_from_path(bm, path, edata,
+                                                     use_fill_check);
+
+                       if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
+                               BMO_elem_flag_enable(bm, f, FACE_NEW);
+                               f->mat_nr = mat_nr;
+                               if (use_smooth) {
+                                       BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+                               }
                        }
-               }
 
-               if (j != i) {
-                       continue;
-               }
-
-               if (i) {
-                       BMVert *v1, *v2;
-
-                       /* to define the winding order must select first edge,
-                        * otherwise we could leave this as-is */
-                       edge = edges[0];
-
-                       /* if these are even it doesn't really matter what to do,
-                        * with consistent geometry one will be zero, the choice is clear */
-                       if (winding[0] < winding[1]) {
-                               v1 = verts[0];
-                               v2 = verts[1];
-                       }
-                       else {
-                               v1 = verts[1];
-                               v2 = verts[0];
+                       if (use_restrict) {
+                               BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
                        }
 
-                       if ((use_fill_check == false) ||
-                           /* fairly expensive check - see if there are already faces filling this area */
-                           (BM_face_exists_multi_edge(edges, i) == false))
-                       {
-                               f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE);
-                               if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
-                                       BMO_elem_flag_enable(bm, f, FACE_NEW);
-                                       f->mat_nr = mat_nr;
-                                       if (use_smooth) {
-                                               BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
-                                       }
-                               }
-
-                               if (use_restrict) {
-                                       BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
-                               }
-                       }
+                       edge_free_path(pathbase, path);
                }
-
-               edge_free_path(pathbase, path);
        }
 
        BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
 
-       BLI_array_free(edges);
-       BLI_array_free(verts);
        edge_pathbase_free(pathbase);
        MEM_freeN(edata);
        MEM_freeN(vdata);
index adcf325b51c8db3c20dd5bc9850fba0187fcba77..aad600d13fa9e527afba68a97feb3a07c9f48f5c 100644 (file)
@@ -103,6 +103,21 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
        BMIter iter;
        BMEdge *e;
 
+       bool use_ese = false;
+       GHash *ese_gh = NULL;
+
+       if (copy_select && bm->selected.first) {
+               BMEditSelection *ese;
+
+               ese_gh = BLI_ghash_ptr_new(__func__);
+               for (ese = bm->selected.first; ese; ese = ese->next) {
+                       if (ese->htype != BM_FACE) {
+                               BLI_ghash_insert(ese_gh, ese->ele, ese);
+                       }
+               }
+
+               use_ese = true;
+       }
 
        if (tag_only == false) {
                BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false);
@@ -135,9 +150,18 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
                        BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
 
                        /* keep splitting until each loop has its own edge */
-                       do {
-                               bmesh_edge_separate(bm, e, e->l, copy_select);
-                       } while (!BM_edge_is_boundary(e));
+                       while (!BM_edge_is_boundary(e)) {
+                               BMLoop *l_sep = e->l;
+                               bmesh_edge_separate(bm, e, l_sep, copy_select);
+                               BLI_assert(l_sep->e != e);
+
+                               if (use_ese) {
+                                       BMEditSelection *ese = BLI_ghash_lookup(ese_gh, e);
+                                       if (UNLIKELY(ese)) {
+                                               BM_select_history_store_after_notest(bm, ese, l_sep->e);
+                                       }
+                               }
+                       }
 
                        BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
                        BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
@@ -157,14 +181,39 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con
 
        BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
                if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
-                       if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) {
-                               BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
-                               bmesh_vert_separate(bm, e->v1, NULL, NULL, copy_select);
-                       }
-                       if (BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
-                               BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
-                               bmesh_vert_separate(bm, e->v2, NULL, NULL, copy_select);
+                       unsigned int i;
+                       for (i = 0; i < 2; i++) {
+                               BMVert *v = ((&e->v1)[i]);
+                               if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+                                       BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+                                       if (use_ese) {
+                                               BMVert **vtar;
+                                               int vtar_len;
+
+                                               bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select);
+
+                                               if (vtar_len) {
+                                                       BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v);
+                                                       if (UNLIKELY(ese)) {
+                                                               int j;
+                                                               for (j = 0; j < vtar_len; j++) {
+                                                                       BLI_assert(v != vtar[j]);
+                                                                       BM_select_history_store_after_notest(bm, ese, vtar[j]);
+                                                               }
+                                                       }
+                                               }
+                                               MEM_freeN(vtar);
+                                       }
+                                       else {
+                                               bmesh_vert_separate(bm, v, NULL, NULL, copy_select);
+                                       }
+                               }
                        }
                }
        }
+
+       if (use_ese) {
+               BLI_ghash_free(ese_gh, NULL, NULL);
+       }
 }
index c1b99274bed0d877c7af509add1494653434705e..a119a89c842852f9ba29a063477789006d0c11e1 100644 (file)
@@ -184,6 +184,9 @@ set(SRC
        nodes/COM_GlareNode.cpp
        nodes/COM_GlareNode.h
 
+       nodes/COM_PlaneTrackDeformNode.cpp
+       nodes/COM_PlaneTrackDeformNode.h
+
        nodes/COM_CropNode.cpp
        nodes/COM_CropNode.h
        operations/COM_CropOperation.cpp
@@ -595,6 +598,12 @@ set(SRC
        operations/COM_ProjectorLensDistortionOperation.h
        operations/COM_ScreenLensDistortionOperation.cpp
        operations/COM_ScreenLensDistortionOperation.h
+       operations/COM_PlaneTrackCommonOperation.cpp
+       operations/COM_PlaneTrackCommonOperation.h
+       operations/COM_PlaneTrackMaskOperation.cpp
+       operations/COM_PlaneTrackMaskOperation.h
+       operations/COM_PlaneTrackWarpImageOperation.cpp
+       operations/COM_PlaneTrackWarpImageOperation.h
 
        #Filter operations
        operations/COM_ConvolutionFilterOperation.h
index 80ae952b87f6d72037b0db95a902cf9058d2f70f..db0cdd1692e2b160f477fb4a3f2b4cc21b8a8a8d 100644 (file)
 #include "COM_ViewerNode.h"
 #include "COM_ZCombineNode.h"
 #include "COM_PixelateNode.h"
+#include "COM_PlaneTrackDeformNode.h"
 
 Node *Converter::convert(bNode *b_node, bool fast)
 {
@@ -402,6 +403,9 @@ Node *Converter::convert(bNode *b_node, bool fast)
                case CMP_NODE_PIXELATE:
                        node = new PixelateNode(b_node);
                        break;
+               case CMP_NODE_PLANETRACKDEFORM:
+                       node = new PlaneTrackDeformNode(b_node);
+                       break;
                default:
                        node = new MuteNode(b_node);
                        break;
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
new file mode 100644 (file)
index 0000000..d6434c2
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Jeroen Bakker
+ *             Monique Dewanchand
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackDeformNode.h"
+#include "COM_ExecutionSystem.h"
+
+#include "COM_PlaneTrackMaskOperation.h"
+#include "COM_PlaneTrackWarpImageOperation.h"
+
+extern "C" {
+       #include "BKE_node.h"
+       #include "BKE_movieclip.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode)
+{
+       /* pass */
+}
+
+void PlaneTrackDeformNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
+{
+       InputSocket *input_image = this->getInputSocket(0);
+
+       OutputSocket *output_warped_image = this->getOutputSocket(0);
+       OutputSocket *output_plane = this->getOutputSocket(1);
+
+       bNode *editorNode = this->getbNode();
+       MovieClip *clip = (MovieClip *) editorNode->id;
+
+       NodePlaneTrackDeformData *data = (NodePlaneTrackDeformData *) editorNode->storage;
+
+       int frame_number = context->getFramenumber();
+
+       if (output_warped_image->isConnected()) {
+               PlaneTrackWarpImageOperation *warp_image_operation = new PlaneTrackWarpImageOperation();
+
+               warp_image_operation->setMovieClip(clip);
+               warp_image_operation->setTrackingObject(data->tracking_object);
+               warp_image_operation->setPlaneTrackName(data->plane_track_name);
+               warp_image_operation->setFramenumber(frame_number);
+
+               input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
+               output_warped_image->relinkConnections(warp_image_operation->getOutputSocket());
+
+               graph->addOperation(warp_image_operation);
+       }
+
+       if (output_plane->isConnected()) {
+               PlaneTrackMaskOperation *plane_mask_operation = new PlaneTrackMaskOperation();
+
+               plane_mask_operation->setMovieClip(clip);
+               plane_mask_operation->setTrackingObject(data->tracking_object);
+               plane_mask_operation->setPlaneTrackName(data->plane_track_name);
+               plane_mask_operation->setFramenumber(frame_number);
+
+               output_plane->relinkConnections(plane_mask_operation->getOutputSocket());
+
+               graph->addOperation(plane_mask_operation);
+       }
+}
diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
new file mode 100644 (file)
index 0000000..cf173cd
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#include "COM_Node.h"
+#include "DNA_node_types.h"
+
+extern "C" {
+       #include "DNA_movieclip_types.h"
+       #include "DNA_node_types.h"
+}
+
+/**
+ * @brief PlaneTrackDeformNode
+ * @ingroup Node
+ */
+class PlaneTrackDeformNode : public Node {
+public:
+       PlaneTrackDeformNode(bNode *editorNode);
+       void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
+};
index c8e3dbf993dfe05549f226524e1bb1a3809a6694..89a56af6b158eca9ff1f83401f862177ff11b360 100644 (file)
@@ -40,7 +40,8 @@ BaseImageOperation::BaseImageOperation() : NodeOperation()
 {
        this->m_image = NULL;
        this->m_buffer = NULL;
-       this->m_imageBuffer = NULL;
+       this->m_imageFloatBuffer = NULL;
+       this->m_imageByteBuffer = NULL;
        this->m_imageUser = NULL;
        this->m_imagewidth = 0;
        this->m_imageheight = 0;
@@ -70,10 +71,6 @@ ImBuf *BaseImageOperation::getImBuf()
                BKE_image_release_ibuf(this->m_image, ibuf, NULL);
                return NULL;
        }
-       
-       if (ibuf->rect_float == NULL) {
-               IMB_float_from_rect(ibuf);
-       }
        return ibuf;
 }
 
@@ -83,7 +80,8 @@ void BaseImageOperation::initExecution()
        ImBuf *stackbuf = getImBuf();
        this->m_buffer = stackbuf;
        if (stackbuf) {
-               this->m_imageBuffer = stackbuf->rect_float;
+               this->m_imageFloatBuffer = stackbuf->rect_float;
+               this->m_imageByteBuffer = stackbuf->rect;
                this->m_depthBuffer = stackbuf->zbuf_float;
                this->m_imagewidth = stackbuf->x;
                this->m_imageheight = stackbuf->y;
@@ -93,7 +91,8 @@ void BaseImageOperation::initExecution()
 
 void BaseImageOperation::deinitExecution()
 {
-       this->m_imageBuffer = NULL;
+       this->m_imageFloatBuffer = NULL;
+       this->m_imageByteBuffer = NULL;
        BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL);
 }
 
@@ -112,23 +111,48 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne
        BKE_image_release_ibuf(this->m_image, stackbuf, NULL);
 }
 
-void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+static void sampleImageAtLocation(ImBuf *ibuf, float x, float y, PixelSampler sampler, bool make_linear_rgb, float color[4])
 {
-       if (this->m_imageBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
-               zero_v4(output);
+       if (ibuf->rect_float) {
+               switch (sampler) {
+                       case COM_PS_NEAREST:
+                               nearest_interpolation_color(ibuf, NULL, color, x, y);
+                               break;
+                       case COM_PS_BILINEAR:
+                               bilinear_interpolation_color(ibuf, NULL, color, x, y);
+                               break;
+                       case COM_PS_BICUBIC:
+                               bicubic_interpolation_color(ibuf, NULL, color, x, y);
+                               break;
+               }
        }
        else {
+               unsigned char byte_color[4];
                switch (sampler) {
                        case COM_PS_NEAREST:
-                               nearest_interpolation_color(this->m_buffer, NULL, output, x, y);
+                               nearest_interpolation_color(ibuf, byte_color, NULL, x, y);
                                break;
                        case COM_PS_BILINEAR:
-                               bilinear_interpolation_color(this->m_buffer, NULL, output, x, y);
+                               bilinear_interpolation_color(ibuf, byte_color, NULL, x, y);
                                break;
                        case COM_PS_BICUBIC:
-                               bicubic_interpolation_color(this->m_buffer, NULL, output, x, y);
+                               bicubic_interpolation_color(ibuf, byte_color, NULL, x, y);
                                break;
                }
+               rgba_uchar_to_float(color, byte_color);
+               if (make_linear_rgb) {
+                       IMB_colormanagement_colorspace_to_scene_linear_v4(color, FALSE, ibuf->rect_colorspace);
+               }
+       }
+}
+
+void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+               zero_v4(output);
+       }
+       else {
+               sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output);
        }
 }
 
@@ -136,22 +160,12 @@ void ImageAlphaOperation::executePixel(float output[4], float x, float y, PixelS
 {
        float tempcolor[4];
 
-       if (this->m_imageBuffer == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
+       if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) {
                output[0] = 0.0f;
        }
        else {
                tempcolor[3] = 1.0f;
-               switch (sampler) {
-                       case COM_PS_NEAREST:
-                               nearest_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
-                               break;
-                       case COM_PS_BILINEAR:
-                               bilinear_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
-                               break;
-                       case COM_PS_BICUBIC:
-                               bicubic_interpolation_color(this->m_buffer, NULL, tempcolor, x, y);
-                               break;
-               }
+               sampleImageAtLocation(this->m_buffer, x, y, sampler, false, tempcolor);
                output[0] = tempcolor[3];
        }
 }
index e75e7daa186153985059547159cbce08bb354e18..b51f11edd0406cf76f6d86eae9d002e2109f14a8 100644 (file)
@@ -42,7 +42,8 @@ protected:
        ImBuf *m_buffer;
        Image *m_image;
        ImageUser *m_imageUser;
-       float *m_imageBuffer;
+       float *m_imageFloatBuffer;
+       unsigned int *m_imageByteBuffer;
        float *m_depthBuffer;
        int m_imageheight;
        int m_imagewidth;
index 1c9dd0f170ef6b5fdfe19611766ce5387147f7cf..1a2a1e778338c15cb028e9d6330f7fc651b52d80 100644 (file)
@@ -47,7 +47,7 @@ void MultilayerColorOperation::executePixel(float output[4], float x, float y, P
 {
        int yi = y;
        int xi = x;
-       if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+       if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
                zero_v4(output);
        }
        else {
@@ -66,7 +66,7 @@ void MultilayerColorOperation::executePixel(float output[4], float x, float y, P
                }
                else {
                        int offset = (yi * this->getWidth() + xi) * 3;
-                       copy_v3_v3(output, &this->m_imageBuffer[offset]);
+                       copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
                }
        }
 }
@@ -75,11 +75,11 @@ void MultilayerValueOperation::executePixel(float output[4], float x, float y, P
 {
        int yi = y;
        int xi = x;
-       if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+       if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
                output[0] = 0.0f;
        }
        else {
-               float result = this->m_imageBuffer[yi * this->getWidth() + xi];
+               float result = this->m_imageFloatBuffer[yi * this->getWidth() + xi];
                output[0] = result;
        }
 }
@@ -88,11 +88,11 @@ void MultilayerVectorOperation::executePixel(float output[4], float x, float y,
 {
        int yi = y;
        int xi = x;
-       if (this->m_imageBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
+       if (this->m_imageFloatBuffer == NULL || xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight() ) {
                output[0] = 0.0f;
        }
        else {
                int offset = (yi * this->getWidth() + xi) * 3;
-               copy_v3_v3(output, &this->m_imageBuffer[offset]);
+               copy_v3_v3(output, &this->m_imageFloatBuffer[offset]);
        }
 }
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp
new file mode 100644 (file)
index 0000000..51e803f
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackCommonOperation::PlaneTrackCommonOperation() : NodeOperation()
+{
+       this->m_movieClip = NULL;
+       this->m_framenumber = 0;
+       this->m_trackingObjectName[0] = '\0';
+       this->m_planeTrackName[0] = '\0';
+}
+
+void PlaneTrackCommonOperation::initExecution()
+{
+       MovieTracking *tracking;
+       MovieTrackingObject *object;
+
+       memset(this->m_corners, 0, sizeof(this->m_corners));
+       memset(this->m_frameSpaceCorners, 0, sizeof(this->m_frameSpaceCorners));
+
+       if (!this->m_movieClip)
+               return;
+
+       tracking = &this->m_movieClip->tracking;
+
+       object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName);
+       if (object) {
+               MovieTrackingPlaneTrack *plane_track;
+
+               plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName);
+
+               if (plane_track) {
+                       MovieTrackingPlaneMarker *plane_marker;
+                       int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber);
+
+                       plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+                       memcpy(this->m_corners, plane_marker->corners, sizeof(this->m_corners));
+               }
+       }
+
+       for (int i = 0; i < 4; i++) {
+               this->m_frameSpaceCorners[i][0] = this->m_corners[i][0] * this->getWidth();
+               this->m_frameSpaceCorners[i][1] = this->m_corners[i][1] * this->getHeight();
+       }
+}
+
+void PlaneTrackCommonOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
+{
+       NodeOperation::determineResolution(resolution, preferredResolution);
+
+       resolution[0] = 0;
+       resolution[1] = 0;
+
+       if (this->m_movieClip) {
+               int width, height;
+               MovieClipUser user = {0};
+
+               BKE_movieclip_user_set_frame(&user, this->m_framenumber);
+               BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height);
+
+               resolution[0] = width;
+               resolution[1] = height;
+       }
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h
new file mode 100644 (file)
index 0000000..705bdf4
--- /dev/null
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackCommonOperation_h
+#define _COM_PlaneTrackCommonOperation_h
+
+#include <string.h>
+
+#include "COM_NodeOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackCommonOperation : public NodeOperation {
+protected:
+       MovieClip *m_movieClip;
+       int m_framenumber;
+       char m_trackingObjectName[64];
+       char m_planeTrackName[64];
+
+       float m_corners[4][2];            /* Corners coordinates in normalized space. */
+       float m_frameSpaceCorners[4][2];  /* Corners coordinates in pixel space. */
+
+       /**
+        * Determine the output resolution. The resolution is retrieved from the Renderer
+        */
+       void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]);
+
+public:
+       PlaneTrackCommonOperation();
+
+       void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;}
+       void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); }
+       void setPlaneTrackName(char *plane_track) { BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); }
+       void setFramenumber(int framenumber) {this->m_framenumber = framenumber;}
+
+       void initExecution();
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp
new file mode 100644 (file)
index 0000000..fe794cb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackMaskOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BLI_jitter.h"
+
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+PlaneTrackMaskOperation::PlaneTrackMaskOperation() : PlaneTrackCommonOperation()
+{
+       this->addOutputSocket(COM_DT_VALUE);
+}
+
+void PlaneTrackMaskOperation::initExecution()
+{
+       PlaneTrackCommonOperation::initExecution();
+
+       const int osa = 8;
+       this->m_osa = osa;
+       BLI_jitter_init(this->m_jitter[0], osa);
+}
+
+void PlaneTrackMaskOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float point[2];
+
+       int inside_counter = 0;
+       for (int sample = 0; sample < this->m_osa; sample++) {
+               point[0] = x + this->m_jitter[sample][0];
+               point[1] = y + this->m_jitter[sample][1];
+
+               if (isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) ||
+                   isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3]))
+               {
+                       inside_counter++;
+               }
+       }
+
+       output[0] = (float) inside_counter / this->m_osa;
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h
new file mode 100644 (file)
index 0000000..db32f98
--- /dev/null
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackMaskOperation_h
+#define _COM_PlaneTrackMaskOperation_h
+
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackMaskOperation : public PlaneTrackCommonOperation {
+protected:
+       int m_osa;
+       float m_jitter[32][2];
+
+public:
+       PlaneTrackMaskOperation();
+
+       void initExecution();
+
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
new file mode 100644 (file)
index 0000000..9bbf456
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#include "COM_PlaneTrackWarpImageOperation.h"
+#include "COM_ReadBufferOperation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+
+extern "C" {
+       #include "BLI_jitter.h"
+
+       #include "BKE_movieclip.h"
+       #include "BKE_node.h"
+       #include "BKE_tracking.h"
+}
+
+BLI_INLINE bool isPointInsideQuad(const float x, const float y, const float corners[4][2])
+{
+       float point[2];
+
+       point[0] = x;
+       point[1] = y;
+
+       return isect_point_tri_v2(point, corners[0], corners[1], corners[2]) ||
+              isect_point_tri_v2(point, corners[0], corners[2], corners[3]);
+}
+
+BLI_INLINE bool resolveUV(const float x, const float y, const float corners[4][2], float uv[2])
+{
+       float point[2];
+       bool inside;
+
+       inside = isPointInsideQuad(x, y, corners);
+
+       point[0] = x;
+       point[1] = y;
+
+       /* Use reverse bilinear to get UV coordinates within original frame */
+       resolve_quad_uv(uv, point, corners[0], corners[1], corners[2], corners[3]);
+
+       return inside;
+}
+
+BLI_INLINE void resolveUVAndDxDy(const float x, const float y, const float corners[4][2],
+                                 float *u_r, float *v_r, float *dx_r, float *dy_r)
+{
+       float inputUV[2];
+       float uv_a[2], uv_b[2];
+
+       float dx, dy;
+       float uv_l, uv_r;
+       float uv_u, uv_d;
+
+       bool ok1, ok2;
+
+       resolveUV(x, y, corners, inputUV);
+
+       /* adaptive sampling, red (U) channel */
+       ok1 = resolveUV(x - 1, y, corners, uv_a);
+       ok2 = resolveUV(x + 1, y, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.0f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.0f;
+
+       dx = 0.5f * (uv_l + uv_r);
+
+       /* adaptive sampling, green (V) channel */
+       ok1 = resolveUV(x, y - 1, corners, uv_a);
+       ok2 = resolveUV(x, y + 1, corners, uv_b);
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dy = 0.5f * (uv_u + uv_d);
+
+       /* more adaptive sampling, red and green (UV) channels */
+       ok1 = resolveUV(x - 1, y - 1, corners, uv_a);
+       ok2 = resolveUV(x - 1, y + 1, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dx += 0.25f * (uv_l + uv_r);
+       dy += 0.25f * (uv_u + uv_d);
+
+       ok1 = resolveUV(x + 1, y - 1, corners, uv_a);
+       ok2 = resolveUV(x + 1, y + 1, corners, uv_b);
+       uv_l = ok1 ? fabsf(inputUV[0] - uv_a[0]) : 0.f;
+       uv_r = ok2 ? fabsf(inputUV[0] - uv_b[0]) : 0.f;
+       uv_u = ok1 ? fabsf(inputUV[1] - uv_a[1]) : 0.f;
+       uv_d = ok2 ? fabsf(inputUV[1] - uv_b[1]) : 0.f;
+
+       dx += 0.25f * (uv_l + uv_r);
+       dy += 0.25f * (uv_u + uv_d);
+
+       /* should use mipmap */
+       *dx_r = min(dx, 0.2f);
+       *dy_r = min(dy, 0.2f);
+
+       *u_r = inputUV[0];
+       *v_r = inputUV[1];
+}
+
+PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation()
+{
+       this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
+       this->addOutputSocket(COM_DT_COLOR);
+       this->m_pixelReader = NULL;
+       this->setComplex(true);
+}
+
+void PlaneTrackWarpImageOperation::initExecution()
+{
+       PlaneTrackCommonOperation::initExecution();
+
+       this->m_pixelReader = this->getInputSocketReader(0);
+
+       const int osa = 8;
+       this->m_osa = osa;
+       BLI_jitter_init(this->m_jitter[0], osa);
+}
+
+void PlaneTrackWarpImageOperation::deinitExecution()
+{
+       this->m_pixelReader = NULL;
+}
+
+void PlaneTrackWarpImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
+{
+       float color_accum[4];
+
+       zero_v4(color_accum);
+       for (int sample = 0; sample < this->m_osa; sample++) {
+               float current_x = x + this->m_jitter[sample][0],
+                     current_y = y + this->m_jitter[sample][1];
+               if (isPointInsideQuad(current_x, current_y, this->m_frameSpaceCorners)) {
+                       float current_color[4];
+                       float u, v, dx, dy;
+
+                       resolveUVAndDxDy(current_x, current_y, this->m_frameSpaceCorners, &u, &v, &dx, &dy);
+
+                       u *= this->m_pixelReader->getWidth();
+                       v *= this->m_pixelReader->getHeight();
+
+                       this->m_pixelReader->read(current_color, u, v, dx, dy, COM_PS_BICUBIC);
+                       premul_to_straight_v4(current_color);
+                       add_v4_v4(color_accum, current_color);
+               }
+       }
+
+       mul_v4_v4fl(output, color_accum, 1.0f / this->m_osa);
+       straight_to_premul_v4(output);
+}
+
+bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+       float frame_space_corners[4][2];
+
+       for (int i = 0; i < 4; i++) {
+               frame_space_corners[i][0] = this->m_corners[i][0] * this->getWidth();
+               frame_space_corners[i][1] = this->m_corners[i][1] * this->getHeight();
+       }
+
+       float UVs[4][2];
+
+       /* TODO(sergey): figure out proper way to do this. */
+       resolveUV(input->xmin - 2, input->ymin - 2, frame_space_corners, UVs[0]);
+       resolveUV(input->xmax + 2, input->ymin - 2, frame_space_corners, UVs[1]);
+       resolveUV(input->xmax + 2, input->ymax + 2, frame_space_corners, UVs[2]);
+       resolveUV(input->xmin - 2, input->ymax + 2, frame_space_corners, UVs[3]);
+
+       float min[2], max[2];
+       INIT_MINMAX2(min, max);
+       for (int i = 0; i < 4; i++) {
+               minmax_v2v2_v2(min, max, UVs[i]);
+       }
+
+       rcti newInput;
+
+       newInput.xmin = min[0] * readOperation->getWidth() - 1;
+       newInput.ymin = min[1] * readOperation->getHeight() - 1;
+       newInput.xmax = max[0] * readOperation->getWidth() + 1;
+       newInput.ymax = max[1] * readOperation->getHeight() + 1;
+
+       return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
new file mode 100644 (file)
index 0000000..a92ff3f
--- /dev/null
@@ -0,0 +1,53 @@
+
+/*
+ * Copyright 2013, Blender Foundation.
+ *
+ * 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:
+ *             Sergey Sharybin
+ */
+
+#ifndef _COM_PlaneTrackWarpImageOperation_h
+#define _COM_PlaneTrackWarpImageOperation_h
+
+#include <string.h>
+
+#include "COM_PlaneTrackCommonOperation.h"
+
+#include "DNA_movieclip_types.h"
+#include "DNA_tracking_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+class PlaneTrackWarpImageOperation : public PlaneTrackCommonOperation {
+protected:
+       SocketReader *m_pixelReader;
+       int m_osa;
+       float m_jitter[32][2];
+
+public:
+       PlaneTrackWarpImageOperation();
+
+       void initExecution();
+       void deinitExecution();
+
+       void executePixel(float output[4], float x, float y, PixelSampler sampler);
+
+       bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+};
+
+#endif
index 423613fb78093d6eb094f9f9ecc312c113621a6b..81308dd84f211efdcff00589b39ea2dbfff8e17f 100644 (file)
@@ -90,16 +90,14 @@ enum TfmMode {
 
 /* TRANSFORM CONTEXTS */
 #define CTX_NONE            0
-#define CTX_TEXTURE         1
-#define CTX_EDGE            2
-#define CTX_NO_PET          4
-#define CTX_TWEAK           8
-#define CTX_NO_MIRROR       16
-#define CTX_AUTOCONFIRM     32
-#define CTX_BMESH           64
-#define CTX_NDOF            128
-#define CTX_MOVIECLIP       256
-#define CTX_MASK            512
+#define CTX_TEXTURE         (1 << 0)
+#define CTX_EDGE            (1 << 1)
+#define CTX_NO_PET          (1 << 2)
+#define CTX_NO_MIRROR       (1 << 3)
+#define CTX_AUTOCONFIRM     (1 << 4)
+#define CTX_NDOF            (1 << 5)
+#define CTX_MOVIECLIP       (1 << 6)
+#define CTX_MASK            (1 << 7)
 
 /* Standalone call to get the transformation center corresponding to the current situation
  * returns 1 if successful, 0 otherwise (usually means there's no selection)
index 2a1bdee32f77dc59cbb53e84f6dab5e8910062d0..6ced2423074c0f51b44d9092c7ad03fbffbb2af4 100644 (file)
@@ -102,32 +102,53 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
        MaskLayer *masklay;
 
        /* parent info */
-       SpaceClip *sc;
-       MovieClip *clip;
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTracking *tracking;
        MovieTrackingTrack *track;
-       MovieTrackingMarker *marker;
+       MovieTrackingPlaneTrack *plane_track;
        MovieTrackingObject *tracking_object;
        /* done */
 
-       int framenr;
+       int framenr, parent_type;
+       float parmask_pos[2], orig_corners[4][2];
+       char *sub_parent_name;
 
-       float marker_pos_ofs[2];
-       float parmask_pos[2];
-
-       if ((NULL == (sc = CTX_wm_space_clip(C))) ||
-           (NULL == (clip = sc->clip)) ||
-           (NULL == (track = clip->tracking.act_track)) ||
-           (NULL == (tracking_object = BKE_tracking_object_get_active(&clip->tracking))))
-       {
+       if (ELEM(NULL, sc, clip)) {
                return OPERATOR_CANCELLED;
        }
 
        framenr = ED_space_clip_get_clip_frame_number(sc);
-       marker = BKE_tracking_marker_get(track, framenr);
 
-       add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+       tracking = &clip->tracking;
+       tracking_object = BKE_tracking_object_get_active(&clip->tracking);
+
+       if (tracking_object == NULL) {
+               return OPERATOR_CANCELLED;
+       }
+
+       if ((track = BKE_tracking_track_get_active(tracking)) != NULL) {
+               MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
+               float marker_pos_ofs[2];
+
+               add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
 
-       BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+               BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs);
+
+               sub_parent_name = track->name;
+               parent_type = MASK_PARENT_POINT_TRACK;
+       }
+       else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) {
+               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+               zero_v2(parmask_pos);
+               sub_parent_name = plane_track->name;
+               parent_type = MASK_PARENT_PLANE_TRACK;
+               memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners));
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
 
        for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
                MaskSpline *spline;
@@ -144,10 +165,12 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
                                if (MASKPOINT_ISSEL_ANY(point)) {
                                        point->parent.id_type = ID_MC;
                                        point->parent.id = &clip->id;
+                                       point->parent.type = parent_type;
                                        BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent));
-                                       BLI_strncpy(point->parent.sub_parent, track->name, sizeof(point->parent.sub_parent));
+                                       BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent));
 
                                        copy_v2_v2(point->parent.parent_orig, parmask_pos);
+                                       memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig));
                                }
                        }
                }
index 93bdca930962b5dc9974bd746c07364e53d2c159..d5fbdca5b0aadde226f37185e3ea09148e795156 100644 (file)
@@ -38,6 +38,7 @@
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_mask.h"
+#include "BKE_report.h"
 
 #include "DNA_object_types.h"
 #include "DNA_mask_types.h"
index 59fe2a6705784c73d2638ef3f3129fc6d937a8c9..1360a180b2d02a136a962486fb94f6c69888dac2 100644 (file)
@@ -952,6 +952,8 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *eve
                return OPERATOR_CANCELLED;
        }
 
+       BM_select_history_validate(bm);
+
        return OPERATOR_FINISHED;
 }
 
index 4610bb89ae4670b1b320ed4f20406070fc81fc89..38ce56b4bc7a6f7bbf6cbd9c3fbe06dbb0f7bf9e 100644 (file)
@@ -2399,7 +2399,7 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
        RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
 }
 
-static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
 {
        Base *base_new;
        Object *obedit = base_old->object;
@@ -2441,7 +2441,7 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh
        BM_mesh_free(bm_new);
        ((Mesh *)base_new->object->data)->edit_btmesh = NULL;
        
-       return true;
+       return base_new;
 }
 
 static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
@@ -2452,7 +2452,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
        /* sel -> tag */
        BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, BM_ELEM_SELECT);
 
-       return mesh_separate_tagged(bmain, scene, base_old, bm_old);
+       return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
 }
 
 /* flush a hflag to from verts to edges/faces */
@@ -2492,6 +2492,63 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag)
        }
 }
 
+/**
+ * Sets an object to a single material. from one of its slots.
+ *
+ * \note This could be used for split-by-material for non mesh types.
+ * \note This could take material data from another object or args.
+ */
+static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr)
+{
+       ID *obdata = ob->data;
+
+       Material ***matarar;
+       short *totcolp;
+
+       totcolp = give_totcolp_id(obdata);
+       matarar = give_matarar_id(obdata);
+
+       if ((totcolp && matarar) == 0) {
+               BLI_assert(0);
+               return;
+       }
+
+       if (*totcolp) {
+               Material *ma_ob;
+               Material *ma_obdata;
+               char matbit;
+
+               if (mat_nr < ob->totcol) {
+                       ma_ob = ob->mat[mat_nr];
+                       matbit = ob->matbits[mat_nr];
+               }
+               else {
+                       ma_ob = NULL;
+                       matbit = 0;
+               }
+
+               if (mat_nr < *totcolp) {
+                        ma_obdata = (*matarar)[mat_nr];
+               }
+               else {
+                       ma_obdata = NULL;
+               }
+
+               BKE_material_clear_id(obdata, true);
+               BKE_material_resize_object(ob, 1, true);
+               BKE_material_resize_id(obdata, 1, true);
+
+               ob->mat[0] = ma_ob;
+               ob->matbits[0] = matbit;
+               (*matarar)[0] = ma_obdata;
+       }
+       else {
+               BKE_material_clear_id(obdata, true);
+               BKE_material_resize_object(ob, 0, true);
+               BKE_material_resize_id(obdata, 0, true);
+       }
+}
+
 static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
 {
        BMFace *f_cmp, *f;
@@ -2499,6 +2556,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
        bool result = false;
 
        while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
+               Base *base_new;
                const short mat_nr = f_cmp->mat_nr;
                int tot = 0;
 
@@ -2522,11 +2580,22 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
 
                /* leave the current object with some materials */
                if (tot == bm_old->totface) {
+                       mesh_separate_material_assign_mat_nr(base_old->object, mat_nr);
+
+                       /* since we're in editmode, must set faces here */
+                       BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
+                               f->mat_nr = 0;
+                       }
                        break;
                }
 
                /* Move selection into a separate object */
-               result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               if (base_new) {
+                       mesh_separate_material_assign_mat_nr(base_new->object, mat_nr);
+               }
+
+               result |= (base_new != NULL);
        }
 
        return result;
@@ -2585,7 +2654,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
                bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
 
                /* Move selection into a separate object */
-               result |= mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
        }
 
        return result;
index d1fd50939748f0a50b6d9cb6906a39fcaa32e2de..eb58bdc7696c4162f85b73ae21ce06618cd7bb97 100644 (file)
@@ -111,6 +111,57 @@ static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int wid
        }
 }
 
+static int generic_track_get_markersnr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track)
+{
+       if (track) {
+               return track->markersnr;
+       }
+       else if (plane_track) {
+               return plane_track->markersnr;
+       }
+
+       return 0;
+}
+
+static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                            int marker_index)
+{
+       if (track) {
+               return track->markers[marker_index].framenr;
+       }
+       else if (plane_track) {
+               return plane_track->markers[marker_index].framenr;
+       }
+
+       return 0;
+}
+
+static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                            int marker_index)
+{
+       if (track) {
+               return (track->markers[marker_index].flag & MARKER_DISABLED) == 0;
+       }
+       else if (plane_track) {
+               return true;
+       }
+
+       return false;
+}
+
+static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTrackingPlaneTrack *plane_track,
+                                              int marker_index)
+{
+       if (track) {
+               return (track->markers[marker_index].flag & MARKER_TRACKED) == 0;
+       }
+       else if (plane_track) {
+               return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0;
+       }
+
+       return false;
+}
+
 static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene)
 {
        float x;
@@ -119,6 +170,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
+       MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
        MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking);
 
        glEnable(GL_BLEND);
@@ -143,34 +195,29 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
        }
 
        /* track */
-       if (act_track) {
-               MovieTrackingTrack *track = act_track;
-
+       if (act_track || act_plane_track) {
                for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
                        int framenr;
-                       MovieTrackingMarker *marker;
+                       int markersnr = generic_track_get_markersnr(act_track, act_plane_track);
 
-                       while (a < track->markersnr) {
-                               if (track->markers[a].framenr >= i)
+                       while (a < markersnr) {
+                               int marker_framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
+
+                               if (marker_framenr >= i)
                                        break;
 
-                               if (a < track->markersnr - 1 && track->markers[a + 1].framenr > i)
+                               if (a < markersnr - 1 && generic_track_get_marker_framenr(act_track, act_plane_track, a + 1) > i)
                                        break;
 
                                a++;
                        }
 
-                       if (a < track->markersnr)
-                               marker = &track->markers[a];
-                       else
-                               marker = &track->markers[track->markersnr - 1];
-
-                       if ((marker->flag & MARKER_DISABLED) == 0) {
-                               framenr = marker->framenr;
+                       if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
+                               framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
 
                                if (framenr != i)
                                        glColor4ub(128, 128, 0, 96);
-                               else if ((marker->flag & MARKER_TRACKED) == 0)
+                               else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
                                        glColor4ub(255, 255, 0, 196);
                                else
                                        glColor4ub(255, 255, 0, 96);
@@ -961,13 +1008,159 @@ static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx
        *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask);
 }
 
+static void plane_track_colors(bool is_active, float color[3], float selected_color[3])
+{
+       UI_GetThemeColor3fv(TH_MARKER, color);
+
+       if (is_active)
+               UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
+       else
+               UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
+}
+
+static void getArrowEndPoint(const int width, const int height, const float zoom,
+                             const float start_corner[2], const float end_corner[2],
+                             float end_point[2])
+{
+       float direction[2];
+       float max_length;
+
+       sub_v2_v2v2(direction, end_corner, start_corner);
+
+       direction[0] *= width;
+       direction[1] *= height;
+       max_length = len_v2(direction);
+       normalize_v2(direction);
+       mul_v2_fl(direction, min_ff(32.0f / zoom, max_length));
+       direction[0] /= width;
+       direction[1] /= height;
+
+       add_v2_v2v2(end_point, start_corner, direction);
+}
+
+static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                                 MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+                                 bool draw_outline, int width, int height)
+{
+       bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0;
+       bool is_selected_track = plane_track->flag & SELECT;
+       float px[2];
+
+       if (draw_outline) {
+               UI_ThemeColor(TH_MARKER_OUTLINE);
+       }
+       else {
+               float color[3], selected_color[3];
+               plane_track_colors(is_active_track, color, selected_color);
+               if (is_selected_track) {
+                       glColor3fv(selected_color);
+               }
+               else {
+                       glColor3fv(color);
+               }
+       }
+
+       px[0] = 1.0f / width / sc->zoom;
+       px[1] = 1.0f / height / sc->zoom;
+
+       if (draw_outline) {
+               if (!tiny) {
+                       glLineWidth(3.0f);
+               }
+       }
+       else if (tiny) {
+               glLineStipple(3, 0xaaaa);
+               glEnable(GL_LINE_STIPPLE);
+               glEnable(GL_COLOR_LOGIC_OP);
+               glLogicOp(GL_NOR);
+       }
+
+       /* Draw rectangle itself. */
+       glBegin(GL_LINE_LOOP);
+       glVertex2fv(plane_marker->corners[0]);
+       glVertex2fv(plane_marker->corners[1]);
+       glVertex2fv(plane_marker->corners[2]);
+       glVertex2fv(plane_marker->corners[3]);
+       glEnd();
+
+       /* Draw axis. */
+       if (!draw_outline) {
+               float end_point[2];
+               glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+
+               getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+               glColor3f(1.0, 0.0, 0.0f);
+               glBegin(GL_LINES);
+               glVertex2fv(plane_marker->corners[0]);
+               glVertex2fv(end_point);
+               glEnd();
+
+               getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+               glColor3f(0.0, 1.0, 0.0f);
+               glBegin(GL_LINES);
+               glVertex2fv(plane_marker->corners[0]);
+               glVertex2fv(end_point);
+               glEnd();
+
+               glPopAttrib();
+       }
+
+       /* Draw sliders. */
+       if (is_selected_track) {
+               int i;
+               for (i = 0; i < 4; i++) {
+                       draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
+                                                3.0f * px[0], 3.0f * px[1], draw_outline, px);
+               }
+       }
+
+       if (draw_outline) {
+               if (!tiny) {
+                       glLineWidth(1.0f);
+               }
+       }
+       else if (tiny) {
+               glDisable(GL_COLOR_LOGIC_OP);
+               glDisable(GL_LINE_STIPPLE);
+               glLineStipple(3, 0xaaaa);
+               glEnable(GL_LINE_STIPPLE);
+       }
+}
+
+static void draw_plane_marker_outline(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                                      MovieTrackingPlaneMarker *plane_marker, int width, int height)
+{
+       draw_plane_marker_ex(sc, plane_track, plane_marker, false, true, width, height);
+}
+
+static void draw_plane_marker(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                              MovieTrackingPlaneMarker *plane_marker, bool is_active_track,
+                              int width, int height)
+{
+       draw_plane_marker_ex(sc, plane_track, plane_marker, is_active_track, false, width, height);
+}
+
+static void draw_plane_track(SpaceClip *sc, MovieTrackingPlaneTrack *plane_track,
+                             int framenr, bool is_active_track, int width, int height)
+{
+       MovieTrackingPlaneMarker *plane_marker;
+
+       plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+
+       draw_plane_marker_outline(sc, plane_track, plane_marker, width, height);
+       draw_plane_marker(sc, plane_track, plane_marker, is_active_track, width, height);
+}
+
+/* Draw all kind of tracks. */
 static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                                  int width, int height, float zoomx, float zoomy)
 {
        float x, y;
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track, *act_track;
+       MovieTrackingPlaneTrack *plane_track, *active_plane_track;
        MovieTrackingMarker *marker;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
@@ -1160,6 +1353,15 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                glDisable(GL_POINT_SMOOTH);
        }
 
+       /* Draw plane tracks */
+       active_plane_track = BKE_tracking_plane_track_get_active(tracking);
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               draw_plane_track(sc, plane_track, framenr, plane_track == active_plane_track, width, height);
+       }
+
        glPopMatrix();
 
        if (sc->flag & SC_SHOW_NAMES) {
index edc6ac1ecf73ebbc807d3d1db2c3ec5f37a06f66..cdb0fdadebd9ea5f90b99c1b191914b5084847e5 100644 (file)
@@ -466,11 +466,10 @@ static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
 
        if (act_track)
-               clip_delete_track(C, clip, tracksbase, act_track);
+               clip_delete_track(C, clip, act_track);
 
        return OPERATOR_FINISHED;
 }
@@ -498,7 +497,6 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
 
        if (act_track) {
@@ -508,7 +506,7 @@ static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
                        MovieTrackingMarker *marker = &act_track->markers[a];
 
                        if (marker->flag & MARKER_GRAPH_SEL)
-                               clip_delete_marker(C, clip, tracksbase, act_track, marker);
+                               clip_delete_marker(C, clip, act_track, marker);
                        else
                                a++;
                }
index 51cb83eecad6f8d7fc632c7d5bd49063a9f48152..8d112b7413c432180e893c005e3d6f3243f0b6df 100644 (file)
@@ -132,8 +132,8 @@ void clip_graph_tracking_values_iterate(struct SpaceClip *sc, int selected_only,
 void clip_graph_tracking_iterate(struct SpaceClip *sc, int selected_only, int include_hidden, void *userdata,
                                  void (*func)(void *userdata, struct MovieTrackingMarker *marker));
 
-void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track);
-void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct ListBase *tracksbase, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
+void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track);
+void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
 
 void clip_view_center_to_point(SpaceClip *sc, float x, float y);
 
@@ -193,6 +193,9 @@ void CLIP_OT_tracking_object_remove(struct wmOperatorType *ot);
 void CLIP_OT_copy_tracks(struct wmOperatorType *ot);
 void CLIP_OT_paste_tracks(struct wmOperatorType *ot);
 
+void CLIP_OT_create_plane_track(struct wmOperatorType *ot);
+void CLIP_OT_slide_plane_marker(struct wmOperatorType *ot);
+
 /* tracking_select.c */
 void CLIP_OT_select(struct wmOperatorType *ot);
 void CLIP_OT_select_all(struct wmOperatorType *ot);
index d7a9b1c0cb6fd4ea32533e5cd15dbe858c19174b..72a3cb98a6a1ffa8205d34ff6b6b4ca0aa9896a8 100644 (file)
@@ -175,11 +175,14 @@ void clip_graph_tracking_iterate(SpaceClip *sc, int selected_only, int include_h
        }
 }
 
-void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, MovieTrackingTrack *track)
+void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
 {
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingStabilization *stab = &tracking->stabilization;
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
+       MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+       ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
 
        int has_bundle = FALSE, update_stab = FALSE;
 
@@ -196,6 +199,51 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
        if (track->flag & TRACK_HAS_BUNDLE)
                has_bundle = TRUE;
 
+       /* Make sure no plane will use freed track */
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = next_plane_track)
+       {
+               bool found  = false;
+               int i;
+
+               next_plane_track = plane_track->next;
+
+               for (i = 0; i < plane_track->point_tracksnr; i++) {
+                       if (plane_track->point_tracks[i] == track) {
+                               found = true;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       continue;
+               }
+
+               if (plane_track->point_tracksnr > 4) {
+                       int track_index;
+                       MovieTrackingTrack **new_point_tracks;
+
+                       new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr,
+                                                      "new point tracks array");
+
+                       for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
+                               if (plane_track->point_tracks[i] != track) {
+                                       new_point_tracks[track_index++] = plane_track->point_tracks[i];
+                               }
+                       }
+
+                       MEM_freeN(plane_track->point_tracks);
+                       plane_track->point_tracks = new_point_tracks;
+                       plane_track->point_tracksnr--;
+               }
+               else {
+                       /* Delete planes with less than 3 point tracks in it. */
+                       BKE_tracking_plane_track_free(plane_track);
+                       BLI_freelinkN(plane_tracks_base, plane_track);
+               }
+       }
+
        BKE_tracking_track_free(track);
        BLI_freelinkN(tracksbase, track);
 
@@ -212,11 +260,11 @@ void clip_delete_track(bContext *C, MovieClip *clip, ListBase *tracksbase, Movie
                WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 }
 
-void clip_delete_marker(bContext *C, MovieClip *clip, ListBase *tracksbase,
-                        MovieTrackingTrack *track, MovieTrackingMarker *marker)
+void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
+                        MovieTrackingMarker *marker)
 {
        if (track->markersnr == 1) {
-               clip_delete_track(C, clip, tracksbase, track);
+               clip_delete_track(C, clip, track);
        }
        else {
                BKE_tracking_marker_delete(track, marker->framenr);
index 562a8584560517f76c13071bf720579baabd99d5..8213853c9374b337a77419eb097d26401d05de56 100644 (file)
@@ -517,6 +517,10 @@ static void clip_operatortypes(void)
        WM_operatortype_append(CLIP_OT_copy_tracks);
        WM_operatortype_append(CLIP_OT_paste_tracks);
 
+       /* Plane tracker */
+       WM_operatortype_append(CLIP_OT_create_plane_track);
+       WM_operatortype_append(CLIP_OT_slide_plane_marker);
+
        /* ** clip_graph_ops.c  ** */
 
        /* graph editing */
@@ -685,6 +689,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf)
 
        WM_keymap_add_item(keymap, "CLIP_OT_hide_tracks_clear", HKEY, KM_PRESS, KM_ALT, 0);
 
+       /* plane tracks */
+       WM_keymap_add_item(keymap, "CLIP_OT_slide_plane_marker", LEFTMOUSE, KM_PRESS, 0, 0);
+
        /* clean-up */
        WM_keymap_add_item(keymap, "CLIP_OT_join_tracks", JKEY, KM_PRESS, KM_CTRL, 0);
 
index f3d070452a5f8bd77418bb949c87f8a518731e00..e14fc8ad399b4ff4fc9d3f463243771771fb0cb1 100644 (file)
@@ -34,6 +34,7 @@
 #include "DNA_camera_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_movieclip_types.h"
 #include "DNA_object_types.h"   /* SELECT */
 #include "DNA_scene_types.h"
@@ -55,6 +56,8 @@
 #include "BKE_report.h"
 #include "BKE_scene.h"
 #include "BKE_library.h"
+#include "BKE_mask.h"
+#include "BKE_node.h"
 #include "BKE_sound.h"
 
 #include "WM_api.h"
@@ -88,6 +91,7 @@ static bool add_marker(const bContext *C, float x, float y)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track;
        int width, height;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -101,8 +105,10 @@ static bool add_marker(const bContext *C, float x, float y)
        track = BKE_tracking_track_add(tracking, tracksbase, x, y, framenr, width, height);
 
        BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, 0);
+       BKE_tracking_plane_tracks_deselect_all(plane_tracks_base);
 
        clip->tracking.act_track = track;
+       clip->tracking.act_plane_track = NULL;
 
        return true;
 }
@@ -234,13 +240,31 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *track = tracksbase->first, *next;
+       MovieTrackingPlaneTrack *plane_track, *next_plane_track;
+       bool modified = false;
+
+       /* Delete selected plane tracks. */
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = next_plane_track)
+       {
+               next_plane_track = plane_track->next;
+
+               if (plane_track->flag & SELECT) {
+                       BKE_tracking_plane_track_free(plane_track);
+                       BLI_freelinkN(plane_tracks_base, plane_track);
+                       modified = true;
+               }
+       }
 
+       /* Remove selected point tracks (they'll also be removed from planes which uses them). */
        while (track) {
                next = track->next;
 
                if (TRACK_VIEW_SELECTED(sc, track))
-                       clip_delete_track(C, clip, tracksbase, track);
+                       clip_delete_track(C, clip, track);
 
                track = next;
        }
@@ -248,6 +272,10 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
        /* nothing selected now, unlock view so it can be scrolled nice again */
        sc->flag &= ~SC_LOCK_SELECTION;
 
+       if (modified) {
+               WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+       }
+
        return OPERATOR_FINISHED;
 }
 
@@ -274,7 +302,9 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
        MovieTrackingTrack *track = tracksbase->first, *next;
+       MovieTrackingPlaneTrack *plane_track, *plane_track_next;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int has_selection = 0;
 
@@ -287,13 +317,34 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op))
                        if (marker) {
                                has_selection |= track->markersnr > 1;
 
-                               clip_delete_marker(C, clip, tracksbase, track, marker);
+                               clip_delete_marker(C, clip, track, marker);
                        }
                }
 
                track = next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track_next)
+       {
+               plane_track_next = plane_track->next;
+
+               if (plane_track->flag & SELECT) {
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, framenr);
+
+                       if (plane_marker) {
+                               if (plane_track->markersnr == 1) {
+                                       BKE_tracking_plane_track_free(plane_track);
+                                       BLI_freelinkN(plane_tracks_base, plane_track);
+                               }
+                               else {
+                                       BKE_tracking_plane_marker_delete(plane_track, framenr);
+                               }
+                       }
+               }
+       }
+
        if (!has_selection) {
                /* nothing selected now, unlock view so it can be scrolled nice again */
                sc->flag &= ~SC_LOCK_SELECTION;
@@ -727,6 +778,7 @@ static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event
                MovieTracking *tracking = &clip->tracking;
 
                tracking->act_track = slidedata->track;
+               tracking->act_plane_track = NULL;
 
                op->customdata = slidedata;
 
@@ -3670,3 +3722,350 @@ void CLIP_OT_paste_tracks(wmOperatorType *ot)
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
+
+/********************** Create plane track operator *********************/
+
+static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTracking *tracking = &clip->tracking;
+       MovieTrackingPlaneTrack *plane_track;
+       ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       plane_track = BKE_tracking_plane_track_add(tracking, plane_tracks_base, tracks_base, framenr);
+
+       if (plane_track == NULL) {
+               BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
+               return OPERATOR_CANCELLED;
+       }
+       else {
+               BKE_tracking_tracks_deselect_all(tracks_base);
+
+               plane_track->flag |= SELECT;
+               clip->tracking.act_track = NULL;
+               clip->tracking.act_plane_track = plane_track;
+
+               /* Copute homoraphies and apply them on marker's corner, so we've got
+                * quite nice motion from the very beginning.
+                */
+               BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+       }
+
+       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+       return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_create_plane_track(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Create Plane Track";
+       ot->description = "Create new plane track out of selected point tracks";
+       ot->idname = "CLIP_OT_create_plane_track";
+
+       /* api callbacks */
+       ot->exec = create_plane_track_tracks_exec;
+       ot->poll = ED_space_clip_tracking_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Slide plane marker corner operator *********************/
+
+typedef struct SlidePlaneMarkerData {
+       MovieTrackingPlaneTrack *plane_track;
+       MovieTrackingPlaneMarker *plane_marker;
+       int width, height;
+       int corner_index;
+       float *corner;
+       int previous_mval[2];
+       float previous_corner[2];
+       float old_corner[2];
+       bool accurate;
+} SlidePlaneMarkerData;
+
+static bool mouse_on_plane_slide_zone(SpaceClip *sc, float co[2], float slide_zone[2], int width, int height)
+{
+       const float size = 12.0f;
+       float dx, dy;
+
+       dx = size / width / sc->zoom;
+       dy = size / height / sc->zoom;
+
+       return IN_RANGE_INCL(co[0], slide_zone[0] - dx, slide_zone[0] + dx) &&
+              IN_RANGE_INCL(co[1], slide_zone[1] - dy, slide_zone[1] + dy);
+}
+
+static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C, const wmEvent *event, int *corner_r)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       ARegion *ar = CTX_wm_region(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       MovieTrackingPlaneTrack *plane_track;
+       int width, height;
+       float co[2];
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       ED_space_clip_get_size(sc, &width, &height);
+
+       if (width == 0 || height == 0) {
+               return NULL;
+       }
+
+       ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
+                       bool ok = false;
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (mouse_on_plane_slide_zone(sc, co, plane_marker->corners[i], width, height)) {
+                                       if (corner_r) {
+                                               *corner_r = i;
+                                       }
+                                       ok = true;
+                                       break;
+                               }
+                       }
+
+                       if (ok) {
+                               return plane_track;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+static void *slide_plane_marker_customdata(bContext *C, const wmEvent *event)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       ARegion *ar = CTX_wm_region(C);
+       MovieTrackingPlaneTrack *plane_track;
+       int width, height;
+       float co[2];
+       SlidePlaneMarkerData *customdata = NULL;
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+       int corner;
+
+       ED_space_clip_get_size(sc, &width, &height);
+
+       if (width == 0 || height == 0) {
+               return NULL;
+       }
+
+       ED_clip_mouse_pos(sc, ar, event->mval, co);
+
+       plane_track = tracking_plane_marker_check_slide(C, event, &corner);
+       if (plane_track) {
+               MovieTrackingPlaneMarker *plane_marker;
+
+               customdata = MEM_callocN(sizeof(SlidePlaneMarkerData), "slide plane marker data");
+
+               plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+
+               customdata->plane_track = plane_track;
+               customdata->plane_marker = plane_marker;
+               customdata->width = width;
+               customdata->height = height;
+
+               customdata->previous_mval[0] = event->mval[0];
+               customdata->previous_mval[1] = event->mval[1];
+
+               customdata->corner_index = corner;
+               customdata->corner = plane_marker->corners[corner];
+
+               copy_v2_v2(customdata->previous_corner, customdata->corner);
+               copy_v2_v2(customdata->old_corner, customdata->corner);
+       }
+
+       return customdata;
+}
+
+static int slide_plane_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       SlidePlaneMarkerData *slidedata = slide_plane_marker_customdata(C, event);
+
+       if (slidedata) {
+               SpaceClip *sc = CTX_wm_space_clip(C);
+               MovieClip *clip = ED_space_clip_get_clip(sc);
+               MovieTracking *tracking = &clip->tracking;
+
+               tracking->act_plane_track = slidedata->plane_track;
+               tracking->act_track = NULL;
+
+               op->customdata = slidedata;
+
+               hide_cursor(C);
+               WM_event_add_modal_handler(C, op);
+
+               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
+
+               return OPERATOR_RUNNING_MODAL;
+       }
+
+       return OPERATOR_PASS_THROUGH;
+}
+
+static void cancel_mouse_slide_plane_marker(SlidePlaneMarkerData *data)
+{
+       copy_v2_v2(data->corner, data->old_corner);
+}
+
+static void free_slide_plane_marker_data(SlidePlaneMarkerData *data)
+{
+       MEM_freeN(data);
+}
+
+static void slide_plane_marker_update_homographies(SpaceClip *sc, SlidePlaneMarkerData *data)
+{
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       BKE_tracking_track_plane_from_existing_motion(data->plane_track, framenr);
+}
+
+static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       SpaceClip *sc = CTX_wm_space_clip(C);
+       MovieClip *clip = ED_space_clip_get_clip(sc);
+       SlidePlaneMarkerData *data = (SlidePlaneMarkerData *) op->customdata;
+       float dx, dy, mdelta[2];
+       int next_corner_index, prev_corner_index, diag_corner_index;
+       float *next_corner, *prev_corner, *diag_corner;
+       float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2];
+
+       switch (event->type) {
+               case LEFTCTRLKEY:
+               case RIGHTCTRLKEY:
+               case LEFTSHIFTKEY:
+               case RIGHTSHIFTKEY:
+                       if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
+                               data->accurate = event->val == KM_PRESS;
+
+                       /* fall-through */
+               case MOUSEMOVE:
+                       mdelta[0] = event->mval[0] - data->previous_mval[0];
+                       mdelta[1] = event->mval[1] - data->previous_mval[1];
+
+                       dx = mdelta[0] / data->width / sc->zoom;
+                       dy = mdelta[1] / data->height / sc->zoom;
+
+                       if (data->accurate) {
+                               dx /= 5.0f;
+                               dy /= 5.0f;
+                       }
+
+                       data->corner[0] = data->previous_corner[0] + dx;
+                       data->corner[1] = data->previous_corner[1] + dy;
+
+
+                       /*
+                                                      prev_edge
+                           (Corner 3, current) <-----------------------   (Corner 2, previous)
+                                   |                                              ^
+                                   |                                              |
+                                   |                                              |
+                                   |                                              |
+                         next_edge |                                              | next_diag_edge
+                                   |                                              |
+                                   |                                              |
+                                   |                                              |
+                                   v                                              |
+                            (Corner 0, next)   ----------------------->   (Corner 1, diagonal)
+                                                     prev_diag_edge
+                        */
+
+                       next_corner_index = (data->corner_index + 1) % 4;
+                       prev_corner_index = (data->corner_index + 3) % 4;
+                       diag_corner_index = (data->corner_index + 2) % 4;
+
+                       next_corner = data->plane_marker->corners[next_corner_index];
+                       prev_corner = data->plane_marker->corners[prev_corner_index];
+                       diag_corner = data->plane_marker->corners[diag_corner_index];
+
+                       sub_v2_v2v2(next_edge, next_corner, data->corner);
+                       sub_v2_v2v2(prev_edge, data->corner, prev_corner);
+                       sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
+                       sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);
+
+                       if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner);
+                       }
+
+                       if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner);
+                       }
+
+                       if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
+                               closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner);
+                       }
+
+                       data->previous_mval[0] = event->mval[0];
+                       data->previous_mval[1] = event->mval[1];
+                       copy_v2_v2(data->previous_corner, data->corner);
+
+                       DAG_id_tag_update(&sc->clip->id, 0);
+
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
+
+                       break;
+
+               case LEFTMOUSE:
+                       if (event->val == KM_RELEASE) {
+                               /* Marker is now keyframed. */
+                               data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+                               slide_plane_marker_update_homographies(sc, data);
+
+                               free_slide_plane_marker_data(op->customdata);
+
+                               show_cursor(C);
+
+                               DAG_id_tag_update(&sc->clip->id, 0);
+                               WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+                               return OPERATOR_FINISHED;
+                       }
+
+                       break;
+
+               case ESCKEY:
+                       cancel_mouse_slide_plane_marker(op->customdata);
+
+                       free_slide_plane_marker_data(op->customdata);
+
+                       show_cursor(C);
+
+                       WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
+
+                       return OPERATOR_CANCELLED;
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void CLIP_OT_slide_plane_marker(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Slide Plane Marker";
+       ot->description = "Slide plane marker areas";
+       ot->idname = "CLIP_OT_slide_plane_marker";
+
+       /* api callbacks */
+       ot->poll = ED_space_clip_tracking_poll;
+       ot->invoke = slide_plane_marker_invoke;
+       ot->modal = slide_plane_marker_modal;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING;
+}
index b03209173d8b9135fac0beb75910feff2819f34e..6e4d10173fb2af20b78a90e5e9f3213142b65081 100644 (file)
@@ -169,6 +169,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2])
        return sqrtf(min_ffff(d1, d2, d3, d4));
 }
 
+/* Distance to quad defined by it's corners, corners are relative to pos */
 static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
 {
        float d1, d2, d3, d4;
@@ -184,7 +185,22 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2])
        return sqrtf(min_ffff(d1, d2, d3, d4));
 }
 
-static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2])
+/* Same as above, but all the coordinates are absolute */
+static float dist_to_crns_abs(float co[2], float corners[4][2])
+{
+       float d1, d2, d3, d4;
+       float *v1 = corners[0], *v2 = corners[1];
+       float *v3 = corners[2], *v4 = corners[3];
+
+       d1 = dist_squared_to_line_segment_v2(co, v1, v2);
+       d2 = dist_squared_to_line_segment_v2(co, v2, v3);
+       d3 = dist_squared_to_line_segment_v2(co, v3, v4);
+       d4 = dist_squared_to_line_segment_v2(co, v4, v1);
+
+       return sqrtf(min_ffff(d1, d2, d3, d4));
+}
+
+static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, float co[2], float *distance_r)
 {
        MovieTrackingTrack *track = NULL, *cur;
        float mindist = 0.0f;
@@ -221,19 +237,88 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbas
                cur = cur->next;
        }
 
+       *distance_r = mindist;
+
        return track;
 }
 
+static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, ListBase *plane_tracks_base,
+                                                         float co[2], float *distance_r)
+{
+       MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track;
+       float min_distance = 0.0f;
+       int framenr = ED_space_clip_get_clip_frame_number(sc);
+
+       for (current_plane_track = plane_tracks_base->first;
+            current_plane_track;
+            current_plane_track = current_plane_track->next)
+       {
+               MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(current_plane_track, framenr);
+
+               if ((current_plane_track->flag & TRACK_HIDDEN) == 0) {
+                       float distance = dist_to_crns_abs(co, plane_marker->corners);
+                       if (plane_track == NULL || distance < min_distance) {
+                               plane_track = current_plane_track;
+                               min_distance = distance;
+                       }
+               }
+       }
+
+       *distance_r = min_distance;
+
+       return plane_track;
+}
+
+static void delect_all_tracks(ListBase *tracks_base)
+{
+       MovieTrackingTrack *track;
+       for (track = tracks_base->first;
+            track;
+            track = track->next)
+       {
+               BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
+       }
+}
+
+static void delect_all_plane_tracks(ListBase *plane_tracks_base)
+{
+       MovieTrackingPlaneTrack *plane_track;
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               plane_track->flag &= ~SELECT;
+       }
+}
+
 static int mouse_select(bContext *C, float co[2], int extend)
 {
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
-       MovieTrackingTrack *track = NULL;   /* selected marker */
+       MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
+       float distance_to_track, distance_to_plane_track;
+
+       track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
+       plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);
+
+       /* Between track and plane we choose closest to the mouse for selection here. */
+       if (track && plane_track) {
+               if (distance_to_track < distance_to_plane_track) {
+                       plane_track = NULL;
+               }
+               else {
+                       track = NULL;
+               }
+       }
 
-       track = find_nearest_track(sc, tracksbase, co);
+       if (!extend) {
+               delect_all_plane_tracks(plane_tracks_base);
+       }
 
        if (track) {
                int area = track_mouse_area(C, co, track);
@@ -242,10 +327,13 @@ static int mouse_select(bContext *C, float co[2], int extend)
                        area = TRACK_AREA_ALL;
 
                if (extend && TRACK_AREA_SELECTED(track, area)) {
-                       if (track == act_track)
+                       if (track == act_track) {
                                BKE_tracking_track_deselect(track, area);
-                       else
+                       }
+                       else {
                                clip->tracking.act_track = track;
+                               clip->tracking.act_plane_track = NULL;
+                       }
                }
                else {
                        if (area == TRACK_AREA_POINT)
@@ -253,7 +341,25 @@ static int mouse_select(bContext *C, float co[2], int extend)
 
                        BKE_tracking_track_select(tracksbase, track, area, extend);
                        clip->tracking.act_track = track;
+                       clip->tracking.act_plane_track = NULL;
+               }
+       }
+       else if (plane_track) {
+               if (!extend) {
+                       delect_all_tracks(tracksbase);
+               }
+
+               if (plane_track->flag & SELECT) {
+                       if (extend) {
+                               plane_track->flag &= ~SELECT;
+                       }
+               }
+               else {
+                       plane_track->flag |= SELECT;
                }
+
+               clip->tracking.act_track = NULL;
+               clip->tracking.act_plane_track = plane_track;
        }
 
        if (!extend) {
@@ -350,7 +456,9 @@ static int border_select_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        rcti rect;
        rctf rectf;
        int change = FALSE, mode, extend;
@@ -389,6 +497,33 @@ static int border_select_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
+                                       if (mode == GESTURE_MODAL_SELECT) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                               else if (!extend) {
+                                       plane_track->flag &= ~SELECT;
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -430,7 +565,9 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        rcti rect;
        int change = FALSE;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -466,6 +603,37 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               float screen_co[2];
+
+                               /* marker in screen coords */
+                               ED_clip_point_stable_pos__reverse(sc, ar, plane_marker->corners[i], screen_co);
+
+                               if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
+                                   BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
+                               {
+                                       if (select) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -518,17 +686,22 @@ void CLIP_OT_select_lasso(wmOperatorType *ot)
 
 /********************** circle select operator *********************/
 
-static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+static int point_inside_ellipse(float point[2], float offset[2], float ellipse[2])
 {
        /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */
        float x, y;
 
-       x = (marker->pos[0] - offset[0]) * ellipse[0];
-       y = (marker->pos[1] - offset[1]) * ellipse[1];
+       x = (point[0] - offset[0]) * ellipse[0];
+       y = (point[1] - offset[1]) * ellipse[1];
 
        return x * x + y * y < 1.0f;
 }
 
+static int marker_inside_ellipse(MovieTrackingMarker *marker, float offset[2], float ellipse[2])
+{
+       return point_inside_ellipse(marker->pos, offset, ellipse);
+}
+
 static int circle_select_exec(bContext *C, wmOperator *op)
 {
        SpaceClip *sc = CTX_wm_space_clip(C);
@@ -537,7 +710,9 @@ static int circle_select_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        int x, y, radius, width, height, mode, change = FALSE;
        float zoomx, zoomy, offset[2], ellipse[2];
        int framenr = ED_space_clip_get_clip_frame_number(sc);
@@ -577,6 +752,30 @@ static int circle_select_exec(bContext *C, wmOperator *op)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       MovieTrackingPlaneMarker *plane_marker =
+                               BKE_tracking_plane_marker_get(plane_track, framenr);
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
+                                       if (mode == GESTURE_MODAL_SELECT) {
+                                               plane_track->flag |= SELECT;
+                                       }
+                                       else {
+                                               plane_track->flag &= ~SELECT;
+                                       }
+                               }
+                       }
+
+                       change = TRUE;
+               }
+       }
+
        if (change) {
                BKE_tracking_dopesheet_tag_update(tracking);
 
@@ -619,16 +818,18 @@ static int select_all_exec(bContext *C, wmOperator *op)
        MovieClip *clip = ED_space_clip_get_clip(sc);
        MovieTracking *tracking = &clip->tracking;
        MovieTrackingTrack *track = NULL;   /* selected track */
+       MovieTrackingPlaneTrack *plane_track = NULL;   /* selected plane track */
        MovieTrackingMarker *marker;
        ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
        int action = RNA_enum_get(op->ptr, "action");
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        int has_selection = FALSE;
 
        if (action == SEL_TOGGLE) {
                action = SEL_SELECT;
-               track = tracksbase->first;
-               while (track) {
+
+               for (track = tracksbase->first; track; track = track->next) {
                        if (TRACK_VIEW_SELECTED(sc, track)) {
                                marker = BKE_tracking_marker_get(track, framenr);
 
@@ -637,13 +838,20 @@ static int select_all_exec(bContext *C, wmOperator *op)
                                        break;
                                }
                        }
+               }
 
-                       track = track->next;
+               for (plane_track = plane_tracks_base->first;
+                    plane_track;
+                    plane_track = plane_track->next)
+               {
+                       if (plane_track->flag & SELECT) {
+                               action = SEL_DESELECT;
+                               break;
+                       }
                }
        }
 
-       track = tracksbase->first;
-       while (track) {
+       for (track = tracksbase->first; track; track = track->next) {
                if ((track->flag & TRACK_HIDDEN) == 0) {
                        marker = BKE_tracking_marker_get(track, framenr);
 
@@ -670,8 +878,29 @@ static int select_all_exec(bContext *C, wmOperator *op)
 
                if (TRACK_VIEW_SELECTED(sc, track))
                        has_selection = TRUE;
+       }
 
-               track = track->next;
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
+                       switch (action) {
+                               case SEL_SELECT:
+                                       plane_track->flag |= SELECT;
+                                       break;
+                               case SEL_DESELECT:
+                                       plane_track->flag &= ~SELECT;
+                                       break;
+                               case SEL_INVERT:
+                                       plane_track->flag ^= SELECT;
+                                       break;
+                       }
+               }
+
+               if (plane_track->flag & SELECT) {
+                       has_selection = TRUE;
+               }
        }
 
        if (!has_selection)
index d6f644ab330c9009e261a470ea0addb81c27dde0..0efc7b927a95b3684827dd496334b65e6aee7379 100644 (file)
@@ -115,6 +115,7 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat
                /* create list item */
                but = uiDefIconTextButS(block, LISTROW, 0, icon, dir, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, nr, 0, i, 0, 0, entry);
                uiButSetFunc(but, file_panel_cb, entry, NULL);
+               uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */
                uiButSetFlag(but, UI_ICON_LEFT | UI_TEXT_LEFT);
 
                /* create delete button */
index 2957edd941b4a967207b26f55fff58666ae495a8..aed5699a9d7940e3be308dde471f93efa22f2b29 100644 (file)
@@ -1465,6 +1465,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
        row = uiLayoutRow(layout, FALSE);
        uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
        uiItemR(row, ptr, "layer_weight", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "blend_mode", 0, "", ICON_NONE);
 
        uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
 
index cf3c0454e6b0103ad61e65918241fceecae5ba06..5cc22b25f72e7613fbd1fcb84f16614a7241fc4a 100644 (file)
@@ -2225,6 +2225,39 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
        }
 }
 
+static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       bNode *node = ptr->data;
+
+       uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
+
+       if (node->id) {
+               MovieClip *clip = (MovieClip *) node->id;
+               MovieTracking *tracking = &clip->tracking;
+               MovieTrackingObject *object;
+               uiLayout *col;
+               PointerRNA tracking_ptr;
+               NodeTrackPosData *data = node->storage;
+
+               RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
+
+               col = uiLayoutColumn(layout, FALSE);
+               uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
+
+               object = BKE_tracking_object_get_named(tracking, data->tracking_object);
+               if (object) {
+                       PointerRNA object_ptr;
+
+                       RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
+
+                       uiItemPointerR(col, ptr, "plane_track_name", &object_ptr, "plane_tracks", "", ICON_ANIM_DATA);
+               }
+               else {
+                       uiItemR(layout, ptr, "plane_track_name", 0, "", ICON_ANIM_DATA);
+               }
+       }
+}
+
 /* only once called */
 static void node_composit_set_butfunc(bNodeType *ntype)
 {
@@ -2444,6 +2477,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_TRACKPOS:
                        ntype->uifunc = node_composit_buts_trackpos;
                        break;
+               case CMP_NODE_PLANETRACKDEFORM:
+                       ntype->uifunc = node_composit_buts_planetrackdeform;
+                       break;
        }
 }
 
index a014724af4a0d5aa37abb5ffec18f7ed029b04a1..1e9b681197c1785897b63f882bf64a91c517ed0f 100644 (file)
@@ -1648,26 +1648,29 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
 }
 
+static int outliner_parenting_poll(bContext *C)
+{
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+
+       if (soops) {
+               return ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS);
+       }
+
+       return FALSE;
+}
+
 static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 {
        Main *bmain = CTX_data_main(C);
-       Scene *scene = NULL;
        Object *ob = NULL;
        SpaceOops *soops = CTX_wm_space_outliner(C);
-       TreeElement *te;
        char obname[MAX_ID_NAME];
 
        RNA_string_get(op->ptr, "dragged_obj", obname);
        ob = (Object *)BKE_libblock_find_name(ID_OB, obname);
 
        /* search forwards to find the object */
-       te = outliner_find_id(soops, &soops->tree, (ID *)ob);
-       /* then search backwards to get the scene */
-       scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
-
-       if (scene == NULL) {
-               return OPERATOR_CANCELLED;
-       }
+       outliner_find_id(soops, &soops->tree, (ID *)ob);
 
        ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type"));
 
@@ -1687,7 +1690,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot)
        /* api callbacks */
        ot->invoke = parent_clear_invoke;
 
-       ot->poll = ED_operator_outliner_active;
+       ot->poll = outliner_parenting_poll;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
index 00476cd467d1752c90a22562015f2be810ee0f11..874852ee320749b4e5e66c963c5e6381b0a11761 100644 (file)
@@ -144,6 +144,10 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
 
        UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
 
+       if (!ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS)) {
+               return FALSE;
+       }
+
        if (drag->type == WM_DRAG_ID) {
                ID *id = (ID *)drag->poin;
                if (GS(id->name) == ID_OB) {
index ed466186d6323b5b6408a33f91a48f0f06dd1d07..6d801b866851856ab6ddb8a20c211a2ae993a395 100644 (file)
@@ -1324,12 +1324,6 @@ int transformEvent(TransInfo *t, const wmEvent *event)
                                        t->redraw |= TREDRAW_HARD;
                                }
                                break;
-//             case LEFTMOUSE:
-//             case RIGHTMOUSE:
-//                     if (WM_modal_tweak_exit(event, t->event_type))
-////                   if (t->options & CTX_TWEAK)
-//                             t->state = TRANS_CONFIRM;
-//                     break;
                        case LEFTALTKEY:
                        case RIGHTALTKEY:
                                if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) {
@@ -1374,7 +1368,7 @@ int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int c
        t->state = TRANS_RUNNING;
 
        /* avoid calculating PET */
-       t->options = CTX_NONE | CTX_NO_PET;
+       t->options = CTX_NO_PET;
 
        t->mode = TFM_DUMMY;
 
@@ -3011,7 +3005,12 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3])
                copy_v3_v3(center, td->center);
        }
        else if (t->options & CTX_MOVIECLIP) {
-               copy_v3_v3(center, td->center);
+               if (td->flag & TD_INDIVIDUAL_SCALE) {
+                       copy_v3_v3(center, td->center);
+               }
+               else {
+                       copy_v3_v3(center, t->center);
+               }
        }
        else {
                copy_v3_v3(center, t->center);
index 4a1c4203a4370d2c606c9e79102340a7fd0c9162..4954f8619349669a5f068a61bd636ac9d3c4cad3 100644 (file)
@@ -455,7 +455,7 @@ typedef struct TransInfo {
 #define        TD_USEQUAT                      (1 << 3)
 #define TD_NOTCONNECTED                (1 << 4)
 #define TD_SINGLESIZE          (1 << 5)        /* used for scaling of MetaElem->rad */
-/*#define TD_TIMEONLY                  (1 << 8) */ /*UNUSED*/
+#define TD_INDIVIDUAL_SCALE    (1 << 8) /* Scale relative to individual element center */
 #define TD_NOCENTER                    (1 << 9)
 #define TD_NO_EXT                      (1 << 10)       /* ext abused for particle key timing */
 #define TD_SKIP                                (1 << 11)       /* don't transform this data */
index cb2cb801b5022d1e5944006515dd682ad3fd4faf..01605003d7b40c492806f827253f5a65ab10ee38 100644 (file)
@@ -5959,7 +5959,8 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
 
 enum transDataTracking_Mode {
        transDataTracking_ModeTracks = 0,
-       transDataTracking_ModeCurves = 1
+       transDataTracking_ModeCurves = 1,
+       transDataTracking_ModePlaneTracks = 2,
 };
 
 typedef struct TransDataTracking {
@@ -5978,6 +5979,9 @@ typedef struct TransDataTracking {
        /* marker transformation from curves editor */
        float *prev_pos, scale;
        short coord;
+
+       MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
 } TransDataTracking;
 
 static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
@@ -6008,6 +6012,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
 
        tdt->markersnr = track->markersnr;
        tdt->markers = track->markers;
+       tdt->track = track;
 
        if (rel) {
                if (!anchor) {
@@ -6026,6 +6031,7 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra
        copy_v3_v3(td->iloc, td->loc);
 
        //copy_v3_v3(td->center, td->loc);
+       td->flag |= TD_INDIVIDUAL_SCALE;
        td->center[0] = marker->pos[0] * aspx;
        td->center[1] = marker->pos[1] * aspy;
 
@@ -6076,6 +6082,52 @@ static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d
        }
 }
 
+static void planeMarkerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
+                                       MovieTrackingPlaneTrack *plane_track, float corner[2],
+                                       float aspx, float aspy)
+{
+       tdt->mode = transDataTracking_ModePlaneTracks;
+       tdt->plane_track = plane_track;
+
+       td2d->loc[0] = corner[0] * aspx; /* hold original location */
+       td2d->loc[1] = corner[1] * aspy;
+
+       td2d->loc2d = corner; /* current location */
+       td2d->loc[2] = 0.0f;
+
+       td->flag = 0;
+       td->loc = td2d->loc;
+       copy_v3_v3(td->iloc, td->loc);
+       copy_v3_v3(td->center, td->loc);
+
+       memset(td->axismtx, 0, sizeof(td->axismtx));
+       td->axismtx[2][2] = 1.0f;
+
+       td->ext = NULL;
+       td->val = NULL;
+
+       td->flag |= TD_SELECTED;
+       td->dist = 0.0;
+
+       unit_m3(td->mtx);
+       unit_m3(td->smtx);
+}
+
+static void planeTrackToTransData(const int framenr, TransData *td, TransData2D *td2d,
+                                  TransDataTracking *tdt, MovieTrackingPlaneTrack *plane_track,
+                                  float aspx, float aspy)
+{
+       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr);
+       int i;
+
+       tdt->flag = plane_marker->flag;
+       plane_marker->flag &= ~PLANE_MARKER_TRACKED;
+
+       for (i = 0; i < 4; i++) {
+               planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspx, aspy);
+       }
+}
+
 static void transDataTrackingFree(TransInfo *t)
 {
        TransDataTracking *tdt = t->customData;
@@ -6096,7 +6148,9 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
        SpaceClip *sc = CTX_wm_space_clip(C);
        MovieClip *clip = ED_space_clip_get_clip(sc);
        ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+       ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
        MovieTrackingTrack *track;
+       MovieTrackingPlaneTrack *plane_track;
        TransDataTracking *tdt;
        int framenr = ED_space_clip_get_clip_frame_number(sc);
        float aspx, aspy;
@@ -6122,6 +6176,15 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
                track = track->next;
        }
 
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       t->total += 4;
+               }
+       }
+
        if (t->total == 0)
                return;
 
@@ -6165,11 +6228,23 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
 
                track = track->next;
        }
+
+       for (plane_track = plane_tracks_base->first;
+            plane_track;
+            plane_track = plane_track->next)
+       {
+               if (plane_track->flag & SELECT) {
+                       planeTrackToTransData(framenr, td, td2d, tdt, plane_track, aspx, aspy);
+                       td += 4;
+                       td2d += 4;
+                       tdt += 4;
+               }
+       }
 }
 
 static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDataTracking *tdt,
-                                       MovieTrackingMarker *marker, MovieTrackingMarker *prev_marker,
-                                       short coord, float size)
+                                       MovieTrackingTrack *track, MovieTrackingMarker *marker,
+                                       MovieTrackingMarker *prev_marker, short coord, float size)
 {
        float frames_delta = (marker->framenr - prev_marker->framenr);
 
@@ -6180,6 +6255,7 @@ static void markerToTransCurveDataInit(TransData *td, TransData2D *td2d, TransDa
        tdt->coord = coord;
        tdt->scale = 1.0f / size * frames_delta;
        tdt->prev_pos = prev_marker->pos;
+       tdt->track = track;
 
        /* calculate values depending on marker's speed */
        td2d->loc[0] = marker->framenr;
@@ -6265,14 +6341,14 @@ static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
                                        continue;
 
                                if (marker->flag & MARKER_GRAPH_SEL_X) {
-                                       markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 0, width);
+                                       markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
                                        td += 1;
                                        td2d += 1;
                                        tdt += 1;
                                }
 
                                if (marker->flag & MARKER_GRAPH_SEL_Y) {
-                                       markerToTransCurveDataInit(td, td2d, tdt, marker, &track->markers[i - 1], 1, height);
+                                       markerToTransCurveDataInit(td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
 
                                        td += 1;
                                        td2d += 1;
@@ -6313,57 +6389,54 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
 
 static void cancelTransTracking(TransInfo *t)
 {
-       TransDataTracking *tdt = t->customData;
        SpaceClip *sc = t->sa->spacedata.first;
-       MovieClip *clip = ED_space_clip_get_clip(sc);
-       ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
-       MovieTrackingTrack *track;
-       MovieTrackingMarker *marker;
-       int a, framenr = ED_space_clip_get_clip_frame_number(sc);
+       int i, framenr = ED_space_clip_get_clip_frame_number(sc);
 
-       if (tdt->mode == transDataTracking_ModeTracks) {
-               track = tracksbase->first;
-               while (track) {
-                       if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
-                               marker = BKE_tracking_marker_get(track, framenr);
-                               marker->flag = tdt->flag;
+       i = 0;
+       while (i < t->total) {
+               TransDataTracking *tdt = (TransDataTracking *) t->customData + i;
 
-                               tdt++;
+               if (tdt->mode == transDataTracking_ModeTracks) {
+                       MovieTrackingTrack *track = tdt->track;
+                       MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
 
-                               if (track->flag & SELECT)
-                                       tdt++;
+                       marker->flag = tdt->flag;
 
-                               if (track->pat_flag & SELECT)
-                                       tdt += 2;
+                       if (track->flag & SELECT)
+                               i++;
 
-                               if (track->search_flag & SELECT)
-                                       tdt += 2;
-                       }
+                       if (track->pat_flag & SELECT)
+                               i += 4;
 
-                       track = track->next;
+                       if (track->search_flag & SELECT)
+                               i += 2;
                }
-       }
-       else if (tdt->mode == transDataTracking_ModeCurves) {
-               MovieTrackingMarker *prev_marker;
+               else if (tdt->mode == transDataTracking_ModeCurves) {
+                       MovieTrackingTrack *track = tdt->track;
+                       MovieTrackingMarker *marker, *prev_marker;
+                       int a;
 
-               track = tracksbase->first;
-               while (track) {
-                       if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
-                               for (a = 1; a < track->markersnr; a++) {
-                                       marker = &track->markers[a];
-                                       prev_marker = &track->markers[a - 1];
+                       for (a = 1; a < track->markersnr; a++) {
+                               marker = &track->markers[a];
+                               prev_marker = &track->markers[a - 1];
 
-                                       if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
-                                               continue;
+                               if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED))
+                                       continue;
 
-                                       if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
-                                               marker->flag = tdt->flag;
-                                       }
+                               if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
+                                       marker->flag = tdt->flag;
                                }
                        }
+               }
+               else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+                       MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
+                       MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr);
 
-                       track = track->next;
+                       plane_marker->flag = tdt->flag;
+                       i += 3;
                }
+
+               i++;
        }
 }
 
@@ -6432,6 +6505,10 @@ void flushTransTracking(TransInfo *t)
                else if (tdt->mode == transDataTracking_ModeCurves) {
                        td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
                }
+               else if (tdt->mode == transDataTracking_ModePlaneTracks) {
+                       td2d->loc2d[0] = td2d->loc[0] / aspx;
+                       td2d->loc2d[1] = td2d->loc[1] / aspy;
+               }
        }
 }
 
@@ -6668,10 +6745,6 @@ void createTransData(bContext *C, TransInfo *t)
                        sort_trans_data_dist(t);
                }
        }
-       else if (t->options == CTX_BMESH) {
-               // TRANSFORM_FIX_ME
-               //createTransBMeshVerts(t, G.editBMesh->bm, G.editBMesh->td);
-       }
        else if (t->spacetype == SPACE_IMAGE) {
                t->flag |= T_POINTS | T_2D_EDIT;
                if (t->options & CTX_MASK) {
index cb0a053003630c8e06294f0996b60097d7685fb1..4c7ac4193b36b0930ce4eb04fa993ae73bc96705 100644 (file)
@@ -659,7 +659,9 @@ static void recalcData_spaceclip(TransInfo *t)
        if (ED_space_clip_check_show_trackedit(sc)) {
                MovieClip *clip = ED_space_clip_get_clip(sc);
                ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
+               ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
                MovieTrackingTrack *track;
+               MovieTrackingPlaneTrack *plane_track;
                int framenr = ED_space_clip_get_clip_frame_number(sc);
 
                flushTransTracking(t);
@@ -690,6 +692,15 @@ static void recalcData_spaceclip(TransInfo *t)
                        track = track->next;
                }
 
+               for (plane_track = plane_tracks_base->first;
+                    plane_track;
+                    plane_track = plane_track->next)
+               {
+                       if (plane_track->flag & SELECT) {
+                               BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
+                       }
+               }
+
                DAG_id_tag_update(&clip->id, 0);
        }
        else if (t->options & CTX_MASK) {
index 1495ba1b1a5319c7b433da05cac032b833c24e4b..f4e2ff43fc51bc2bed7ea63e589afb6d7e413254 100644 (file)
@@ -59,7 +59,7 @@ typedef struct bActionActuator {
        short   layer;          /* Animation layer */
        short   end_reset;      /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
        short   strideaxis;     /* Displacement axis */
-       short   pad;
+       short   blend_mode;             /* Layer blending mode */
        float   stridelength;   /* Displacement incurred by cycle */ // not in use
        float   layer_weight;   /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */
 } bActionActuator;
@@ -341,6 +341,10 @@ typedef struct bActuator {
 #define ACT_ACTION_FROM_PROP   6
 #define ACT_ACTION_MOTION              7
 
+/* actionactuator->blend_mode */
+#define ACT_ACTION_BLEND               0
+#define ACT_ACTION_ADD                 1
+
 /* ipoactuator->type */
 #define ACT_IPO_PLAY           0
 #define ACT_IPO_PINGPONG       1
index 1b6b802f2de9d3c34b0a284bb095f54f50d97e00..1b1c912d179730bd7067278d88562a081887a434 100644 (file)
@@ -58,15 +58,18 @@ typedef struct Mask {
 
 typedef struct MaskParent {
        // int flag;             /* parenting flags */ /* not used */
-       int pad;
        int id_type;          /* type of parenting */
+       int type;             /* type of parenting */
        ID *id;               /* ID block of entity to which mask/spline is parented to
                               * in case of parenting to movie tracking data set to MovieClip datablock */
        char parent[64];      /* entity of parent to which parenting happened
                               * in case of parenting to movie tracking data contains name of layer */
        char sub_parent[64];  /* sub-entity of parent to which parenting happened
                               * in case of parenting to movie tracking data contains name of track */
-       float parent_orig[2]; /* track location at the moment of parenting */
+       float parent_orig[2]; /* track location at the moment of parenting,
+                                stored in mask space*/
+
+       float parent_corners_orig[4][2]; /* Original corners of plane track at the moment of parenting */
 } MaskParent;
 
 typedef struct MaskSplinePointUW {
@@ -141,6 +144,12 @@ typedef struct MaskLayer {
 /* MaskParent->flag */
 /* #define MASK_PARENT_ACTIVE  (1 << 0) */ /* UNUSED */
 
+/* MaskParent->type */
+enum {
+       MASK_PARENT_POINT_TRACK = 0, /* parenting happens to point track */
+       MASK_PARENT_PLANE_TRACK = 1, /* parenting happens to plane track */
+};
+
 /* MaskSpline->flag */
 /* reserve (1 << 0) for SELECT */
 enum {
index 9ff4392242eabf2663dcc9a261b2363c2f5edfcc..109cdf5f1a107d402fc956c29c828ff8397aa9d7 100644 (file)
@@ -827,6 +827,10 @@ typedef struct NodeTranslateData {
        char pad[6];
 } NodeTranslateData;
 
+typedef struct NodePlaneTrackDeformData {
+       char tracking_object[64];
+       char plane_track_name[64];
+} NodePlaneTrackDeformData;
 
 typedef struct NodeShaderScript {
        int mode;
index 04cd69bc5aeef9a4a096d83c36e10e4df4a112c7..f81ac4dab0642e473ffbc66d48b27344a54ceba5 100644 (file)
@@ -144,6 +144,44 @@ typedef struct MovieTrackingTrack {
        struct bGPdata *gpd;        /* grease-pencil data */
 } MovieTrackingTrack;
 
+typedef struct MovieTrackingPlaneMarker {
+       /* Corners of the plane in the following order:
+        *
+        *       Y
+        *       ^
+        *       | (3) --- (2)
+        *       |  |       |
+        *       |  |       |
+        *       |  |       |
+        *       | (0) --- (1)
+        *       +-------------> X
+        *
+        * The coordinates are stored in frame normalized coordinates.
+        */
+       float corners[4][2];
+
+       int framenr;    /* Number of frame plane marker is associated with */
+       int flag;       /* Marker's flag (alive, ...) */
+} MovieTrackingPlaneMarker;
+
+typedef struct MovieTrackingPlaneTrack {
+       struct MovieTrackingPlaneTrack *next, *prev;
+
+       char name[64];  /* MAX_NAME */
+
+       MovieTrackingTrack **point_tracks;  /* Array of point tracks used to define this plane.
+                                              Each element is a pointer to MovieTrackingTrack. */
+       int point_tracksnr, pad;  /* Number of tracks in point_tracks array. */
+
+       MovieTrackingPlaneMarker *markers;   /* Markers in the plane track */
+       int markersnr;                       /* Count of markers in track (size of markers array) */
+
+       int flag;    /* flags (selection, ...) */
+
+       /* Runtime data */
+       int last_marker, pad2;               /* Most recently used marker */
+} MovieTrackingPlaneTrack;
+
 typedef struct MovieTrackingSettings {
        int flag;
 
@@ -225,6 +263,7 @@ typedef struct MovieTrackingObject {
        float scale;            /* scale of object solution in amera space */
 
        ListBase tracks;        /* list of tracks use to tracking this object */
+       ListBase plane_tracks;  /* list of plane tracks used by this object */
        MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */
 
        /* reconstruction options */
@@ -280,9 +319,11 @@ typedef struct MovieTracking {
        MovieTrackingSettings settings; /* different tracking-related settings */
        MovieTrackingCamera camera;     /* camera intrinsics */
        ListBase tracks;                /* list of tracks used for camera object */
+       ListBase plane_tracks;          /* list of plane tracks used by camera object */
        MovieTrackingReconstruction reconstruction; /* reconstruction data for camera object */
        MovieTrackingStabilization stabilization;   /* stabilization data */
-       MovieTrackingTrack *act_track;      /* active track */
+       MovieTrackingTrack *act_track;             /* active track */
+       MovieTrackingPlaneTrack *act_plane_track;  /* active plane track */
 
        ListBase objects;
        int objectnr, tot_object;       /* index of active object and total number of objects */
@@ -432,4 +473,16 @@ enum {
        TRACKING_COVERAGE_OK         = 2
 };
 
+/* MovieTrackingPlaneMarker->flag */
+enum {
+       PLANE_MARKER_DISABLED = (1 << 0),
+       PLANE_MARKER_TRACKED  = (1 << 1),
+};
+
+/* MovieTrackingPlaneTrack->flag */
+enum {
+       PLANE_TRACK_HIDDEN = (1 << 1),
+       PLANE_TRACK_LOCKED = (1 << 2),
+};
+
 #endif  /* __DNA_TRACKING_TYPES_H__ */
index 0489f85a37fc4d3cce525bf360464cc580b7ef0d..26febf217a6b5d30bef2fa86037ace18ea7eac10 100644 (file)
@@ -347,15 +347,32 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig
 
 static void rna_IDMaterials_append_id(ID *id, Material *ma)
 {
-       material_append_id(id, ma);
+       B