Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Dinges <blender@dingto.org>2013-08-16 16:50:13 +0400
committerThomas Dinges <blender@dingto.org>2013-08-16 16:50:13 +0400
commit0786eebd1194b108d71299137c715b10e100d8f5 (patch)
tree4b89a5aed5b44881a9e52c3cd982f457532d76fa
parent9591957c8aa92740985f323673ccf0b6be318d62 (diff)
parentd75e14b31e5e65d1e38b1ca4688a42a346ac9495 (diff)
Merged revision(s) 59108-59184 from trunk/blender into soc-2013-dingto.
-rw-r--r--build_files/scons/tools/Blender.py12
-rw-r--r--doc/python_api/rst/bge.logic.rst13
-rw-r--r--doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst6
-rw-r--r--extern/libmv/libmv-capi.cc26
-rw-r--r--extern/libmv/libmv-capi.h3
-rw-r--r--extern/libmv/libmv-capi_stub.cc9
-rw-r--r--extern/libmv/libmv/multiview/euclidean_resection.cc109
-rw-r--r--extern/libmv/libmv/multiview/euclidean_resection.h4
-rw-r--r--extern/libmv/libmv/tracking/track_region.cc4
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp66
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.h2
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp1
-rw-r--r--intern/audaspace/intern/AUD_IHandle.h2
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp86
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.h2
-rw-r--r--intern/audaspace/intern/AUD_Space.h3
-rw-r--r--intern/cycles/kernel/kernel_shader.h4
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h7
-rw-r--r--intern/guardedalloc/intern/mallocn.c4
-rw-r--r--release/scripts/modules/bpy_extras/image_utils.py10
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py9
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py30
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_curve.h3
-rw-r--r--source/blender/blenkernel/BKE_mask.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h9
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_tracking.h36
-rw-r--r--source/blender/blenkernel/intern/armature.c5
-rw-r--r--source/blender/blenkernel/intern/curve.c78
-rw-r--r--source/blender/blenkernel/intern/mask.c115
-rw-r--r--source/blender/blenkernel/intern/material.c141
-rw-r--r--source/blender/blenkernel/intern/mesh.c33
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/sound.c4
-rw-r--r--source/blender/blenkernel/intern/tracking.c480
-rw-r--r--source/blender/blenlib/BLI_array.h10
-rw-r--r--source/blender/blenlib/BLI_linklist.h5
-rw-r--r--source/blender/blenlib/BLI_math_base.h8
-rw-r--r--source/blender/blenlib/intern/BLI_array.c42
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c47
-rw-r--r--source/blender/blenloader/intern/readfile.c27
-rw-r--r--source/blender/blenloader/intern/writefile.c17
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c34
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c2
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c167
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c69
-rw-r--r--source/blender/compositor/CMakeLists.txt9
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp81
-rw-r--r--source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h38
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cpp64
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp95
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h62
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp69
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h49
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp207
-rw-r--r--source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h53
-rw-r--r--source/blender/editors/include/ED_transform.h18
-rw-r--r--source/blender/editors/mask/mask_relationships.c55
-rw-r--r--source/blender/editors/mask/mask_shapekey.c1
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c79
-rw-r--r--source/blender/editors/space_clip/clip_draw.c232
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c6
-rw-r--r--source/blender/editors/space_clip/clip_intern.h7
-rw-r--r--source/blender/editors/space_clip/clip_utils.c56
-rw-r--r--source/blender/editors/space_clip/space_clip.c7
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c403
-rw-r--r--source/blender/editors/space_clip/tracking_select.c257
-rw-r--r--source/blender/editors/space_file/file_panels.c1
-rw-r--r--source/blender/editors/space_logic/logic_window.c1
-rw-r--r--source/blender/editors/space_node/drawnode.c36
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c23
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c4
-rw-r--r--source/blender/editors/transform/transform.c15
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_conversions.c163
-rw-r--r--source/blender/editors/transform/transform_generics.c11
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h6
-rw-r--r--source/blender/makesdna/DNA_mask_types.h13
-rw-r--r--source/blender/makesdna/DNA_node_types.h4
-rw-r--r--source/blender/makesdna/DNA_tracking_types.h55
-rw-r--r--source/blender/makesrna/intern/rna_ID.c40
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c14
-rw-r--r--source/blender/makesrna/intern/rna_curve.c4
-rw-r--r--source/blender/makesrna/intern/rna_mask.c43
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c23
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c239
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_composite.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c64
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp7
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp25
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h2
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp1
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp11
-rw-r--r--source/gameengine/Ketsji/BL_Action.h14
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp6
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h7
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp23
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h3
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp2
112 files changed, 3977 insertions, 546 deletions
diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py
index 24bdd32ed26..ee2399500d0 100644
--- a/build_files/scons/tools/Blender.py
+++ b/build_files/scons/tools/Blender.py
@@ -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'])
diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst
index c7915ee5279..3a79d32d917 100644
--- a/doc/python_api/rst/bge.logic.rst
+++ b/doc/python_api/rst/bge.logic.rst
@@ -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
diff --git a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
index a9c91735f91..3be148556ef 100644
--- a/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
+++ b/doc/python_api/rst/bge_types/bge.types.KX_GameObject.rst
@@ -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)
diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc
index 063c63f9266..e1fd509d581 100644
--- a/extern/libmv/libmv-capi.cc
+++ b/extern/libmv/libmv-capi.cc
@@ -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
diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h
index 7c91881fe71..37aab2465ed 100644
--- a/extern/libmv/libmv-capi.h
+++ b/extern/libmv/libmv-capi.h
@@ -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
diff --git a/extern/libmv/libmv-capi_stub.cc b/extern/libmv/libmv-capi_stub.cc
index 36977eb58ba..59a3fe89398 100644
--- a/extern/libmv/libmv-capi_stub.cc
+++ b/extern/libmv/libmv-capi_stub.cc
@@ -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
diff --git a/extern/libmv/libmv/multiview/euclidean_resection.cc b/extern/libmv/libmv/multiview/euclidean_resection.cc
index 10c7330770f..d5421b9691e 100644
--- a/extern/libmv/libmv/multiview/euclidean_resection.cc
+++ b/extern/libmv/libmv/multiview/euclidean_resection.cc
@@ -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
diff --git a/extern/libmv/libmv/multiview/euclidean_resection.h b/extern/libmv/libmv/multiview/euclidean_resection.h
index 1a329702c2a..ff9bccdd5c9 100644
--- a/extern/libmv/libmv/multiview/euclidean_resection.h
+++ b/extern/libmv/libmv/multiview/euclidean_resection.h
@@ -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
};
/**
diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc
index 6e9fb95654d..349d84b3817 100644
--- a/extern/libmv/libmv/tracking/track_region.cc
+++ b/extern/libmv/libmv/tracking/track_region.cc
@@ -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();
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index 371e0007bd3..676a86e88fe 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -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();
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
index d2a4be227ba..f0e47824967 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
@@ -96,6 +96,8 @@ private:
/// Own device.
AUD_OpenALDevice* m_device;
+ bool pause(bool keep);
+
public:
/**
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
index 9beba2eb0a0..b00289b3fae 100644
--- a/intern/audaspace/Python/AUD_PyAPI.cpp
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -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);
diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h
index 9dcb743693e..c80fb4027b8 100644
--- a/intern/audaspace/intern/AUD_IHandle.h
+++ b/intern/audaspace/intern/AUD_IHandle.h
@@ -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;
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index a7e5b25664b..7bf59cd6f31 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -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();
}
}
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index 8675a5ce2b8..3c8c1e438a3 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -139,6 +139,8 @@ protected:
/// Own device.
AUD_SoftwareDevice* m_device;
+ bool pause(bool keep);
+
public:
/**
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index f42cb1ab018..ec2c06900ac 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -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).
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index d8ff662c505..5dd12f98b9c 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -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);
}
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 17d7260c191..ca5f441aa2d 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -33,14 +33,13 @@
#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();
diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c
index 08ac2ce6eff..06ae2ee864d 100644
--- a/intern/guardedalloc/intern/mallocn.c
+++ b/intern/guardedalloc/intern/mallocn.c
@@ -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;
diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py
index 551689c5a75..ff6d23badb6 100644
--- a/release/scripts/modules/bpy_extras/image_utils.py
+++ b/release/scripts/modules/bpy_extras/image_utils.py
@@ -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
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 08dfc2bf8b5..692787ce281 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -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(
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index d38f5f934b4..9f72d7a6d88 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -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():
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 5048a93d565..04584855ed3 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -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'
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 91090dc2c75..6a5dccaed88 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -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=[
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 93f9ec276aa..baa90e7a856 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 92332116ba6..14ceba42aff 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 7c47380f838..91c1715cca6 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -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 *);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 1c88a5c45dd..e582af77d61 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -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);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4e9e18d43e3..27192437c89 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -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
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 84bca0bd3ba..0d148e55753 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index eca607c08df..f006710dc21 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 26ae1b94aee..801ed4f00a5 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -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;
}
}
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index e3f30bad5cf..a7bfb15c99d 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 6dc3c6d7bc6..c23b4ac4408 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -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++;
+ }
+ }
}
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 095957b40d5..0db1f92f70f 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -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;
}
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 5001aa01653..1349c4dc8d4 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -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)
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index feff8f95fd7..2f8eb7d9931 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -60,10 +60,6 @@
#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;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 4c363292898..54ba9ea56d7 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -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)
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index ef5cb8bde04..566fc95eb4f 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -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__ */
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index 3e7fdc8bf75..9c1e1f88bab 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -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
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 4b71babdba1..69dbd3253f0 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -80,6 +80,14 @@
#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))
diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c
index 5823b7db3f1..510bf072513 100644
--- a/source/blender/blenlib/intern/BLI_array.c
+++ b/source/blender/blenlib/intern/BLI_array.c
@@ -59,9 +59,14 @@
*/
#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);
+ }
+}
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index b08fbe17a43..99fc5f27726 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -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) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1f8bbfbec88..37cebc3063d 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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);
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 4f0ccd3c626..f3d58c42bc8 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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;
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index bec301acaa9..0a6c0f4b293 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -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;
}
}
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 062de4f69e1..f23eac61278 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -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);
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 0eb3b0a6443..6eab3c625fa 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -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__);
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 4e78d1dc494..923b877b822 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -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);
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index adcf325b51c..aad600d13fa 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -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);
+ }
}
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index c1b99274bed..a119a89c842 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -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
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 80ae952b87f..db0cdd1692e 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -121,6 +121,7 @@
#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
index 00000000000..d6434c26c7d
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
@@ -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
index 00000000000..cf173cd19f9
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
@@ -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);
+};
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp
index c8e3dbf993d..89a56af6b15 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_ImageOperation.cpp
@@ -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];
}
}
diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h
index e75e7daa186..b51f11edd04 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.h
+++ b/source/blender/compositor/operations/COM_ImageOperation.h
@@ -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;
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 1c9dd0f170e..1a2a1e77833 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -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
index 00000000000..51e803f696b
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp
@@ -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
index 00000000000..705bdf4bd81
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h
@@ -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
index 00000000000..fe794cb769f
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp
@@ -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
index 00000000000..db32f9830e0
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h
@@ -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
index 00000000000..9bbf45682f2
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
@@ -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
index 00000000000..a92ff3f9ddf
--- /dev/null
+++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h
@@ -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
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 423613fb780..81308dd84f2 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -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)
diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c
index 2a1bdee32f7..6ced2423074 100644
--- a/source/blender/editors/mask/mask_relationships.c
+++ b/source/blender/editors/mask/mask_relationships.c
@@ -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));
}
}
}
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index 93bdca93096..d5fbdca5b0a 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -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"
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 59fe2a67057..1360a180b2d 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -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;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 4610bb89ae4..38ce56b4bc7 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -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;
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index d1fd5093974..eb58bdc7696 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -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) {
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
index edc6ac1ecf7..cdb0fdadebd 100644
--- a/source/blender/editors/space_clip/clip_graph_ops.c
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -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++;
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 51cb83eecad..8d112b7413c 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -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);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index d7a9b1c0cb6..72a3cb98a6a 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -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);
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 562a8584560..8213853c937 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -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);
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index f3d070452a5..e14fc8ad399 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -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;
+}
diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c
index b03209173d8..6e4d10173fb 100644
--- a/source/blender/editors/space_clip/tracking_select.c
+++ b/source/blender/editors/space_clip/tracking_select.c
@@ -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)
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index d6f644ab330..0efc7b927a9 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -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 */
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 2957edd941b..aed5699a9d7 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -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);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index cf3c0454e6b..5cc22b25f72 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -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;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index a014724af4a..1e9b681197c 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -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;
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 00476cd467d..874852ee320 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -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) {
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ed466186d63..6d801b86685 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -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);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 4a1c4203a43..4954f861934 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -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 */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index cb2cb801b50..01605003d7b 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -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) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index cb0a0530036..4c7ac4193b3 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -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) {
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 1495ba1b1a5..f4e2ff43fc5 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -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
diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h
index 1b6b802f2de..1b1c912d179 100644
--- a/source/blender/makesdna/DNA_mask_types.h
+++ b/source/blender/makesdna/DNA_mask_types.h
@@ -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 {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 9ff4392242e..109cdf5f1a1 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -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;
diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h
index 04cd69bc5ae..f81ac4dab06 100644
--- a/source/blender/makesdna/DNA_tracking_types.h
+++ b/source/blender/makesdna/DNA_tracking_types.h
@@ -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__ */
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 0489f85a37f..26febf217a6 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -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);
+ BKE_material_append_id(id, ma);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
}
-static Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot)
+static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i, int remove_material_slot)
{
- Material *ma = material_pop_id(id, index_i, remove_material_slot);
+ Material *ma;
+ short *totcol = give_totcolp_id(id);
+ const short totcol_orig = *totcol;
+ if (index_i < 0) {
+ index_i += (*totcol);
+ }
+
+ if ((index_i < 0) || (index_i >= (*totcol))) {
+ BKE_report(reports, RPT_ERROR, "Index out of range");
+ return NULL;
+ }
+
+ ma = BKE_material_pop_id(id, index_i, remove_material_slot);
+
+ if (*totcol == totcol_orig) {
+ BKE_report(reports, RPT_ERROR, "No material to removed");
+ return NULL;
+ }
DAG_id_tag_update(id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
@@ -364,6 +381,15 @@ static Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material
return ma;
}
+static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot)
+{
+ BKE_material_clear_id(id, remove_material_slot);
+
+ DAG_id_tag_update(id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
+ WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
+}
+
static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
{
Library *lib = (Library *)ptr->data;
@@ -476,12 +502,16 @@ static void rna_def_ID_materials(BlenderRNA *brna)
RNA_def_property_flag(parm, PROP_REQUIRED);
func = RNA_def_function(srna, "pop", "rna_IDMaterials_pop_id");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a material from the data block");
- parm = RNA_def_int(func, "index", 0, 0, MAXMAT, "", "Index of material to remove", 0, MAXMAT);
- RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_int(func, "index", -1, -MAXMAT, MAXMAT, "", "Index of material to remove", 0, MAXMAT);
RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove");
RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id");
+ RNA_def_function_ui_description(func, "Remove all materials from the data block");
+ RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
}
static void rna_def_ID(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 134c5bcbee4..99053714246 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -593,6 +593,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_blend_items[] = {
+ {ACT_ACTION_BLEND, "BLEND", 0, "Blend", ""},
+ {ACT_ACTION_ADD, "ADD", 0, "Add", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "ActionActuator", "Actuator");
RNA_def_struct_ui_text(srna, "Action Actuator", "Actuator to control the object movement");
RNA_def_struct_sdna_from(srna, "bActionActuator", "data");
@@ -656,7 +662,7 @@ static void rna_def_action_actuator(BlenderRNA *brna)
prop = RNA_def_property(srna, "layer_weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Layer Weight",
- "How much of the previous layer to blend into this one (0 = add mode)");
+ "How much of the previous layer to blend into this one");
RNA_def_property_update(prop, NC_LOGIC, NULL);
prop = RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE);
@@ -691,6 +697,12 @@ static void rna_def_action_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Child", "Update Action on all children Objects as well");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
+ RNA_def_property_enum_items(prop, prop_blend_items);
+ RNA_def_property_ui_text(prop, "Blend Mode", "Determines how this layer is blended with previous layers");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
prop = RNA_def_property(srna, "stride_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "stridelength");
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 21bf2ec6719..9773e7a340b 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -568,6 +568,10 @@ static Nurb *rna_Curve_spline_new(Curve *cu, int type)
nu->resolu = nu->resolv = 12;
nu->flag = CU_SMOOTH;
+ if ((cu->flag & CU_3D) == 0) {
+ nu->flag |= CU_2D;
+ }
+
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
return nu;
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 65e6b15d676..6a5fc393269 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -84,21 +84,33 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, parent->parent);
if (object) {
- MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
+ int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
- if (track) {
- int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra);
- MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
- float marker_pos_ofs[2], parmask_pos[2];
- MovieClipUser user = {0};
+ if (parent->type == MASK_PARENT_POINT_TRACK) {
+ MovieTrackingTrack *track = BKE_tracking_track_get_named(tracking, object, parent->sub_parent);
- BKE_movieclip_user_set_frame(&user, scene->r.cfra);
+ if (track) {
+ MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_framenr);
+ float marker_pos_ofs[2], parmask_pos[2];
+ MovieClipUser user = {0};
- add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
+ BKE_movieclip_user_set_frame(&user, scene->r.cfra);
- BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+ add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset);
- copy_v2_v2(parent->parent_orig, parmask_pos);
+ BKE_mask_coord_from_movieclip(clip, &user, parmask_pos, marker_pos_ofs);
+
+ copy_v2_v2(parent->parent_orig, parmask_pos);
+ }
+ }
+ else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
+ MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, object, parent->sub_parent);
+ if (plane_track) {
+ MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr);
+
+ memcpy(parent->parent_corners_orig, plane_marker->corners, sizeof(parent->parent_corners_orig));
+ zero_v2(parent->parent_orig);
+ }
}
}
}
@@ -513,6 +525,11 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
{ID_MC, "MOVIECLIP", ICON_SEQUENCE, "Movie Clip", ""},
{0, NULL, 0, NULL, NULL}};
+ static EnumPropertyItem parent_type_items[] = {
+ {MASK_PARENT_POINT_TRACK, "POINT_TRACK", 0, "Point Track", ""},
+ {MASK_PARENT_PLANE_TRACK, "PLANE_TRACK", 0, "Plane Track", ""},
+ {0, NULL, 0, NULL, NULL}};
+
srna = RNA_def_struct(brna, "MaskParent", NULL);
RNA_def_struct_ui_text(srna, "Mask Parent", "Parenting settings for masking element");
@@ -535,6 +552,12 @@ static void rna_MaskSpline_point_remove(ID *id, MaskSpline *spline, ReportList *
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
+ /* type */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, parent_type_items);
+ RNA_def_property_ui_text(prop, "Parent Type", "Parent Type");
+ RNA_def_property_update(prop, 0, "rna_Mask_update_parent");
+
/* parent */
prop = RNA_def_property(srna, "parent", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Parent", "Name of parent object in specified data block to which parenting happens");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 535c279c02f..3b594ab0961 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -5919,6 +5919,29 @@ static void def_cmp_translate(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_planetrackdeform(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "MovieClip");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Movie Clip", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "NodePlaneTrackDeformData", "storage");
+
+ prop = RNA_def_property(srna, "tracking_object", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "tracking_object");
+ RNA_def_property_ui_text(prop, "Tracking Object", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "plane_track_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "plane_track_name");
+ RNA_def_property_ui_text(prop, "Plane Track", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
/* -- Texture Nodes --------------------------------------------------------- */
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 4c47bbf93a6..1026a2c7772 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -95,6 +95,13 @@ static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRN
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
}
+static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+
+ rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+}
+
static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -146,6 +153,27 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value)
clip->tracking.act_track = NULL;
}
+static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
+
+ return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track);
+}
+
+static void rna_tracking_active_plane_track_set(PointerRNA *ptr, PointerRNA value)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *) value.data;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
+ int index = BLI_findindex(plane_tracks_base, plane_track);
+
+ if (index >= 0)
+ clip->tracking.act_plane_track = plane_track;
+ else
+ clip->tracking.act_plane_track = NULL;
+}
+
static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
@@ -197,6 +225,71 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, int value)
}
}
+static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value)
+{
+ MovieClip *clip = (MovieClip *) ptr->id.data;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneTrack *plane_track;
+ MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *) ptr->data;
+
+ /* TODO(sergey): Need to support editing markers from object's tracks */
+
+ plane_track = tracking->plane_tracks.first;
+ while (plane_track) {
+ if (plane_marker >= plane_track->markers &&
+ plane_marker < plane_track->markers + plane_track->markersnr)
+ {
+ break;
+ }
+
+ plane_track = plane_track->next;
+ }
+
+ if (plane_track) {
+ MovieTrackingPlaneMarker new_plane_marker = *plane_marker;
+ new_plane_marker.framenr = value;
+
+ BKE_tracking_plane_marker_delete(plane_track, plane_marker->framenr);
+ BKE_tracking_plane_marker_insert(plane_track, &new_plane_marker);
+ }
+}
+
+static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
+{
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+ char name_esc[sizeof(plane_track->name) * 2];
+ BLI_strescape(name_esc, plane_track->name, sizeof(name_esc));
+ return BLI_sprintfN("tracking.plane_tracks[\"%s\"]", name_esc);
+}
+
+static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value)
+{
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
+ ListBase *plane_tracks_base = &tracking->plane_tracks;
+
+ BLI_strncpy(plane_track->name, value, sizeof(plane_track->name));
+
+ /* TODO: it's a bit difficult to find list track came from knowing just
+ * movie clip ID and MovieTracking structure, so keep this naive
+ * search for a while */
+ if (BLI_findindex(plane_tracks_base, plane_track) < 0) {
+ MovieTrackingObject *object = tracking->objects.first;
+
+ while (object) {
+ if (BLI_findindex(&object->plane_tracks, plane_track)) {
+ plane_tracks_base = &object->plane_tracks;
+ break;
+ }
+
+ object = object->next;
+ }
+ }
+
+ BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+}
+
static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("tracking.camera");
@@ -294,6 +387,20 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
}
}
+static void rna_trackingObject_plane_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
+
+ if (object->flag & TRACKING_OBJECT_CAMERA) {
+ MovieClip *clip = (MovieClip *)ptr->id.data;
+
+ rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
+ }
+ else {
+ rna_iterator_listbase_begin(iter, &object->plane_tracks, NULL);
+ }
+}
+
static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
{
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
@@ -1188,6 +1295,83 @@ static void rna_def_trackingTrack(BlenderRNA *brna)
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
}
+static void rna_def_trackingPlaneMarker(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneMarker", NULL);
+ RNA_def_struct_ui_text(srna, "Movie Tracking Plane Marker Data", "Match-moving plane marker data for tracking");
+
+ /* frame */
+ prop = RNA_def_property(srna, "frame", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "framenr");
+ RNA_def_property_ui_text(prop, "Frame", "Frame number marker is keyframed on");
+ RNA_def_property_int_funcs(prop, NULL, "rna_trackingPlaneMarker_frame_set", NULL);
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, 0);
+
+ /* Corners */
+ prop = RNA_def_property(srna, "corners", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "corners");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2);
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_ui_text(prop, "Corners",
+ "Array of coordinates which represents UI rectange corners in "
+ "frame normalized coordinates");
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+
+ /* enable */
+ prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_MARKER_DISABLED);
+ RNA_def_property_ui_text(prop, "Mode", "Is marker muted for current frame");
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+}
+
+static void rna_def_trackingPlaneMarkers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ RNA_def_property_srna(cprop, "MovieTrackingPlaneMarkers");
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneMarkers", NULL);
+ RNA_def_struct_sdna(srna, "MovieTrackingPlaneTrack");
+ RNA_def_struct_ui_text(srna, "Movie Tracking Plane Markers", "Collection of markers for movie tracking plane track");
+}
+
+static void rna_def_trackingPlaneTrack(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ rna_def_trackingPlaneMarker(brna);
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneTrack", NULL);
+ RNA_def_struct_path_func(srna, "rna_trackingPlaneTrack_path");
+ RNA_def_struct_ui_text(srna, "Movie tracking plane track data", "Match-moving plane track data for tracking");
+ RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA);
+
+ /* name */
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Unique name of track");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_trackingPlaneTrack_name_set");
+ RNA_def_property_string_maxlength(prop, MAX_ID_NAME - 2);
+ RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ /* markers */
+ prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneMarker");
+ RNA_def_property_collection_sdna(prop, NULL, "markers", "markersnr");
+ RNA_def_property_ui_text(prop, "Markers", "Collection of markers in track");
+ rna_def_trackingPlaneMarkers(brna, prop);
+
+ /* select */
+ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT);
+ RNA_def_property_ui_text(prop, "Select", "Plane track is selected");
+ RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL);
+}
+
static void rna_def_trackingStabilization(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1373,6 +1557,23 @@ static void rna_def_trackingTracks(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
}
+static void rna_def_trackingPlaneTracks(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingPlaneTracks", NULL);
+ RNA_def_struct_sdna(srna, "MovieTracking");
+ RNA_def_struct_ui_text(srna, "Movie Plane Tracks", "Collection of movie tracking plane tracks");
+
+ /* active plane track */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Plane Track", "Active plane track in this tracking data object");
+}
+
static void rna_def_trackingObjectTracks(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1400,6 +1601,23 @@ static void rna_def_trackingObjectTracks(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
}
+static void rna_def_trackingObjectPlaneTracks(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "MovieTrackingObjectPlaneTracks", NULL);
+ RNA_def_struct_sdna(srna, "MovieTrackingObject");
+ RNA_def_struct_ui_text(srna, "Plane Tracks", "Collection of tracking plane tracks");
+
+ /* active track */
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "MovieTrackingTrack");
+ RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
+ RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object");
+}
+
static void rna_def_trackingObject(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1432,6 +1650,15 @@ static void rna_def_trackingObject(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
RNA_def_property_srna(prop, "MovieTrackingObjectTracks");
+ /* plane tracks */
+ prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_trackingObject_plane_tracks_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+ RNA_def_property_srna(prop, "MovieTrackingObjectPlaneTracks");
+
/* reconstruction */
prop = RNA_def_property(srna, "reconstruction", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MovieTrackingReconstruction");
@@ -1549,8 +1776,11 @@ static void rna_def_tracking(BlenderRNA *brna)
rna_def_trackingSettings(brna);
rna_def_trackingCamera(brna);
rna_def_trackingTrack(brna);
+ rna_def_trackingPlaneTrack(brna);
rna_def_trackingTracks(brna);
+ rna_def_trackingPlaneTracks(brna);
rna_def_trackingObjectTracks(brna);
+ rna_def_trackingObjectPlaneTracks(brna);
rna_def_trackingStabilization(brna);
rna_def_trackingReconstruction(brna);
rna_def_trackingObject(brna);
@@ -1577,6 +1807,15 @@ static void rna_def_tracking(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks in this tracking data object");
RNA_def_property_srna(prop, "MovieTrackingTracks");
+ /* tracks */
+ prop = RNA_def_property(srna, "plane_tracks", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_trackingPlaneTracks_begin", "rna_iterator_listbase_next",
+ "rna_iterator_listbase_end", "rna_iterator_listbase_get",
+ NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack");
+ RNA_def_property_ui_text(prop, "Plane Tracks", "Collection of plane tracks in this tracking data object");
+ RNA_def_property_srna(prop, "MovieTrackingPlaneTracks");
+
/* stabilization */
prop = RNA_def_property(srna, "stabilization", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "MovieTrackingStabilization");
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 64261246e3d..4ac75c15efe 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -92,6 +92,7 @@ set(SRC
composite/nodes/node_composite_normal.c
composite/nodes/node_composite_normalize.c
composite/nodes/node_composite_outputFile.c
+ composite/nodes/node_composite_planetrackdeform.c
composite/nodes/node_composite_premulkey.c
composite/nodes/node_composite_rgb.c
composite/nodes/node_composite_rotate.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index 626e7955b08..4320e0436ce 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -137,6 +137,7 @@ void register_node_type_cmp_bokehblur(void);
void register_node_type_cmp_switch(void);
void register_node_type_cmp_pixelate(void);
void register_node_type_cmp_trackpos(void);
+void register_node_type_cmp_planetrackdeform(void);
void node_cmp_rlayers_force_hidden_passes(struct bNode *node);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 0b526fcde0e..eeec40c911f 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -1,3 +1,4 @@
+
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -200,6 +201,7 @@ DefNode( CompositorNode, CMP_NODE_KEYINGSCREEN, def_cmp_keyingscreen, "KEYIN
DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYING", Keying, "Keying", "" )
DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" )
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
+DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
new file mode 100644
index 00000000000..7a15d6364dc
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_planetrackdeform.c
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_planetrackdeform.c
+ * \ingroup cmpnodes
+ */
+
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_in[] = {
+ { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate cmp_node_planetrackdeform_out[] = {
+ { SOCK_RGBA, 0, N_("Image")},
+ { SOCK_FLOAT, 0, N_("Plane")},
+ { -1, 0, "" }
+};
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodePlaneTrackDeformData *data = MEM_callocN(sizeof(NodePlaneTrackDeformData), "node plane track deform data");
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_planetrackdeform(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_PLANETRACKDEFORM, "Plane Track Deform", NODE_CLASS_DISTORT, 0);
+ node_type_socket_templates(&ntype, cmp_node_planetrackdeform_in, cmp_node_planetrackdeform_out);
+ node_type_init(&ntype, init);
+ node_type_storage(&ntype, "NodePlaneTrackDeformData", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 90383021c90..a28906254a1 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -66,6 +66,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
float endtime,
struct bAction *action,
short playtype,
+ short blend_mode,
short blendin,
short priority,
short layer,
@@ -88,6 +89,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj,
m_stridelength(stride),
m_layer_weight(layer_weight),
m_playtype(playtype),
+ m_blendmode(blend_mode),
m_priority(priority),
m_layer(layer),
m_ipo_flags(ipo_flags),
@@ -187,6 +189,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
bool bUseContinue = false;
KX_GameObject *obj = (KX_GameObject*)GetParent();
short playtype = BL_Action::ACT_MODE_PLAY;
+ short blendmode = (m_blendmode == ACT_ACTION_ADD) ? BL_Action::ACT_BLEND_ADD : BL_Action::ACT_BLEND_BLEND;
float start = m_startframe;
float end = m_endframe;
@@ -283,7 +286,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
ResetStartTime(curtime);
}
- if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags))
+ if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags, 1.f, blendmode))
{
m_flag |= ACT_FLAG_ACTIVE;
if (bUseContinue)
@@ -328,7 +331,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
// Convert into a play action and play back to the beginning
end = start;
start = obj->GetActionFrame(m_layer);
- obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
+ obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode);
m_flag |= ACT_FLAG_PLAY_END;
break;
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index ce805c774ef..4579a21f554 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -48,6 +48,7 @@ public:
float endtime,
struct bAction *action,
short playtype,
+ short blend_mode,
short blendin,
short priority,
short layer,
@@ -129,6 +130,7 @@ protected:
float m_stridelength;
float m_layer_weight;
short m_playtype;
+ short m_blendmode;
short m_priority;
short m_layer;
short m_ipo_flags;
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 55d9decb333..d8ddb33ddc4 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -32,6 +32,7 @@
#include "BL_ArmatureObject.h"
#include "BL_ActionActuator.h"
+#include "BL_Action.h"
#include "KX_BlenderSceneConverter.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -50,7 +51,6 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_nla_types.h"
#include "DNA_constraint_types.h"
#include "KX_PythonSeq.h"
#include "KX_PythonInit.h"
@@ -137,25 +137,22 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
/* Only allowed for Poses with identical channels */
-void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
+void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
{
- short mode= ACTSTRIPMODE_BLEND;
-
bPoseChannel *dchan;
const bPoseChannel *schan;
bConstraint *dcon, *scon;
float dstweight;
int i;
- switch (mode) {
- case ACTSTRIPMODE_BLEND:
- dstweight = 1.0F - srcweight;
- break;
- case ACTSTRIPMODE_ADD:
- dstweight = 1.0F;
- break;
- default :
- dstweight = 1.0F;
+ if (mode == BL_Action::ACT_BLEND_BLEND)
+ {
+ dstweight = 1.0f - srcweight;
+ } else if (mode == BL_Action::ACT_BLEND_ADD)
+ {
+ dstweight = 1.0f;
+ } else {
+ dstweight = 1.0f;
}
schan= (bPoseChannel *)src->chanbase.first;
@@ -167,7 +164,7 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
copy_qt_qt(dquat, dchan->quat);
copy_qt_qt(squat, schan->quat);
- if (mode==ACTSTRIPMODE_BLEND)
+ if (mode==BL_Action::ACT_BLEND_BLEND)
interp_qt_qtqt(dchan->quat, dquat, squat, srcweight);
else {
mul_fac_qt_fl(squat, srcweight);
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index 445b9af1b10..81388355fc4 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -147,7 +147,7 @@ protected:
};
/* Pose function specific to the game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); /* was blend_poses */
//void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
void game_free_pose(struct bPose *pose);
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 5b528972e00..27989983326 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -225,6 +225,7 @@ void BL_ConvertActuators(const char* maggiename,
actact->end,
actact->act,
actact->type, // + 1, because Blender starts to count at zero,
+ actact->blend_mode,
actact->blendin,
actact->priority,
actact->layer,
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index 9d189a6170e..6d9b22eed91 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -65,7 +65,8 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
m_blendstart(0.f),
m_speed(0.f),
m_priority(0),
- m_playmode(0),
+ m_playmode(ACT_MODE_PLAY),
+ m_blendmode(ACT_BLEND_BLEND),
m_ipo_flags(0),
m_done(true),
m_calc_localtime(true)
@@ -104,7 +105,8 @@ bool BL_Action::Play(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
// Only start playing a new action if we're done, or if
@@ -229,6 +231,7 @@ bool BL_Action::Play(const char* name,
m_endframe = end;
m_blendin = blendin;
m_playmode = play_mode;
+ m_blendmode = blend_mode;
m_endtime = 0.f;
m_blendframe = 0.f;
m_blendstart = 0.f;
@@ -423,7 +426,7 @@ void BL_Action::Update(float curtime)
float weight = 1.f - (m_blendframe/m_blendin);
// Blend the poses
- game_blend_poses(m_pose, m_blendinpose, weight);
+ game_blend_poses(m_pose, m_blendinpose, weight, ACT_BLEND_BLEND);
}
@@ -431,7 +434,7 @@ void BL_Action::Update(float curtime)
if (m_layer_weight >= 0)
{
obj->GetMRDPose(&m_blendpose);
- game_blend_poses(m_pose, m_blendpose, m_layer_weight);
+ game_blend_poses(m_pose, m_blendpose, m_layer_weight, m_blendmode);
}
obj->SetPose(m_pose);
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index e4088633e61..e9d09916517 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -34,7 +34,6 @@
#include "MEM_guardedalloc.h"
#endif
-
class BL_Action
{
private:
@@ -64,6 +63,7 @@ private:
short m_priority;
short m_playmode;
+ short m_blendmode;
short m_ipo_flags;
@@ -91,7 +91,8 @@ public:
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed);
+ float playback_speed,
+ short blend_mode);
/**
* Stop playing the action
*/
@@ -114,7 +115,7 @@ public:
void SetPlayMode(short play_mode);
void SetTimes(float start, float end);
- enum
+ enum
{
ACT_MODE_PLAY = 0,
ACT_MODE_LOOP,
@@ -124,6 +125,13 @@ public:
enum
{
+ ACT_BLEND_BLEND=0,
+ ACT_BLEND_ADD=1,
+ ACT_BLEND_MAX,
+ };
+
+ enum
+ {
ACT_IPOFLAG_FORCE = 1,
ACT_IPOFLAG_LOCAL = 2,
ACT_IPOFLAG_ADD = 4,
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index e3402972ca6..2e882ceba74 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -25,6 +25,7 @@
*/
#include "BL_ActionManager.h"
+#include "BL_Action.h"
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj)
{
@@ -72,12 +73,13 @@ bool BL_ActionManager::PlayAction(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
// Disable layer blending on the first layer
if (layer == 0) layer_weight = -1.f;
- return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+ return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
}
void BL_ActionManager::StopAction(short layer)
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 600e7b6621e..88aa241b6ce 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -27,10 +27,10 @@
#ifndef __BL_ACTIONMANAGER_H__
#define __BL_ACTIONMANAGER_H__
-#include "BL_Action.h"
-
#define MAX_ACTION_LAYERS 8
+class BL_Action;
+
/**
* BL_ActionManager is responsible for handling a KX_GameObject's actions.
*/
@@ -52,7 +52,8 @@ public:
short play_mode=0,
float layer_weight=0.f,
short ipo_flags=0,
- float playback_speed=1.f);
+ float playback_speed=1.f,
+ short blend_mode=0);
/**
* Gets the current frame of an action
*/
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index aa082c7ef19..85fa0b2b3ce 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -401,21 +401,21 @@ void KX_Dome::GLDrawWarpQuads(void)
if (warp.nodes[i][j].i < 0 || warp.nodes[i+1][j].i < 0 || warp.nodes[i+1][j+1].i < 0 || warp.nodes[i][j+1].i < 0)
continue;
- glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i);
- glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
- glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0);
-
- glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i);
- glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height));
- glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0);
+ glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i);
+ glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height));
+ glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0);
glColor3f(warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i, warp.nodes[i+1][j+1].i);
glTexCoord2f((warp.nodes[i+1][j+1].u * uv_width), (warp.nodes[i+1][j+1].v * uv_height));
glVertex3f(warp.nodes[i+1][j+1].x, warp.nodes[i+1][j+1].y,0.0);
- glColor3f(warp.nodes[i][j+1].i, warp.nodes[i][j+1].i, warp.nodes[i][j+1].i);
- glTexCoord2f((warp.nodes[i][j+1].u * uv_width), (warp.nodes[i][j+1].v * uv_height));
- glVertex3f(warp.nodes[i][j+1].x, warp.nodes[i][j+1].y,0.0);
+ glColor3f(warp.nodes[i+1][j].i, warp.nodes[i+1][j].i, warp.nodes[i+1][j].i);
+ glTexCoord2f((warp.nodes[i+1][j].u * uv_width), (warp.nodes[i+1][j].v * uv_height));
+ glVertex3f(warp.nodes[i+1][j].x, warp.nodes[i+1][j].y,0.0);
+
+ glColor3f(warp.nodes[i][j].i, warp.nodes[i][j].i, warp.nodes[i][j].i);
+ glTexCoord2f((warp.nodes[i][j].u * uv_width), (warp.nodes[i][j].v * uv_height));
+ glVertex3f(warp.nodes[i][j].x, warp.nodes[i][j].y,0.0);
}
}
glEnd();
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index ec62ae63f0c..e0ec4983739 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -73,6 +73,7 @@ typedef unsigned long uint_ptr;
#include "KX_ObstacleSimulation.h"
#include "BL_ActionManager.h"
+#include "BL_Action.h"
#include "PyObjectPlus.h" /* python stuff */
@@ -429,9 +430,10 @@ bool KX_GameObject::PlayAction(const char* name,
short play_mode,
float layer_weight,
short ipo_flags,
- float playback_speed)
+ float playback_speed,
+ short blend_mode)
{
- return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
+ return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
}
void KX_GameObject::StopAction(short layer)
@@ -3311,11 +3313,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
short layer=0, priority=0;
short ipo_flags=0;
short play_mode=0;
+ short blend_mode=0;
- static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
+ static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist),
- &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", const_cast<char**>(kwlist),
+ &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
return NULL;
layer_check(layer, "playAction");
@@ -3323,7 +3326,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX)
{
printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1);
- play_mode = BL_Action::ACT_MODE_MAX;
+ play_mode = BL_Action::ACT_MODE_PLAY;
+ }
+
+ if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX)
+ {
+ printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_BLEND", blend_mode, BL_Action::ACT_BLEND_MAX-1);
+ blend_mode = BL_Action::ACT_BLEND_BLEND;
}
if (layer_weight < 0.f || layer_weight > 1.f)
@@ -3332,7 +3341,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
layer_weight = 0.f;
}
- PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
+ PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed, blend_mode);
Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 13a79cebefb..5a3b9df74ee 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -255,7 +255,8 @@ public:
short play_mode=0,
float layer_weight=0.f,
short ipo_flags=0,
- float playback_speed=1.f);
+ float playback_speed=1.f,
+ short blend_mode=0);
/**
* Gets the current frame of an action
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index d8b4bf9e8bd..ae9cbbb2656 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -1820,6 +1820,10 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_LOOP, BL_Action::ACT_MODE_LOOP);
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PING_PONG, BL_Action::ACT_MODE_PING_PONG);
+ /* BL_Action blend modes */
+ KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_BLEND, BL_Action::ACT_BLEND_BLEND);
+ KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_ADD, BL_Action::ACT_BLEND_ADD);
+
// Check for errors
if (PyErr_Occurred())
{
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 5438ae5a97c..3a4b1d82946 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -109,7 +109,7 @@ void KX_SoundActuator::play()
try
{
- m_handle = AUD_getDevice()->play(sound, 0);
+ m_handle = AUD_getDevice()->play(sound);
}
catch(AUD_Exception&)
{