2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2011 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup spclip
|
2011-11-07 12:55:18 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
|
#include "DNA_space_types.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-02-11 16:59:42 +01:00
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_geom.h"
|
|
|
|
|
#include "BLI_math_vector.h"
|
2024-11-23 17:00:21 +01:00
|
|
|
#include "BLI_set.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_context.hh"
|
2024-11-12 15:21:59 +01:00
|
|
|
#include "BKE_image.hh"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_movieclip.h"
|
2024-02-10 18:34:29 +01:00
|
|
|
#include "BKE_report.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_tracking.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
2017-06-08 10:14:53 +02:00
|
|
|
|
2024-03-12 23:12:45 +01:00
|
|
|
#include "UI_interface_icons.hh"
|
2025-01-21 21:53:47 +01:00
|
|
|
#include "UI_resources.hh"
|
2024-03-12 23:12:45 +01:00
|
|
|
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "WM_api.hh"
|
|
|
|
|
#include "WM_types.hh"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-08-05 02:57:52 +02:00
|
|
|
#include "ED_clip.hh"
|
2023-08-04 23:11:22 +02:00
|
|
|
#include "ED_screen.hh"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_access.hh"
|
|
|
|
|
#include "RNA_define.hh"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2024-02-09 18:59:42 +01:00
|
|
|
#include "BLT_translation.hh"
|
2013-05-30 11:37:53 +00:00
|
|
|
|
2024-01-18 22:50:23 +02:00
|
|
|
#include "IMB_imbuf.hh"
|
|
|
|
|
#include "IMB_imbuf_types.hh"
|
2022-06-28 16:03:35 +02:00
|
|
|
|
2024-03-26 20:34:48 -04:00
|
|
|
#include "clip_intern.hh"
|
|
|
|
|
#include "tracking_ops_intern.hh"
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Add Marker Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-05-22 06:28:59 +00:00
|
|
|
static bool add_marker(const bContext *C, float x, float y)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-06-20 10:28:51 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2011-11-07 12:55:18 +00:00
|
|
|
MovieTrackingTrack *track;
|
|
|
|
|
int width, height;
|
2012-06-19 14:26:29 +00:00
|
|
|
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
|
2012-07-26 22:41:40 +00:00
|
|
|
ED_space_clip_get_size(sc, &width, &height);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-05-22 06:28:59 +00:00
|
|
|
if (width == 0 || height == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
track = BKE_tracking_track_add(tracking, &tracking_object->tracks, x, y, framenr, width, height);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
BKE_tracking_track_select(&tracking_object->tracks, track, TRACK_AREA_ALL, false);
|
2022-10-04 17:39:57 +02:00
|
|
|
BKE_tracking_plane_tracks_deselect_all(&tracking_object->plane_tracks);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
tracking_object->active_track = track;
|
2023-03-01 12:32:15 +01:00
|
|
|
tracking_object->active_plane_track = nullptr;
|
2013-05-22 06:28:59 +00:00
|
|
|
|
|
|
|
|
return true;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus add_marker_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2011-11-07 12:55:18 +00:00
|
|
|
float pos[2];
|
|
|
|
|
|
2021-01-19 14:28:44 +01:00
|
|
|
ClipViewLockState lock_state;
|
|
|
|
|
ED_clip_view_lock_state_store(C, &lock_state);
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
RNA_float_get_array(op->ptr, "location", pos);
|
|
|
|
|
|
2013-05-22 06:28:59 +00:00
|
|
|
if (!add_marker(C, pos[0], pos[1])) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2021-01-19 14:28:44 +01:00
|
|
|
ED_clip_view_lock_state_restore_no_jump(C, &lock_state);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus add_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-07-26 22:41:40 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2012-07-26 22:41:40 +00:00
|
|
|
|
2013-05-21 14:44:50 +00:00
|
|
|
if (!RNA_struct_property_is_set(op->ptr, "location")) {
|
2021-02-13 17:44:51 +11:00
|
|
|
/* If location is not set, use mouse position as default. */
|
2013-05-21 14:44:50 +00:00
|
|
|
float co[2];
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_clip_mouse_pos(sc, region, event->mval, co);
|
2013-05-21 14:44:50 +00:00
|
|
|
RNA_float_set_array(op->ptr, "location", co);
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
return add_marker_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_add_marker(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Add Marker";
|
|
|
|
|
ot->idname = "CLIP_OT_add_marker";
|
|
|
|
|
ot->description = "Place new marker at specified location";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = add_marker_invoke;
|
|
|
|
|
ot->exec = add_marker_exec;
|
2012-06-07 16:36:19 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* properties */
|
2012-10-11 23:46:12 +00:00
|
|
|
RNA_def_float_vector(ot->srna,
|
|
|
|
|
"location",
|
|
|
|
|
2,
|
2023-03-01 12:32:15 +01:00
|
|
|
nullptr,
|
2012-10-11 23:46:12 +00:00
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX,
|
2012-06-10 19:59:02 +00:00
|
|
|
"Location",
|
|
|
|
|
"Location of marker on frame",
|
|
|
|
|
-1.0f,
|
|
|
|
|
1.0f);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Add Marker Operator
|
|
|
|
|
* \{ */
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus add_marker_at_click_invoke(bContext *C,
|
|
|
|
|
wmOperator *op,
|
|
|
|
|
const wmEvent * /*event*/)
|
2013-05-22 06:06:22 +00:00
|
|
|
{
|
2025-01-21 21:53:47 +01:00
|
|
|
WorkspaceStatus status(C);
|
|
|
|
|
status.item(IFACE_("Cancel"), ICON_EVENT_ESC);
|
|
|
|
|
status.item(IFACE_("Place Marker"), ICON_MOUSE_LMB);
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Add modal handler for ESC. */
|
2013-05-30 11:37:53 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2013-05-30 11:37:53 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus add_marker_at_click_modal(bContext *C,
|
|
|
|
|
wmOperator * /*op*/,
|
|
|
|
|
const wmEvent *event)
|
2013-05-30 11:37:53 +00:00
|
|
|
{
|
2013-05-31 22:35:25 +00:00
|
|
|
switch (event->type) {
|
|
|
|
|
case MOUSEMOVE:
|
2013-05-30 11:37:53 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2013-05-31 22:35:25 +00:00
|
|
|
case LEFTMOUSE: {
|
2016-01-15 13:48:24 +05:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2016-01-15 13:48:24 +05:00
|
|
|
float pos[2];
|
|
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
ED_workspace_status_text(C, nullptr);
|
2013-05-30 11:37:53 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_clip_point_stable_pos(sc,
|
|
|
|
|
region,
|
2021-10-20 23:45:30 +11:00
|
|
|
event->xy[0] - region->winrct.xmin,
|
|
|
|
|
event->xy[1] - region->winrct.ymin,
|
2020-03-06 16:56:42 +01:00
|
|
|
&pos[0],
|
|
|
|
|
&pos[1]);
|
2013-05-30 11:37:53 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!add_marker(C, pos[0], pos[1])) {
|
2013-05-30 11:37:53 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2013-05-30 11:37:53 +00:00
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
|
|
|
|
return OPERATOR_FINISHED;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2013-05-30 11:37:53 +00:00
|
|
|
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_ESCKEY:
|
2023-03-01 12:32:15 +01:00
|
|
|
ED_workspace_status_text(C, nullptr);
|
2013-05-31 22:35:25 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2025-03-31 23:48:29 +00:00
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-05-31 22:35:25 +00:00
|
|
|
}
|
2013-05-30 11:37:53 +00:00
|
|
|
|
2013-05-31 22:35:25 +00:00
|
|
|
return OPERATOR_PASS_THROUGH;
|
2013-05-22 06:06:22 +00:00
|
|
|
}
|
|
|
|
|
|
2013-05-30 11:37:53 +00:00
|
|
|
void CLIP_OT_add_marker_at_click(wmOperatorType *ot)
|
2013-05-22 06:06:22 +00:00
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2013-05-30 11:37:53 +00:00
|
|
|
ot->name = "Add Marker at Click";
|
|
|
|
|
ot->idname = "CLIP_OT_add_marker_at_click";
|
|
|
|
|
ot->description = "Place new marker at the desired (clicked) position";
|
2013-05-22 06:06:22 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2013-05-30 11:37:53 +00:00
|
|
|
ot->invoke = add_marker_at_click_invoke;
|
2013-05-22 06:06:22 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2013-05-30 11:37:53 +00:00
|
|
|
ot->modal = add_marker_at_click_modal;
|
2013-05-22 06:06:22 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2013-05-30 11:37:53 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
|
2013-05-22 06:06:22 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Delete Track Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus delete_track_exec(bContext *C, wmOperator * /*op*/)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2022-10-07 11:32:21 +02:00
|
|
|
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
/* Delete selected plane tracks. */
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks)
|
|
|
|
|
{
|
2014-03-06 20:07:14 +06:00
|
|
|
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
2017-12-19 12:58:42 +01:00
|
|
|
clip_delete_plane_track(C, clip, plane_track);
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-07 11:32:21 +02:00
|
|
|
|
|
|
|
|
/* Remove selected point tracks (they'll also be removed from planes which uses them). */
|
|
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2013-11-26 00:38:50 +01:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track)) {
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
clip_delete_track(C, clip, track);
|
2013-11-26 00:38:50 +01:00
|
|
|
changed = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-11-26 00:38:50 +01:00
|
|
|
}
|
2022-10-07 11:32:21 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (changed) {
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2022-10-07 11:32:21 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus delete_track_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
2024-03-12 23:12:45 +01:00
|
|
|
{
|
|
|
|
|
if (RNA_boolean_get(op->ptr, "confirm")) {
|
|
|
|
|
return WM_operator_confirm_ex(C,
|
|
|
|
|
op,
|
|
|
|
|
IFACE_("Delete selected tracks?"),
|
|
|
|
|
nullptr,
|
|
|
|
|
IFACE_("Delete"),
|
|
|
|
|
ALERT_ICON_NONE,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
return delete_track_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
void CLIP_OT_delete_track(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Delete Track";
|
|
|
|
|
ot->idname = "CLIP_OT_delete_track";
|
|
|
|
|
ot->description = "Delete selected tracks";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2024-03-12 23:12:45 +01:00
|
|
|
ot->invoke = delete_track_invoke;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = delete_track_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2023-05-16 20:03:45 +02:00
|
|
|
WM_operator_properties_confirm_or_exec(ot);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Delete Marker Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus delete_marker_exec(bContext *C, wmOperator * /*op*/)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
2016-01-15 13:48:24 +05:00
|
|
|
const int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2013-11-26 00:38:50 +01:00
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track)) {
|
2012-06-15 11:03:23 +00:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (marker != nullptr) {
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
clip_delete_marker(C, clip, track, marker);
|
2013-11-26 00:38:50 +01:00
|
|
|
changed = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks)
|
|
|
|
|
{
|
2014-03-06 20:07:14 +06:00
|
|
|
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
|
|
|
|
|
framenr);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (plane_marker != nullptr) {
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
if (plane_track->markersnr == 1) {
|
|
|
|
|
BKE_tracking_plane_track_free(plane_track);
|
2022-10-07 11:32:21 +02:00
|
|
|
BLI_freelinkN(&tracking_object->plane_tracks, plane_track);
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BKE_tracking_plane_marker_delete(plane_track, framenr);
|
|
|
|
|
}
|
2013-11-26 00:38:50 +01:00
|
|
|
changed = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!changed) {
|
2013-11-26 00:38:50 +01:00
|
|
|
return OPERATOR_CANCELLED;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus delete_marker_invoke(bContext *C,
|
|
|
|
|
wmOperator *op,
|
|
|
|
|
const wmEvent * /*event*/)
|
2024-03-12 23:12:45 +01:00
|
|
|
{
|
|
|
|
|
if (RNA_boolean_get(op->ptr, "confirm")) {
|
|
|
|
|
return WM_operator_confirm_ex(C,
|
|
|
|
|
op,
|
|
|
|
|
IFACE_("Delete marker for current frame from selected tracks?"),
|
|
|
|
|
nullptr,
|
|
|
|
|
IFACE_("Delete"),
|
|
|
|
|
ALERT_ICON_NONE,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
return delete_marker_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
void CLIP_OT_delete_marker(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Delete Marker";
|
|
|
|
|
ot->idname = "CLIP_OT_delete_marker";
|
|
|
|
|
ot->description = "Delete marker for current frame from selected tracks";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2024-03-12 23:12:45 +01:00
|
|
|
ot->invoke = delete_marker_invoke;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = delete_marker_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2023-05-16 20:03:45 +02:00
|
|
|
WM_operator_properties_confirm_or_exec(ot);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Slide Marker Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-07-24 10:10:47 +10:00
|
|
|
enum eSlideAction {
|
2022-05-12 11:35:56 +02:00
|
|
|
SLIDE_ACTION_NONE,
|
|
|
|
|
|
|
|
|
|
SLIDE_ACTION_POS,
|
2016-01-15 13:48:24 +05:00
|
|
|
SLIDE_ACTION_SIZE,
|
|
|
|
|
SLIDE_ACTION_OFFSET,
|
|
|
|
|
SLIDE_ACTION_TILT_SIZE,
|
2023-07-24 10:10:47 +10:00
|
|
|
};
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-07-24 10:10:47 +10:00
|
|
|
struct SlideMarkerData {
|
2022-05-12 11:35:56 +02:00
|
|
|
short area;
|
|
|
|
|
eSlideAction action;
|
2011-11-07 12:55:18 +00:00
|
|
|
MovieTrackingTrack *track;
|
|
|
|
|
MovieTrackingMarker *marker;
|
|
|
|
|
|
|
|
|
|
int mval[2];
|
|
|
|
|
int width, height;
|
2022-05-13 12:51:00 +02:00
|
|
|
float *min, *max, *pos, (*corners)[2];
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-03-31 15:31:28 +06:00
|
|
|
bool lock, accurate;
|
2012-06-15 16:07:33 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Data to restore on cancel. */
|
2022-05-13 12:51:00 +02:00
|
|
|
float old_search_min[2], old_search_max[2], old_pos[2];
|
2012-06-15 16:07:33 +00:00
|
|
|
float old_corners[4][2];
|
|
|
|
|
float (*old_markers)[2];
|
2023-07-24 10:10:47 +10:00
|
|
|
};
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
static void slide_marker_tilt_slider_relative(const float pattern_corners[4][2], float r_slider[2])
|
2012-06-15 18:31:46 +00:00
|
|
|
{
|
2022-05-13 13:08:23 +02:00
|
|
|
add_v2_v2v2(r_slider, pattern_corners[1], pattern_corners[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
static SlideMarkerData *create_slide_marker_data(SpaceClip *sc,
|
|
|
|
|
MovieTrackingTrack *track,
|
|
|
|
|
MovieTrackingMarker *marker,
|
|
|
|
|
const wmEvent *event,
|
|
|
|
|
int area,
|
|
|
|
|
int corner,
|
2022-05-12 11:35:56 +02:00
|
|
|
eSlideAction action,
|
2016-01-15 13:48:24 +05:00
|
|
|
int width,
|
|
|
|
|
int height)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2025-03-05 16:35:09 +01:00
|
|
|
SlideMarkerData *data = MEM_callocN<SlideMarkerData>("slide marker data");
|
2012-06-19 14:26:29 +00:00
|
|
|
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
marker = BKE_tracking_marker_ensure(track, framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
data->area = area;
|
|
|
|
|
data->action = action;
|
|
|
|
|
data->track = track;
|
|
|
|
|
data->marker = marker;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (area == TRACK_AREA_POINT) {
|
|
|
|
|
data->pos = marker->pos;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else if (area == TRACK_AREA_PAT) {
|
2022-05-13 12:51:00 +02:00
|
|
|
if (action == SLIDE_ACTION_POS) {
|
|
|
|
|
data->corners = marker->pattern_corners;
|
|
|
|
|
data->pos = marker->pattern_corners[corner];
|
|
|
|
|
}
|
|
|
|
|
else if (action == SLIDE_ACTION_TILT_SIZE) {
|
|
|
|
|
data->corners = marker->pattern_corners;
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else if (area == TRACK_AREA_SEARCH) {
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
data->min = marker->search_min;
|
|
|
|
|
data->max = marker->search_max;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
data->mval[0] = event->mval[0];
|
|
|
|
|
data->mval[1] = event->mval[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
data->width = width;
|
|
|
|
|
data->height = height;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (action == SLIDE_ACTION_SIZE) {
|
2014-03-31 15:31:28 +06:00
|
|
|
data->lock = true;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Backup marker's settings. */
|
2012-06-15 16:07:33 +00:00
|
|
|
memcpy(data->old_corners, marker->pattern_corners, sizeof(data->old_corners));
|
|
|
|
|
copy_v2_v2(data->old_search_min, marker->search_min);
|
|
|
|
|
copy_v2_v2(data->old_search_max, marker->search_max);
|
|
|
|
|
copy_v2_v2(data->old_pos, marker->pos);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return data;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-05 13:37:53 +00:00
|
|
|
static bool slide_check_corners(float (*corners)[2])
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
{
|
|
|
|
|
float cross = 0.0f;
|
2020-08-07 22:36:11 +10:00
|
|
|
const float p[2] = {0.0f, 0.0f};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3])) {
|
2013-09-05 13:37:53 +00:00
|
|
|
return false;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 18:41:07 +02:00
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
float v1[2], v2[2];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 18:41:07 +02:00
|
|
|
int next = (i + 1) % 4;
|
|
|
|
|
int prev = (4 + i - 1) % 4;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
sub_v2_v2v2(v1, corners[i], corners[prev]);
|
|
|
|
|
sub_v2_v2v2(v2, corners[next], corners[i]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 18:41:07 +02:00
|
|
|
float cur_cross = cross_v2v2(v1, v2);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
if (fabsf(cur_cross) > FLT_EPSILON) {
|
|
|
|
|
if (cross == 0.0f) {
|
|
|
|
|
cross = cur_cross;
|
|
|
|
|
}
|
|
|
|
|
else if (cross * cur_cross < 0.0f) {
|
2013-09-05 13:37:53 +00:00
|
|
|
return false;
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-05 13:37:53 +00:00
|
|
|
return true;
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-12 11:30:16 +02:00
|
|
|
static MovieTrackingTrack *tracking_marker_check_slide(
|
2022-05-13 17:14:28 +02:00
|
|
|
bContext *C, const float co[2], int *r_area, eSlideAction *r_action, int *r_corner)
|
2012-06-15 11:40:04 +00:00
|
|
|
{
|
2022-10-07 16:55:43 +02:00
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
TrackPickOptions options = ed_tracking_pick_options_defaults();
|
|
|
|
|
options.selected_only = true;
|
|
|
|
|
options.unlocked_only = true;
|
|
|
|
|
options.enabled_only = true;
|
|
|
|
|
const PointTrackPick track_pick = ed_tracking_pick_point_track(&options, C, co);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
if (ed_tracking_point_track_pick_empty(&track_pick) ||
|
|
|
|
|
!ed_tracking_point_track_pick_can_slide(space_clip, &track_pick))
|
|
|
|
|
{
|
2023-03-01 12:32:15 +01:00
|
|
|
return nullptr;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
const eTrackArea area = track_pick.area;
|
|
|
|
|
eSlideAction action = SLIDE_ACTION_NONE;
|
|
|
|
|
int corner = -1;
|
2022-05-12 11:10:30 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
switch (area) {
|
|
|
|
|
case TRACK_AREA_NONE:
|
|
|
|
|
case TRACK_AREA_ALL:
|
|
|
|
|
BLI_assert_msg(0, "Expected single track area");
|
2023-03-01 12:32:15 +01:00
|
|
|
return nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
case TRACK_AREA_POINT:
|
|
|
|
|
action = SLIDE_ACTION_POS;
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
case TRACK_AREA_PAT:
|
|
|
|
|
if (track_pick.area_detail == TRACK_PICK_AREA_DETAIL_TILT_SIZE) {
|
|
|
|
|
action = SLIDE_ACTION_TILT_SIZE;
|
2022-05-12 11:10:30 +02:00
|
|
|
}
|
2022-10-07 16:55:43 +02:00
|
|
|
else if (track_pick.area_detail == TRACK_PICK_AREA_DETAIL_POSITION) {
|
2022-05-12 11:10:30 +02:00
|
|
|
action = SLIDE_ACTION_POS;
|
2022-10-07 16:55:43 +02:00
|
|
|
corner = track_pick.corner_index;
|
2022-05-12 11:10:30 +02:00
|
|
|
}
|
2022-10-07 16:55:43 +02:00
|
|
|
else {
|
|
|
|
|
BLI_assert_msg(0, "Unhandled pattern area");
|
2023-03-01 12:32:15 +01:00
|
|
|
return nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2022-10-07 16:55:43 +02:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
case TRACK_AREA_SEARCH:
|
|
|
|
|
if (track_pick.area_detail == TRACK_PICK_AREA_DETAIL_SIZE) {
|
|
|
|
|
action = SLIDE_ACTION_SIZE;
|
|
|
|
|
}
|
|
|
|
|
else if (track_pick.area_detail == TRACK_PICK_AREA_DETAIL_OFFSET) {
|
|
|
|
|
action = SLIDE_ACTION_OFFSET;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert_msg(0, "Unhandled search area");
|
2023-03-01 12:32:15 +01:00
|
|
|
return nullptr;
|
2022-10-07 16:55:43 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2012-06-15 11:40:04 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
if (r_area) {
|
|
|
|
|
*r_area = area;
|
|
|
|
|
}
|
|
|
|
|
if (r_action) {
|
|
|
|
|
*r_action = action;
|
|
|
|
|
}
|
|
|
|
|
if (r_corner) {
|
|
|
|
|
*r_corner = corner;
|
2016-01-15 12:23:24 +05:00
|
|
|
}
|
2022-05-12 11:10:30 +02:00
|
|
|
|
2022-10-07 16:55:43 +02:00
|
|
|
return track_pick.track;
|
2012-06-15 11:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
MovieTrackingTrack *tracking_find_slidable_track_in_proximity(bContext *C, const float co[2])
|
2022-05-12 11:30:16 +02:00
|
|
|
{
|
2023-03-01 12:32:15 +01:00
|
|
|
return tracking_marker_check_slide(C, co, nullptr, nullptr, nullptr);
|
2022-05-12 11:30:16 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
static SlideMarkerData *slide_marker_customdata(bContext *C, const wmEvent *event)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region = CTX_wm_region(C);
|
2012-07-26 22:41:40 +00:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
MovieTrackingTrack *track;
|
|
|
|
|
int width, height;
|
|
|
|
|
float co[2];
|
2023-03-01 12:32:15 +01:00
|
|
|
SlideMarkerData *customdata = nullptr;
|
2012-06-19 14:26:29 +00:00
|
|
|
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2022-05-12 11:35:56 +02:00
|
|
|
eSlideAction action;
|
|
|
|
|
int area, corner;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-07-26 22:41:40 +00:00
|
|
|
ED_space_clip_get_size(sc, &width, &height);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (width == 0 || height == 0) {
|
2023-03-01 12:32:15 +01:00
|
|
|
return nullptr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_clip_mouse_pos(sc, region, event->mval, co);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-05-13 17:14:28 +02:00
|
|
|
track = tracking_marker_check_slide(C, co, &area, &action, &corner);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (track != nullptr) {
|
2012-06-15 14:26:27 +00:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
|
2016-01-15 13:48:24 +05:00
|
|
|
customdata = create_slide_marker_data(
|
|
|
|
|
sc, track, marker, event, area, corner, action, width, height);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return customdata;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SlideMarkerData *slidedata = slide_marker_customdata(C, event);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (slidedata != nullptr) {
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
tracking_object->active_track = slidedata->track;
|
2023-03-01 12:32:15 +01:00
|
|
|
tracking_object->active_plane_track = nullptr;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
op->customdata = slidedata;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
clip_tracking_hide_cursor(C);
|
2011-11-07 12:55:18 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
|
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, nullptr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return OPERATOR_PASS_THROUGH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cancel_mouse_slide(SlideMarkerData *data)
|
|
|
|
|
{
|
2012-06-15 16:07:33 +00:00
|
|
|
MovieTrackingMarker *marker = data->marker;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
memcpy(marker->pattern_corners, data->old_corners, sizeof(marker->pattern_corners));
|
2012-06-15 16:07:33 +00:00
|
|
|
copy_v2_v2(marker->search_min, data->old_search_min);
|
|
|
|
|
copy_v2_v2(marker->search_max, data->old_search_max);
|
|
|
|
|
copy_v2_v2(marker->pos, data->old_pos);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
if (data->old_markers != nullptr) {
|
2016-01-15 13:48:24 +05:00
|
|
|
for (int a = 0; a < data->track->markersnr; a++) {
|
2012-06-15 16:07:33 +00:00
|
|
|
copy_v2_v2(data->track->markers[a].pos, data->old_markers[a]);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-10 12:46:18 +00:00
|
|
|
static void apply_mouse_slide(bContext *C, SlideMarkerData *data)
|
|
|
|
|
{
|
|
|
|
|
if (data->area == TRACK_AREA_POINT) {
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
|
|
|
|
const int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
|
2013-09-10 12:46:18 +00:00
|
|
|
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
|
2016-01-15 13:48:24 +05:00
|
|
|
if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) {
|
|
|
|
|
BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-10 12:46:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
static void free_slide_data(SlideMarkerData *data)
|
|
|
|
|
{
|
2023-03-01 12:32:15 +01:00
|
|
|
if (data->old_markers != nullptr) {
|
2012-06-15 16:07:33 +00:00
|
|
|
MEM_freeN(data->old_markers);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
MEM_freeN(data);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
SlideMarkerData *data = (SlideMarkerData *)op->customdata;
|
2011-11-07 12:55:18 +00:00
|
|
|
float dx, dy, mdelta[2];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (event->type) {
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_LEFTCTRLKEY:
|
|
|
|
|
case EVT_RIGHTCTRLKEY:
|
|
|
|
|
case EVT_LEFTSHIFTKEY:
|
|
|
|
|
case EVT_RIGHTSHIFTKEY:
|
2016-01-15 13:48:24 +05:00
|
|
|
if (data->action == SLIDE_ACTION_SIZE) {
|
2020-03-18 10:38:37 -06:00
|
|
|
if (ELEM(event->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) {
|
2012-03-25 23:19:21 +00:00
|
|
|
data->lock = event->val == KM_RELEASE;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-03-18 10:38:37 -06:00
|
|
|
if (ELEM(event->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) {
|
2012-03-25 23:19:21 +00:00
|
|
|
data->accurate = event->val == KM_PRESS;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2017-05-20 14:01:03 +10:00
|
|
|
ATTR_FALLTHROUGH;
|
2011-11-07 12:55:18 +00:00
|
|
|
case MOUSEMOVE:
|
2012-05-07 08:53:59 +00:00
|
|
|
mdelta[0] = event->mval[0] - data->mval[0];
|
|
|
|
|
mdelta[1] = event->mval[1] - data->mval[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
dx = mdelta[0] / data->width / sc->zoom;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (data->lock) {
|
2012-03-25 23:19:21 +00:00
|
|
|
dy = -dx / data->height * data->width;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
dy = mdelta[1] / data->height / sc->zoom;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (data->accurate) {
|
2016-01-15 13:48:24 +05:00
|
|
|
dx /= 5.0f;
|
|
|
|
|
dy /= 5.0f;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (data->area == TRACK_AREA_POINT) {
|
2022-05-13 13:08:23 +02:00
|
|
|
data->pos[0] += dx;
|
|
|
|
|
data->pos[1] += dy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, nullptr);
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&sc->clip->id, 0);
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2012-06-15 16:07:33 +00:00
|
|
|
else if (data->area == TRACK_AREA_PAT) {
|
2022-05-13 12:51:00 +02:00
|
|
|
if (data->action == SLIDE_ACTION_POS) {
|
2022-05-13 13:08:23 +02:00
|
|
|
float prev_pos[2];
|
|
|
|
|
copy_v2_v2(prev_pos, data->pos);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
data->pos[0] += dx;
|
|
|
|
|
data->pos[1] += dy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-15 18:31:46 +00:00
|
|
|
if (!slide_check_corners(data->corners)) {
|
2022-05-13 13:08:23 +02:00
|
|
|
copy_v2_v2(data->pos, prev_pos);
|
2012-06-15 18:31:46 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
/* Allow pattern to be arbitrary size and resize search area if needed. */
|
2022-05-12 10:58:22 +02:00
|
|
|
BKE_tracking_marker_clamp_search_size(data->marker);
|
2012-06-15 18:31:46 +00:00
|
|
|
}
|
|
|
|
|
else if (data->action == SLIDE_ACTION_TILT_SIZE) {
|
2022-05-13 13:08:23 +02:00
|
|
|
const float delta[2] = {dx, dy};
|
|
|
|
|
|
|
|
|
|
/* Slider position relative to the marker position using current state of pattern
|
|
|
|
|
* corners. */
|
|
|
|
|
float slider[2];
|
|
|
|
|
slide_marker_tilt_slider_relative(data->corners, slider);
|
|
|
|
|
|
|
|
|
|
/* Vector which connects marker position with the slider state at the current corners
|
|
|
|
|
* state.
|
|
|
|
|
* The coordinate is in the pixel space. */
|
|
|
|
|
float start_px[2];
|
|
|
|
|
copy_v2_v2(start_px, slider);
|
|
|
|
|
start_px[0] *= data->width;
|
|
|
|
|
start_px[1] *= data->height;
|
|
|
|
|
|
|
|
|
|
/* Vector which connects marker position with the slider state with the new mouse delta
|
|
|
|
|
* taken into account.
|
|
|
|
|
* The coordinate is in the pixel space. */
|
|
|
|
|
float end_px[2];
|
|
|
|
|
add_v2_v2v2(end_px, slider, delta);
|
|
|
|
|
end_px[0] *= data->width;
|
|
|
|
|
end_px[1] *= data->height;
|
2012-06-15 18:31:46 +00:00
|
|
|
|
2022-03-24 16:55:57 +01:00
|
|
|
float scale = 1.0f;
|
2022-05-13 13:08:23 +02:00
|
|
|
if (len_squared_v2(start_px) != 0.0f) {
|
|
|
|
|
scale = len_v2(end_px) / len_v2(start_px);
|
2012-06-15 18:31:46 +00:00
|
|
|
|
|
|
|
|
if (scale < 0.0f) {
|
|
|
|
|
scale = 0.0;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-06-15 18:31:46 +00:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
const float angle = -angle_signed_v2v2(start_px, end_px);
|
2012-06-15 18:31:46 +00:00
|
|
|
|
2012-11-04 07:18:29 +00:00
|
|
|
for (int a = 0; a < 4; a++) {
|
|
|
|
|
float vec[2];
|
2012-06-15 18:31:46 +00:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
mul_v2_fl(data->corners[a], scale);
|
2012-06-15 18:31:46 +00:00
|
|
|
|
2012-06-15 16:07:33 +00:00
|
|
|
copy_v2_v2(vec, data->corners[a]);
|
|
|
|
|
vec[0] *= data->width;
|
|
|
|
|
vec[1] *= data->height;
|
|
|
|
|
|
|
|
|
|
data->corners[a][0] = (vec[0] * cosf(angle) - vec[1] * sinf(angle)) / data->width;
|
|
|
|
|
data->corners[a][1] = (vec[1] * cosf(angle) + vec[0] * sinf(angle)) / data->height;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-06-15 16:07:33 +00:00
|
|
|
|
2022-05-12 10:58:22 +02:00
|
|
|
BKE_tracking_marker_clamp_search_size(data->marker);
|
2012-06-15 16:07:33 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-06-15 16:07:33 +00:00
|
|
|
else if (data->area == TRACK_AREA_SEARCH) {
|
|
|
|
|
if (data->action == SLIDE_ACTION_SIZE) {
|
2022-05-13 13:08:23 +02:00
|
|
|
data->min[0] -= dx;
|
|
|
|
|
data->min[1] += dy;
|
2012-06-15 16:07:33 +00:00
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
data->max[0] += dx;
|
|
|
|
|
data->max[1] -= dy;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-05-12 10:58:22 +02:00
|
|
|
BKE_tracking_marker_clamp_search_size(data->marker);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2022-05-13 10:42:28 +02:00
|
|
|
else if (data->action == SLIDE_ACTION_OFFSET) {
|
2022-05-13 13:08:23 +02:00
|
|
|
const float delta[2] = {dx, dy};
|
|
|
|
|
add_v2_v2(data->min, delta);
|
|
|
|
|
add_v2_v2(data->max, delta);
|
Planar tracking support for motion tracking
===========================================
Major list of changes done in tomato branch:
- Add a planar tracking implementation to libmv
This adds a new planar tracking implementation to libmv. The
tracker is based on Ceres[1], the new nonlinear minimizer that
myself and Sameer released from Google as open source. Since
the motion model is more involved, the interface is
different than the RegionTracker interface used previously
in Blender.
The start of a C API in libmv-capi.{cpp,h} is also included.
- Migrate from pat_{min,max} for markers to 4 corners representation
Convert markers in the movie clip editor / 2D tracker from using
pat_min and pat_max notation to using the a more general, 4-corner
representation.
There is still considerable porting work to do; in particular
sliding from preview widget does not work correct for rotated
markers.
All other areas should be ported to new representation:
* Added support of sliding individual corners. LMB slide + Ctrl
would scale the whole pattern
* S would scale the whole marker, S-S would scale pattern only
* Added support of marker's rotation which is currently rotates
only patterns around their centers or all markers around median,
Rotation or other non-translation/scaling transformation of search
area doesn't make sense.
* Track Preview widget would display transformed pattern which
libmv actually operates with.
- "Efficient Second-order Minimization" for the planar tracker
This implements the "Efficient Second-order Minimization"
scheme, as supported by the existing translation tracker.
This increases the amount of per-iteration work, but
decreases the number of iterations required to converge and
also increases the size of the basin of attraction for the
optimization.
- Remove the use of the legacy RegionTracker API from Blender,
and replaces it with the new TrackRegion API. This also
adds several features to the planar tracker in libmv:
* Do a brute-force initialization of tracking similar to "Hybrid"
mode in the stable release, but using all floats. This is slower
but more accurate. It is still necessary to evaluate if the
performance loss is worth it. In particular, this change is
necessary to support high bit depth imagery.
* Add support for masks over the search window. This is a step
towards supporting user-defined tracker masks. The tracker masks
will make it easy for users to make a mask for e.g. a ball.
Not exposed into interface yet/
* Add Pearson product moment correlation coefficient checking (aka
"Correlation" in the UI. This causes tracking failure if the
tracked patch is not linearly related to the template.
* Add support for warping a few points in addition to the supplied
points. This is useful because the tracking code deliberately
does not expose the underlying warp representation. Instead,
warps are specified in an aparametric way via the correspondences.
- Replace the old style tracker configuration panel with the
new planar tracking panel. From a users perspective, this means:
* The old "tracking algorithm" picker is gone. There is only 1
algorithm now. We may revisit this later, but I would much
prefer to have only 1 algorithm. So far no optimization work
has been done so the speed is not there yet.
* There is now a dropdown to select the motion model. Choices:
* Translation
* Translation, rotation
* Translation, scale
* Translation, rotation, scale
* Affine
* Perspective
* The old "Hybrid" mode is gone; instead there is a toggle to
enable or disable translation-only tracker initialization. This
is the equivalent of the hyrbid mode before, but rewritten to work
with the new planar tracking modes.
* The pyramid levels setting is gone. At a future date, the planar
tracker will decide to use pyramids or not automatically. The
pyramid setting was ultimately a mistake; with the brute force
initialization it is unnecessary.
- Add light-normalized tracking
Added the ability to normalize patterns by their average value while
tracking, to make them invariant to global illumination changes.
Additional details could be found at wiki page [2]
[1] http://code.google.com/p/ceres-solver
[2] http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Motion_Tracker
2012-06-10 15:28:19 +00:00
|
|
|
|
2022-05-13 10:42:28 +02:00
|
|
|
BKE_tracking_marker_clamp_search_position(data->marker);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
data->marker->flag &= ~MARKER_TRACKED;
|
|
|
|
|
|
2022-05-13 13:08:23 +02:00
|
|
|
copy_v2_v2_int(data->mval, event->mval);
|
|
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, nullptr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
break;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
case LEFTMOUSE:
|
|
|
|
|
if (event->val == KM_RELEASE) {
|
2023-03-01 12:32:15 +01:00
|
|
|
apply_mouse_slide(C, data);
|
|
|
|
|
free_slide_data(data);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
clip_tracking_show_cursor(C);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
2020-03-18 10:38:37 -06:00
|
|
|
case EVT_ESCKEY:
|
2023-03-01 12:32:15 +01:00
|
|
|
cancel_mouse_slide(data);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
free_slide_data(data);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
clip_tracking_show_cursor(C);
|
|
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
return OPERATOR_CANCELLED;
|
2025-03-31 23:48:29 +00:00
|
|
|
default: {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_slide_marker(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Slide Marker";
|
|
|
|
|
ot->description = "Slide marker areas";
|
|
|
|
|
ot->idname = "CLIP_OT_slide_marker";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-06-07 16:36:19 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = slide_marker_invoke;
|
|
|
|
|
ot->modal = slide_marker_modal;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2019-05-29 00:48:48 +10:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR_XY | OPTYPE_BLOCKING;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
|
RNA_def_float_vector(ot->srna,
|
|
|
|
|
"offset",
|
|
|
|
|
2,
|
2023-03-01 12:32:15 +01:00
|
|
|
nullptr,
|
2011-11-07 12:55:18 +00:00
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX,
|
2016-01-15 13:48:24 +05:00
|
|
|
"Offset",
|
2020-12-24 13:11:22 -06:00
|
|
|
"Offset in floating-point units, 1.0 is the width and height of the image",
|
2016-01-15 13:48:24 +05:00
|
|
|
-FLT_MAX,
|
|
|
|
|
FLT_MAX);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Clear Track Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus clear_track_path_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2016-01-15 14:02:26 +05:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
2023-03-01 12:32:15 +01:00
|
|
|
const eTrackClearAction action = eTrackClearAction(RNA_enum_get(op->ptr, "action"));
|
2016-01-15 14:02:26 +05:00
|
|
|
const bool clear_active = RNA_boolean_get(op->ptr, "clear_active");
|
2022-05-12 10:16:33 +02:00
|
|
|
const int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
if (clear_active) {
|
2023-03-01 12:32:15 +01:00
|
|
|
if (tracking_object->active_track != nullptr) {
|
2022-10-07 11:32:21 +02:00
|
|
|
BKE_tracking_track_path_clear(tracking_object->active_track, framenr, action);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 14:02:26 +05:00
|
|
|
else {
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2016-01-15 14:02:26 +05:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track)) {
|
|
|
|
|
BKE_tracking_track_path_clear(track, framenr, action);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2012-01-09 20:18:48 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
BKE_tracking_dopesheet_tag_update(&clip->tracking);
|
2016-01-15 14:02:26 +05:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
return OPERATOR_FINISHED;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
void CLIP_OT_clear_track_path(wmOperatorType *ot)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem clear_path_actions[] = {
|
2020-10-24 11:42:17 -07:00
|
|
|
{TRACK_CLEAR_UPTO, "UPTO", 0, "Clear Up To", "Clear path up to current frame"},
|
2016-01-15 14:02:26 +05:00
|
|
|
{TRACK_CLEAR_REMAINED,
|
|
|
|
|
"REMAINED",
|
|
|
|
|
0,
|
2020-10-24 11:42:17 -07:00
|
|
|
"Clear Remained",
|
2016-01-15 14:02:26 +05:00
|
|
|
"Clear path at remaining frames (after current)"},
|
2020-10-24 11:42:17 -07:00
|
|
|
{TRACK_CLEAR_ALL, "ALL", 0, "Clear All", "Clear the whole path"},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2016-01-15 14:02:26 +05:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Clear Track Path";
|
|
|
|
|
ot->description = "Clear tracks after/before current position or clear the whole track";
|
|
|
|
|
ot->idname = "CLIP_OT_clear_track_path";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->exec = clear_track_path_exec;
|
|
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* properties */
|
|
|
|
|
RNA_def_enum(ot->srna,
|
|
|
|
|
"action",
|
|
|
|
|
clear_path_actions,
|
|
|
|
|
TRACK_CLEAR_REMAINED,
|
|
|
|
|
"Action",
|
|
|
|
|
"Clear action to execute");
|
|
|
|
|
RNA_def_boolean(ot->srna,
|
|
|
|
|
"clear_active",
|
2023-07-22 11:36:59 +10:00
|
|
|
false,
|
2016-01-15 14:02:26 +05:00
|
|
|
"Clear Active",
|
|
|
|
|
"Clear active track only instead of all selected tracks");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Disable Markers Operator
|
|
|
|
|
* \{ */
|
2016-01-15 14:02:26 +05:00
|
|
|
|
2016-01-27 14:27:37 +01:00
|
|
|
enum {
|
|
|
|
|
MARKER_OP_DISABLE = 0,
|
|
|
|
|
MARKER_OP_ENABLE = 1,
|
|
|
|
|
MARKER_OP_TOGGLE = 2,
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus disable_markers_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
|
|
|
|
const int action = RNA_enum_get(op->ptr, "action");
|
|
|
|
|
const int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2016-01-15 14:02:26 +05:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
|
|
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
|
2016-01-27 14:27:37 +01:00
|
|
|
switch (action) {
|
|
|
|
|
case MARKER_OP_DISABLE:
|
|
|
|
|
marker->flag |= MARKER_DISABLED;
|
|
|
|
|
break;
|
|
|
|
|
case MARKER_OP_ENABLE:
|
|
|
|
|
marker->flag &= ~MARKER_DISABLED;
|
|
|
|
|
break;
|
|
|
|
|
case MARKER_OP_TOGGLE:
|
|
|
|
|
marker->flag ^= MARKER_DISABLED;
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 14:02:26 +05:00
|
|
|
}
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&clip->id, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
void CLIP_OT_disable_markers(wmOperatorType *ot)
|
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem actions_items[] = {
|
2016-01-27 14:27:37 +01:00
|
|
|
{MARKER_OP_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
|
|
|
|
|
{MARKER_OP_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
|
|
|
|
|
{MARKER_OP_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2016-01-15 14:02:26 +05:00
|
|
|
};
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Disable Markers";
|
|
|
|
|
ot->description = "Disable/enable selected markers";
|
|
|
|
|
ot->idname = "CLIP_OT_disable_markers";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->exec = disable_markers_exec;
|
|
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* properties */
|
|
|
|
|
RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Disable action to execute");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Hide Tracks Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus hide_tracks_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2016-01-15 14:02:26 +05:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2022-10-05 17:41:58 +02:00
|
|
|
const int unselected = RNA_boolean_get(op->ptr, "unselected");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* Hide point tracks. */
|
2022-10-04 17:39:57 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2016-01-15 14:02:26 +05:00
|
|
|
if (unselected == 0 && TRACK_VIEW_SELECTED(sc, track)) {
|
|
|
|
|
track->flag |= TRACK_HIDDEN;
|
|
|
|
|
}
|
|
|
|
|
else if (unselected == 1 && !TRACK_VIEW_SELECTED(sc, track)) {
|
|
|
|
|
track->flag |= TRACK_HIDDEN;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 14:02:26 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
const MovieTrackingTrack *active_track = tracking_object->active_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
if (active_track != nullptr && active_track->flag & TRACK_HIDDEN) {
|
|
|
|
|
tracking_object->active_track = nullptr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
/* Hide place tracks. */
|
2022-10-04 17:39:57 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
|
2016-01-15 14:02:26 +05:00
|
|
|
if (unselected == 0 && plane_track->flag & SELECT) {
|
|
|
|
|
plane_track->flag |= PLANE_TRACK_HIDDEN;
|
|
|
|
|
}
|
|
|
|
|
else if (unselected == 1 && (plane_track->flag & SELECT) == 0) {
|
|
|
|
|
plane_track->flag |= PLANE_TRACK_HIDDEN;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 14:02:26 +05:00
|
|
|
}
|
2022-10-04 17:39:57 +02:00
|
|
|
|
|
|
|
|
const MovieTrackingPlaneTrack *active_plane_track = tracking_object->active_plane_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
if (active_plane_track != nullptr && active_plane_track->flag & TRACK_HIDDEN) {
|
|
|
|
|
tracking_object->active_plane_track = nullptr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
BKE_tracking_dopesheet_tag_update(tracking);
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_hide_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Hide Tracks";
|
|
|
|
|
ot->description = "Hide selected tracks";
|
|
|
|
|
ot->idname = "CLIP_OT_hide_tracks";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = hide_tracks_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* properties */
|
2023-07-22 11:36:59 +10:00
|
|
|
RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected tracks");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Hide Tracks Clear Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus hide_tracks_clear_exec(bContext *C, wmOperator * /*op*/)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Unhide point tracks. */
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2012-03-25 23:19:21 +00:00
|
|
|
track->flag &= ~TRACK_HIDDEN;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Unhide plane tracks. */
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
|
2014-03-06 20:07:14 +06:00
|
|
|
plane_track->flag &= ~PLANE_TRACK_HIDDEN;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
BKE_tracking_dopesheet_tag_update(&clip->tracking);
|
2012-05-03 23:15:01 +00:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, nullptr);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_hide_tracks_clear(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Hide Tracks Clear";
|
|
|
|
|
ot->description = "Clear hide selected tracks";
|
|
|
|
|
ot->idname = "CLIP_OT_hide_tracks_clear";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = hide_tracks_clear_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Frame Jump Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2019-05-07 17:07:04 +02:00
|
|
|
static bool frame_jump_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
2023-03-01 12:32:15 +01:00
|
|
|
return space_clip != nullptr;
|
2019-05-07 17:07:04 +02:00
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus frame_jump_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2012-03-25 23:19:21 +00:00
|
|
|
int pos = RNA_enum_get(op->ptr, "position");
|
2011-11-07 12:55:18 +00:00
|
|
|
int delta;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-10 19:59:02 +00:00
|
|
|
if (pos <= 1) { /* jump to path */
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingTrack *active_track = tracking_object->active_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
if (active_track == nullptr) {
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
delta = pos == 1 ? 1 : -1;
|
2022-06-30 18:36:42 +02:00
|
|
|
while (sc->user.framenr + delta >= scene->r.sfra && sc->user.framenr + delta <= scene->r.efra)
|
|
|
|
|
{
|
2016-01-15 13:48:24 +05:00
|
|
|
int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr + delta);
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(active_track, framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
if (marker == nullptr || marker->flag & MARKER_DISABLED) {
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
sc->user.framenr += delta;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-02-04 01:23:48 +01:00
|
|
|
else { /* to failed frame */
|
2022-10-04 17:39:57 +02:00
|
|
|
if (tracking_object->reconstruction.flag & TRACKING_RECONSTRUCTED) {
|
2016-01-15 13:48:24 +05:00
|
|
|
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
delta = pos == 3 ? 1 : -1;
|
2016-01-15 13:48:24 +05:00
|
|
|
framenr += delta;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-06-30 18:36:42 +02:00
|
|
|
while (framenr + delta >= scene->r.sfra && framenr + delta <= scene->r.efra) {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieReconstructedCamera *cam = BKE_tracking_camera_get_reconstructed(
|
2022-10-04 17:39:57 +02:00
|
|
|
tracking, tracking_object, framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
if (cam == nullptr) {
|
2016-01-15 13:48:24 +05:00
|
|
|
sc->user.framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, framenr);
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
framenr += delta;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-06-30 18:36:42 +02:00
|
|
|
if (scene->r.cfra != sc->user.framenr) {
|
|
|
|
|
scene->r.cfra = sc->user.framenr;
|
2022-02-03 21:32:50 +11:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_frame_jump(wmOperatorType *ot)
|
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem position_items[] = {
|
2016-01-15 13:48:24 +05:00
|
|
|
{0, "PATHSTART", 0, "Path Start", "Jump to start of current path"},
|
|
|
|
|
{1, "PATHEND", 0, "Path End", "Jump to end of current path"},
|
|
|
|
|
{2, "FAILEDPREV", 0, "Previous Failed", "Jump to previous failed frame"},
|
|
|
|
|
{2, "FAILNEXT", 0, "Next Failed", "Jump to next failed frame"},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2011-11-07 12:55:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Jump to Frame";
|
|
|
|
|
ot->description = "Jump to special frame";
|
|
|
|
|
ot->idname = "CLIP_OT_frame_jump";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = frame_jump_exec;
|
2019-05-07 17:07:04 +02:00
|
|
|
ot->poll = frame_jump_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* properties */
|
2016-01-15 13:48:24 +05:00
|
|
|
RNA_def_enum(ot->srna, "position", position_items, 0, "Position", "Position to jump to");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Join Tracks Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus join_tracks_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
|
|
|
|
MovieTrackingStabilization *stabilization = &tracking->stabilization;
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
bool update_stabilization = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingTrack *active_track = tracking_object->active_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
if (active_track == nullptr) {
|
2011-11-07 12:55:18 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "No active track to join to");
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-11-23 17:00:21 +01:00
|
|
|
blender::Set<MovieTrackingPlaneTrack *> point_tracks;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
|
|
|
|
if (TRACK_VIEW_SELECTED(sc, track) && track != active_track) {
|
|
|
|
|
BKE_tracking_tracks_join(tracking, active_track, track);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
if (track->flag & TRACK_USE_2D_STAB) {
|
|
|
|
|
update_stabilization = true;
|
2022-10-07 11:32:21 +02:00
|
|
|
if ((active_track->flag & TRACK_USE_2D_STAB) == 0) {
|
|
|
|
|
active_track->flag |= TRACK_USE_2D_STAB;
|
2017-03-02 00:16:36 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2022-10-07 11:32:21 +02:00
|
|
|
stabilization->tot_track--;
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
}
|
2022-10-07 11:32:21 +02:00
|
|
|
BLI_assert(0 <= stabilization->tot_track);
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
}
|
|
|
|
|
if (track->flag & TRACK_USE_2D_STAB_ROT) {
|
|
|
|
|
update_stabilization = true;
|
2022-10-07 11:32:21 +02:00
|
|
|
if ((active_track->flag & TRACK_USE_2D_STAB_ROT) == 0) {
|
|
|
|
|
active_track->flag |= TRACK_USE_2D_STAB_ROT;
|
2017-03-02 00:16:36 +11:00
|
|
|
}
|
|
|
|
|
else {
|
2022-10-07 11:32:21 +02:00
|
|
|
stabilization->tot_rot_track--;
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
}
|
2022-10-07 11:32:21 +02:00
|
|
|
BLI_assert(0 <= stabilization->tot_rot_track);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
|
2016-01-27 16:20:17 +01:00
|
|
|
if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
|
2022-10-07 11:32:21 +02:00
|
|
|
BKE_tracking_plane_track_replace_point_track(plane_track, track, active_track);
|
2016-01-27 16:20:17 +01:00
|
|
|
if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) {
|
2024-11-23 17:00:21 +01:00
|
|
|
point_tracks.add(plane_track);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-01-27 16:20:17 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_free(track);
|
2022-10-07 11:32:21 +02:00
|
|
|
BLI_freelinkN(&tracking_object->tracks, track);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Rework 2D stabilizator
See this page for motivation and description of concepts:
https://github.com/Ichthyostega/blender/wiki
See this video for UI explanation and demonstration of usage
http://vimeo.com/blenderHack/stabilizerdemo
This proposal attempts to improve usability of Blender's image stabilization
feature for real-world footage esp. with moving and panning camera. It builds
upon the feature tracking to get a measurement of 2D image movement.
- Use a weighted average of movement contributions (instead of a median).
- Allow for rotation compensation and zoom (image scale) compensation.
- Allow to pick a different set of tracks for translation and for
rotation/zoom.
- Treat translation / rotation / zoom contributions systematically in a
similar way.
- Improve handling of partial tracking data with gaps and varying
start / end points.
- Have a user definable anchor frame and interpolate / extrapolate data to
avoid jumping back to "neutral" position when no tracking data is available.
- Support for travelling and panning shots by including an //intended//
position/rotation/zoom ("target position"). The idea is for these parameters
to be //animated// by the user, in order to supply an smooth, intended
camera movement. This way, we can keep the image content roughly in frame
even when moving completely away from the initial view.
A known shortcoming is that the pivot point for rotation compensation is set to
the translation compensated image center. This can produce spurious rotation on
travelling shots, which needs to be compensated manually (by animating the
target rotation parameter). There are several possible ways to address that
problem, yet all of them are considered beyond the scope of this improvement
proposal for now.
Own modifications:
- Restrict line length, it's really handy for split-view editing
- In motion tracking we prefer fully human-readable comments, meaning we
don't use doxygen with it's weird markup and comments are supposed to
start with capital and end with a full stop,
- Add explicit comparison of pointer to NULL.
Reviewers: sergey
Subscribers: kusi, kdawg, forest-house, mardy, Samoth, plasmasolutions, willolis, sebastian_k, hype, enetheru, sunboy, jta, leon_cheung
Maniphest Tasks: T49036
Differential Revision: https://developer.blender.org/D583
2016-08-16 10:32:55 +02:00
|
|
|
if (update_stabilization) {
|
|
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-27 16:20:17 +01:00
|
|
|
int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2024-11-23 17:00:21 +01:00
|
|
|
for (MovieTrackingPlaneTrack *plane_track : point_tracks) {
|
2016-01-27 16:20:17 +01:00
|
|
|
BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-24 14:54:54 +02:00
|
|
|
DEG_id_tag_update(&clip->id, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_join_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Join Tracks";
|
|
|
|
|
ot->description = "Join selected tracks";
|
|
|
|
|
ot->idname = "CLIP_OT_join_tracks";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = join_tracks_exec;
|
2012-06-07 16:36:19 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Average Tracks Operator
|
|
|
|
|
* \{ */
|
2019-11-28 11:14:32 +01:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus average_tracks_exec(bContext *C, wmOperator *op)
|
2019-11-28 11:14:32 +01:00
|
|
|
{
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2019-11-28 11:14:32 +01:00
|
|
|
|
|
|
|
|
/* Collect source tracks. */
|
|
|
|
|
int num_source_tracks;
|
|
|
|
|
MovieTrackingTrack **source_tracks = BKE_tracking_selected_tracks_in_active_object(
|
|
|
|
|
tracking, &num_source_tracks);
|
|
|
|
|
if (num_source_tracks == 0) {
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create new empty track, which will be the averaged result.
|
2023-10-19 18:53:16 +11:00
|
|
|
* Makes it simple to average all selection to it. */
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingTrack *result_track = BKE_tracking_track_add_empty(tracking,
|
|
|
|
|
&tracking_object->tracks);
|
2019-11-28 11:14:32 +01:00
|
|
|
|
|
|
|
|
/* Perform averaging. */
|
|
|
|
|
BKE_tracking_tracks_average(result_track, source_tracks, num_source_tracks);
|
|
|
|
|
|
|
|
|
|
const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
|
|
|
|
|
if (!keep_original) {
|
|
|
|
|
for (int i = 0; i < num_source_tracks; i++) {
|
|
|
|
|
clip_delete_track(C, clip, source_tracks[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Update selection, making the result track active and selected. */
|
|
|
|
|
/* TODO(sergey): Should become some sort of utility function available for all operators. */
|
|
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
BKE_tracking_track_select(&tracking_object->tracks, result_track, TRACK_AREA_ALL, false);
|
2022-10-07 11:32:21 +02:00
|
|
|
BKE_tracking_plane_tracks_deselect_all(&tracking_object->plane_tracks);
|
2019-11-28 11:14:32 +01:00
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
tracking_object->active_track = result_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
tracking_object->active_plane_track = nullptr;
|
2019-11-28 11:14:32 +01:00
|
|
|
|
|
|
|
|
/* Inform the dependency graph and interface about changes. */
|
|
|
|
|
DEG_id_tag_update(&clip->id, 0);
|
|
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
|
|
|
|
|
|
|
|
|
/* Free memory. */
|
|
|
|
|
MEM_freeN(source_tracks);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus average_tracks_invoke(bContext *C,
|
|
|
|
|
wmOperator *op,
|
|
|
|
|
const wmEvent * /*event*/)
|
2019-11-28 11:14:32 +01:00
|
|
|
{
|
|
|
|
|
PropertyRNA *prop_keep_original = RNA_struct_find_property(op->ptr, "keep_original");
|
|
|
|
|
if (!RNA_property_is_set(op->ptr, prop_keep_original)) {
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
|
|
|
|
|
|
|
|
|
const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking);
|
|
|
|
|
|
|
|
|
|
if (num_selected_tracks == 1) {
|
|
|
|
|
RNA_property_boolean_set(op->ptr, prop_keep_original, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return average_tracks_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_average_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* Identifiers. */
|
|
|
|
|
ot->name = "Average Tracks";
|
|
|
|
|
ot->description = "Average selected tracks into active";
|
|
|
|
|
ot->idname = "CLIP_OT_average_tracks";
|
|
|
|
|
|
|
|
|
|
/* API callbacks. */
|
|
|
|
|
ot->exec = average_tracks_exec;
|
|
|
|
|
ot->invoke = average_tracks_invoke;
|
|
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
|
|
|
|
|
|
|
|
|
/* Flags. */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
|
|
|
|
|
/* Properties. */
|
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
prop = RNA_def_boolean(ot->srna, "keep_original", true, "Keep Original", "Keep original tracks");
|
2022-09-15 11:13:33 +02:00
|
|
|
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
|
2019-11-28 11:14:32 +01:00
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Lock Tracks Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2016-01-27 14:27:37 +01:00
|
|
|
enum {
|
|
|
|
|
TRACK_ACTION_LOCK = 0,
|
|
|
|
|
TRACK_ACTION_UNLOCK = 1,
|
|
|
|
|
TRACK_ACTION_TOGGLE = 2,
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus lock_tracks_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
|
|
|
|
const int action = RNA_enum_get(op->ptr, "action");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2012-03-24 06:38:07 +00:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track)) {
|
2016-01-27 14:27:37 +01:00
|
|
|
switch (action) {
|
|
|
|
|
case TRACK_ACTION_LOCK:
|
|
|
|
|
track->flag |= TRACK_LOCKED;
|
|
|
|
|
break;
|
|
|
|
|
case TRACK_ACTION_UNLOCK:
|
|
|
|
|
track->flag &= ~TRACK_LOCKED;
|
|
|
|
|
break;
|
|
|
|
|
case TRACK_ACTION_TOGGLE:
|
|
|
|
|
track->flag ^= TRACK_LOCKED;
|
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EVALUATED, clip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_lock_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem actions_items[] = {
|
2016-01-27 14:27:37 +01:00
|
|
|
{TRACK_ACTION_LOCK, "LOCK", 0, "Lock", "Lock selected tracks"},
|
|
|
|
|
{TRACK_ACTION_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock selected tracks"},
|
|
|
|
|
{TRACK_ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle locked flag for selected tracks"},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2011-11-07 12:55:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Lock Tracks";
|
|
|
|
|
ot->description = "Lock/unlock selected tracks";
|
|
|
|
|
ot->idname = "CLIP_OT_lock_tracks";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = lock_tracks_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* properties */
|
2016-01-15 13:48:24 +05:00
|
|
|
RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Lock action to execute");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Set Keyframe Operator
|
|
|
|
|
* \{ */
|
2012-07-26 09:50:27 +00:00
|
|
|
|
2016-01-27 14:27:37 +01:00
|
|
|
enum {
|
|
|
|
|
SOLVER_KEYFRAME_A = 0,
|
|
|
|
|
SOLVER_KEYFRAME_B = 1,
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus set_solver_keyframe_exec(bContext *C, wmOperator *op)
|
2012-07-26 09:50:27 +00:00
|
|
|
{
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-05 18:01:29 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
|
|
|
|
const int keyframe = RNA_enum_get(op->ptr, "keyframe");
|
|
|
|
|
const int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr);
|
2012-07-26 09:50:27 +00:00
|
|
|
|
2016-01-27 14:27:37 +01:00
|
|
|
if (keyframe == SOLVER_KEYFRAME_A) {
|
2022-10-05 18:01:29 +02:00
|
|
|
tracking_object->keyframe1 = framenr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2016-01-15 14:02:26 +05:00
|
|
|
else {
|
2022-10-05 18:01:29 +02:00
|
|
|
tracking_object->keyframe2 = framenr;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
void CLIP_OT_set_solver_keyframe(wmOperatorType *ot)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem keyframe_items[] = {
|
2016-01-27 14:27:37 +01:00
|
|
|
{SOLVER_KEYFRAME_A, "KEYFRAME_A", 0, "Keyframe A", ""},
|
|
|
|
|
{SOLVER_KEYFRAME_B, "KEYFRAME_B", 0, "Keyframe B", ""},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2016-01-15 14:02:26 +05:00
|
|
|
};
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* identifiers */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->name = "Set Solver Keyframe";
|
|
|
|
|
ot->description = "Set keyframe used by solver";
|
|
|
|
|
ot->idname = "CLIP_OT_set_solver_keyframe";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->exec = set_solver_keyframe_exec;
|
|
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2016-01-15 14:02:26 +05:00
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
|
RNA_def_enum(ot->srna, "keyframe", keyframe_items, 0, "Keyframe", "Keyframe to set");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Track Copy Color Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus track_copy_color_exec(bContext *C, wmOperator * /*op*/)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
MovieTrackingTrack *active_track = tracking_object->active_track;
|
2023-03-01 12:32:15 +01:00
|
|
|
if (active_track == nullptr) {
|
2016-01-15 14:02:26 +05:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
|
|
|
|
if (TRACK_VIEW_SELECTED(sc, track) && track != active_track) {
|
2016-01-15 14:02:26 +05:00
|
|
|
track->flag &= ~TRACK_CUSTOMCOLOR;
|
2022-10-07 11:32:21 +02:00
|
|
|
if (active_track->flag & TRACK_CUSTOMCOLOR) {
|
|
|
|
|
copy_v3_v3(track->color, active_track->color);
|
2016-01-15 14:02:26 +05:00
|
|
|
track->flag |= TRACK_CUSTOMCOLOR;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2019-05-23 10:02:37 +02:00
|
|
|
DEG_id_tag_update(&clip->id, 0);
|
2016-01-15 14:02:26 +05:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
|
|
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
void CLIP_OT_track_copy_color(wmOperatorType *ot)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->name = "Copy Color";
|
|
|
|
|
ot->description = "Copy color to all selected tracks";
|
|
|
|
|
ot->idname = "CLIP_OT_track_copy_color";
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2016-01-15 14:02:26 +05:00
|
|
|
ot->exec = track_copy_color_exec;
|
|
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Clean Tracks Operator
|
|
|
|
|
* \{ */
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2014-04-11 11:25:41 +10:00
|
|
|
static bool is_track_clean(MovieTrackingTrack *track, int frames, int del)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2014-04-11 11:25:41 +10:00
|
|
|
bool ok = true;
|
2016-01-15 13:48:24 +05:00
|
|
|
int prev = -1, count = 0;
|
2023-03-01 12:32:15 +01:00
|
|
|
MovieTrackingMarker *markers = track->markers, *new_markers = nullptr;
|
2012-03-25 23:19:21 +00:00
|
|
|
int start_disabled = 0;
|
|
|
|
|
int markersnr = track->markersnr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (del) {
|
2025-03-05 16:35:09 +01:00
|
|
|
new_markers = MEM_calloc_arrayN<MovieTrackingMarker>(markersnr, "track cleaned markers");
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
for (int a = 0; a < markersnr; a++) {
|
2012-03-25 23:19:21 +00:00
|
|
|
int end = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
if (prev == -1) {
|
2016-01-15 13:48:24 +05:00
|
|
|
if ((markers[a].flag & MARKER_DISABLED) == 0) {
|
2012-03-25 23:19:21 +00:00
|
|
|
prev = a;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
|
|
|
|
else {
|
2012-03-25 23:19:21 +00:00
|
|
|
start_disabled = 1;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (prev >= 0) {
|
2012-05-07 08:53:59 +00:00
|
|
|
end = a == markersnr - 1;
|
|
|
|
|
end |= (a < markersnr - 1) && (markers[a].framenr != markers[a + 1].framenr - 1 ||
|
|
|
|
|
markers[a].flag & MARKER_DISABLED);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (end) {
|
2012-03-25 23:19:21 +00:00
|
|
|
int segok = 1, len = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (a != prev && markers[a].framenr != markers[a - 1].framenr + 1) {
|
2012-05-07 08:53:59 +00:00
|
|
|
len = a - prev;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
|
|
|
|
else if (markers[a].flag & MARKER_DISABLED) {
|
2012-05-07 08:53:59 +00:00
|
|
|
len = a - prev;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
len = a - prev + 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (frames) {
|
|
|
|
|
if (len < frames) {
|
2012-03-25 23:19:21 +00:00
|
|
|
segok = 0;
|
2023-07-22 11:36:59 +10:00
|
|
|
ok = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!del) {
|
2011-11-07 12:55:18 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (del) {
|
|
|
|
|
if (segok) {
|
2012-03-25 23:19:21 +00:00
|
|
|
int t = len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (markers[a].flag & MARKER_DISABLED) {
|
2011-11-07 12:55:18 +00:00
|
|
|
t++;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Place disabled marker in front of current segment. */
|
2012-03-24 06:38:07 +00:00
|
|
|
if (start_disabled) {
|
2016-01-15 13:48:24 +05:00
|
|
|
memcpy(new_markers + count, markers + prev, sizeof(MovieTrackingMarker));
|
2011-11-07 12:55:18 +00:00
|
|
|
new_markers[count].framenr--;
|
2012-03-25 23:19:21 +00:00
|
|
|
new_markers[count].flag |= MARKER_DISABLED;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
count++;
|
2012-03-25 23:19:21 +00:00
|
|
|
start_disabled = 0;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
memcpy(new_markers + count, markers + prev, t * sizeof(MovieTrackingMarker));
|
2012-03-25 23:19:21 +00:00
|
|
|
count += t;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else if (markers[a].flag & MARKER_DISABLED) {
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Current segment which would be deleted was finished by
|
|
|
|
|
* disabled marker, so next segment should be started from
|
|
|
|
|
* disabled marker.
|
|
|
|
|
*/
|
2012-03-25 23:19:21 +00:00
|
|
|
start_disabled = 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
prev = -1;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-03-05 12:00:25 +01:00
|
|
|
if (del && count == 0) {
|
2023-07-22 11:36:59 +10:00
|
|
|
ok = false;
|
2018-01-08 14:10:50 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (del) {
|
2011-11-07 12:55:18 +00:00
|
|
|
MEM_freeN(track->markers);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (count) {
|
2012-03-25 23:19:21 +00:00
|
|
|
track->markers = new_markers;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-03-01 12:32:15 +01:00
|
|
|
track->markers = nullptr;
|
2011-11-07 12:55:18 +00:00
|
|
|
MEM_freeN(new_markers);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:19:21 +00:00
|
|
|
track->markersnr = count;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus clean_tracks_exec(bContext *C, wmOperator *op)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2012-03-25 23:19:21 +00:00
|
|
|
int frames = RNA_int_get(op->ptr, "frames");
|
|
|
|
|
int action = RNA_enum_get(op->ptr, "action");
|
|
|
|
|
float error = RNA_float_get(op->ptr, "error");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (error && action == TRACKING_CLEAN_DELETE_SEGMENT) {
|
2012-03-25 23:19:21 +00:00
|
|
|
action = TRACKING_CLEAN_DELETE_TRACK;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2016-01-15 13:48:24 +05:00
|
|
|
if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) {
|
2013-03-17 10:26:23 +00:00
|
|
|
bool ok;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 22:52:53 +11:00
|
|
|
ok = is_track_clean(track, frames, action == TRACKING_CLEAN_DELETE_SEGMENT) &&
|
2016-01-15 13:48:24 +05:00
|
|
|
((error == 0.0f) || (track->flag & TRACK_HAS_BUNDLE) == 0 || (track->error < error));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
if (!ok) {
|
2012-03-25 23:19:21 +00:00
|
|
|
if (action == TRACKING_CLEAN_SELECT) {
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2012-03-25 23:19:21 +00:00
|
|
|
else if (action == TRACKING_CLEAN_DELETE_TRACK) {
|
2022-10-04 17:39:57 +02:00
|
|
|
if (track == tracking_object->active_track) {
|
2023-03-01 12:32:15 +01:00
|
|
|
tracking_object->active_track = nullptr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_free(track);
|
2022-10-04 17:39:57 +02:00
|
|
|
BLI_freelinkN(&tracking_object->tracks, track);
|
2023-03-01 12:32:15 +01:00
|
|
|
track = nullptr;
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
/* Happens when all tracking segments are not long enough. */
|
2012-03-25 23:19:21 +00:00
|
|
|
if (track && track->markersnr == 0) {
|
2022-10-04 17:39:57 +02:00
|
|
|
if (track == tracking_object->active_track) {
|
2023-03-01 12:32:15 +01:00
|
|
|
tracking_object->active_track = nullptr;
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_free(track);
|
2022-10-04 17:39:57 +02:00
|
|
|
BLI_freelinkN(&tracking_object->tracks, track);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-23 10:02:37 +02:00
|
|
|
DEG_id_tag_update(&clip->id, 0);
|
2013-07-28 07:11:00 +00:00
|
|
|
BKE_tracking_dopesheet_tag_update(tracking);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus clean_tracks_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
2011-11-07 12:55:18 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!RNA_struct_property_is_set(op->ptr, "frames")) {
|
2011-11-07 12:55:18 +00:00
|
|
|
RNA_int_set(op->ptr, "frames", clip->tracking.settings.clean_frames);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!RNA_struct_property_is_set(op->ptr, "error")) {
|
2011-11-07 12:55:18 +00:00
|
|
|
RNA_float_set(op->ptr, "error", clip->tracking.settings.clean_error);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-15 13:48:24 +05:00
|
|
|
if (!RNA_struct_property_is_set(op->ptr, "action")) {
|
2011-11-07 12:55:18 +00:00
|
|
|
RNA_enum_set(op->ptr, "action", clip->tracking.settings.clean_action);
|
2016-01-15 13:48:24 +05:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
return clean_tracks_exec(C, op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_clean_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem actions_items[] = {
|
2016-01-15 13:48:24 +05:00
|
|
|
{TRACKING_CLEAN_SELECT, "SELECT", 0, "Select", "Select unclean tracks"},
|
|
|
|
|
{TRACKING_CLEAN_DELETE_TRACK, "DELETE_TRACK", 0, "Delete Track", "Delete unclean tracks"},
|
|
|
|
|
{TRACKING_CLEAN_DELETE_SEGMENT,
|
|
|
|
|
"DELETE_SEGMENTS",
|
|
|
|
|
0,
|
|
|
|
|
"Delete Segments",
|
|
|
|
|
"Delete unclean segments of tracks"},
|
2023-03-01 12:32:15 +01:00
|
|
|
{0, nullptr, 0, nullptr, nullptr},
|
2011-11-07 12:55:18 +00:00
|
|
|
};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Clean Tracks";
|
|
|
|
|
ot->description = "Clean tracks with high error values or few frames";
|
|
|
|
|
ot->idname = "CLIP_OT_clean_tracks";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = clean_tracks_exec;
|
|
|
|
|
ot->invoke = clean_tracks_invoke;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-07 12:55:18 +00:00
|
|
|
/* properties */
|
2012-04-14 15:44:31 +00:00
|
|
|
RNA_def_int(ot->srna,
|
|
|
|
|
"frames",
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
INT_MAX,
|
|
|
|
|
"Tracked Frames",
|
2023-07-24 21:22:07 +02:00
|
|
|
"Affect tracks which are tracked less than the "
|
|
|
|
|
"specified number of frames",
|
2016-01-15 13:48:24 +05:00
|
|
|
0,
|
|
|
|
|
INT_MAX);
|
2012-04-14 15:44:31 +00:00
|
|
|
RNA_def_float(ot->srna,
|
|
|
|
|
"error",
|
|
|
|
|
0.0f,
|
|
|
|
|
0.0f,
|
|
|
|
|
FLT_MAX,
|
|
|
|
|
"Reprojection Error",
|
2023-07-24 21:22:07 +02:00
|
|
|
"Affect tracks which have a larger reprojection error",
|
2016-01-15 13:48:24 +05:00
|
|
|
0.0f,
|
|
|
|
|
100.0f);
|
|
|
|
|
RNA_def_enum(ot->srna, "action", actions_items, 0, "Action", "Cleanup action to execute");
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Add Tracking Object
|
|
|
|
|
* \{ */
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus tracking_object_new_exec(bContext *C, wmOperator * /*op*/)
|
2011-12-05 18:57:17 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_object_add(tracking, "Object");
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2024-02-19 15:54:08 +01:00
|
|
|
DEG_id_tag_update(&clip->id, ID_RECALC_SYNC_TO_EVAL);
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2011-12-05 18:57:17 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_tracking_object_new(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Add Tracking Object";
|
|
|
|
|
ot->description = "Add new object for tracking";
|
|
|
|
|
ot->idname = "CLIP_OT_tracking_object_new";
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = tracking_object_new_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-12-05 18:57:17 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-12-05 18:57:17 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Remove Tracking Object
|
|
|
|
|
* \{ */
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus tracking_object_remove_exec(bContext *C, wmOperator *op)
|
2011-12-05 18:57:17 +00:00
|
|
|
{
|
2012-03-25 23:19:21 +00:00
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-03-25 23:19:21 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-05 18:01:29 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2022-10-05 18:01:29 +02:00
|
|
|
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
2016-01-15 13:48:24 +05:00
|
|
|
BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking cannot be deleted");
|
2011-12-05 18:57:17 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-05 18:01:29 +02:00
|
|
|
BKE_tracking_object_delete(tracking, tracking_object);
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2024-02-19 15:54:08 +01:00
|
|
|
DEG_id_tag_update(&clip->id, ID_RECALC_SYNC_TO_EVAL);
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2011-12-05 18:57:17 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_tracking_object_remove(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2012-06-24 13:52:20 +00:00
|
|
|
ot->name = "Remove Tracking Object";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->description = "Remove object for tracking";
|
|
|
|
|
ot->idname = "CLIP_OT_tracking_object_remove";
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = tracking_object_remove_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2011-12-05 18:57:17 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2011-12-05 18:57:17 +00:00
|
|
|
}
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Copy Tracks to Clipboard Operator
|
|
|
|
|
* \{ */
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus copy_tracks_exec(bContext *C, wmOperator * /*op*/)
|
2012-01-09 20:18:48 +00:00
|
|
|
{
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-01-09 20:18:48 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-05 18:01:29 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2016-01-15 14:02:26 +05:00
|
|
|
clip_tracking_clear_invisible_track_selection(sc, clip);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2022-10-05 18:01:29 +02:00
|
|
|
BKE_tracking_clipboard_copy_tracks(tracking, tracking_object);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_copy_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Copy Tracks";
|
2023-04-14 12:12:30 +02:00
|
|
|
ot->description = "Copy the selected tracks to the internal clipboard";
|
2012-01-09 20:18:48 +00:00
|
|
|
ot->idname = "CLIP_OT_copy_tracks";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-01-09 20:18:48 +00:00
|
|
|
ot->exec = copy_tracks_exec;
|
2012-04-29 12:32:26 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
2012-01-09 20:18:48 +00:00
|
|
|
|
|
|
|
|
/* flags */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER;
|
2012-01-09 20:18:48 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Paste Tracks From Clipboard Operator
|
|
|
|
|
* \{ */
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool paste_tracks_poll(bContext *C)
|
2012-01-09 20:18:48 +00:00
|
|
|
{
|
2012-04-29 12:32:26 +00:00
|
|
|
if (ED_space_clip_tracking_poll(C)) {
|
2012-01-09 20:18:48 +00:00
|
|
|
return BKE_tracking_clipboard_has_tracks();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-22 11:36:59 +10:00
|
|
|
return false;
|
2012-01-09 20:18:48 +00:00
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus paste_tracks_exec(bContext *C, wmOperator * /*op*/)
|
2012-01-09 20:18:48 +00:00
|
|
|
{
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
2012-06-19 14:26:29 +00:00
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2012-01-09 20:18:48 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-05 15:56:08 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2022-10-05 15:56:08 +02:00
|
|
|
BKE_tracking_tracks_deselect_all(&tracking_object->tracks);
|
|
|
|
|
BKE_tracking_clipboard_paste_tracks(tracking, tracking_object);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
2012-05-07 08:53:59 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2012-01-09 20:18:48 +00:00
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_paste_tracks(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Paste Tracks";
|
2023-04-14 12:12:30 +02:00
|
|
|
ot->description = "Paste tracks from the internal clipboard";
|
2012-01-09 20:18:48 +00:00
|
|
|
ot->idname = "CLIP_OT_paste_tracks";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2012-01-09 20:18:48 +00:00
|
|
|
ot->exec = paste_tracks_exec;
|
|
|
|
|
ot->poll = paste_tracks_poll;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
2012-05-07 08:53:59 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2012-01-09 20:18:48 +00:00
|
|
|
}
|
Merge plane track feature from tomato branch
This commit includes all the changes made for plane tracker
in tomato branch.
Movie clip editor changes:
- Artist might create a plane track out of multiple point
tracks which belongs to the same track (minimum amount of
point tracks is 4, maximum is not actually limited).
When new plane track is added, it's getting "tracked"
across all point tracks, which makes it stick to the same
plane point tracks belong to.
- After plane track was added, it need to be manually adjusted
in a way it covers feature one might to mask/replace.
General transform tools (G, R, S) or sliding corners with
a mouse could be sued for this. Plane corner which
corresponds to left bottom image corner has got X/Y axis
on it (red is for X axis, green for Y).
- Re-adjusting plane corners makes plane to be "re-tracked"
for the frames sequence between current frame and next
and previous keyframes.
- Kayframes might be removed from the plane, using Shit-X
(Marker Delete) operator. However, currently manual
re-adjustment or "re-track" trigger is needed.
Compositor changes:
- Added new node called Plane Track Deform.
- User selects which plane track to use (for this he need
to select movie clip datablock, object and track names).
- Node gets an image input, which need to be warped into
the plane.
- Node outputs:
* Input image warped into the plane.
* Plane, rasterized to a mask.
Masking changes:
- Mask points might be parented to a plane track, which
makes this point deforming in a way as if it belongs
to the tracked plane.
Some video tutorials are available:
- Coder video: http://www.youtube.com/watch?v=vISEwqNHqe4
- Artist video: https://vimeo.com/71727578
This is mine and Keir's holiday code project :)
2013-08-16 09:46:30 +00:00
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Insert Track Keyframe Operator
|
|
|
|
|
* \{ */
|
2013-09-09 11:55:52 +00:00
|
|
|
|
|
|
|
|
static void keyframe_set_flag(bContext *C, bool set)
|
|
|
|
|
{
|
|
|
|
|
SpaceClip *sc = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(sc);
|
2022-10-07 11:32:21 +02:00
|
|
|
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
|
|
|
|
|
const int framenr = ED_space_clip_get_clip_frame_number(sc);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
2013-09-09 11:55:52 +00:00
|
|
|
if (TRACK_VIEW_SELECTED(sc, track)) {
|
2013-09-17 08:58:12 +00:00
|
|
|
if (set) {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr);
|
2013-09-17 08:58:12 +00:00
|
|
|
marker->flag &= ~MARKER_TRACKED;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (marker != nullptr) {
|
2013-09-09 11:55:52 +00:00
|
|
|
marker->flag |= MARKER_TRACKED;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-09 11:55:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 11:32:21 +02:00
|
|
|
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, &tracking_object->plane_tracks) {
|
2014-03-06 20:07:14 +06:00
|
|
|
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
|
2013-09-17 08:58:12 +00:00
|
|
|
if (set) {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track,
|
|
|
|
|
framenr);
|
2013-09-17 08:58:12 +00:00
|
|
|
if (plane_marker->flag & PLANE_MARKER_TRACKED) {
|
|
|
|
|
plane_marker->flag &= ~PLANE_MARKER_TRACKED;
|
2016-01-15 13:48:24 +05:00
|
|
|
BKE_tracking_track_plane_from_existing_motion(plane_track, plane_marker->framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-09 11:55:52 +00:00
|
|
|
}
|
2013-09-17 08:58:12 +00:00
|
|
|
else {
|
2016-01-15 13:48:24 +05:00
|
|
|
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
|
|
|
|
|
framenr);
|
2013-09-17 08:58:12 +00:00
|
|
|
if (plane_marker) {
|
2013-09-17 08:54:10 +00:00
|
|
|
if ((plane_marker->flag & PLANE_MARKER_TRACKED) == 0) {
|
|
|
|
|
plane_marker->flag |= PLANE_MARKER_TRACKED;
|
2016-01-15 13:48:24 +05:00
|
|
|
BKE_tracking_retrack_plane_from_existing_motion_at_segment(plane_track,
|
|
|
|
|
plane_marker->framenr);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-09-17 08:54:10 +00:00
|
|
|
}
|
2013-09-09 11:55:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-17 08:54:10 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
2013-09-09 11:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus keyframe_insert_exec(bContext *C, wmOperator * /*op*/)
|
2013-09-09 11:55:52 +00:00
|
|
|
{
|
|
|
|
|
keyframe_set_flag(C, true);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_keyframe_insert(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2019-09-20 14:31:24 +02:00
|
|
|
ot->name = "Insert Keyframe";
|
2013-09-09 11:55:52 +00:00
|
|
|
ot->description = "Insert a keyframe to selected tracks at current frame";
|
|
|
|
|
ot->idname = "CLIP_OT_keyframe_insert";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2013-09-09 11:55:52 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
|
|
|
|
ot->exec = keyframe_insert_exec;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-19 19:41:44 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Delete Track Keyframe Operator
|
|
|
|
|
* \{ */
|
2013-09-09 11:55:52 +00:00
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus keyframe_delete_exec(bContext *C, wmOperator * /*op*/)
|
2013-09-09 11:55:52 +00:00
|
|
|
{
|
|
|
|
|
keyframe_set_flag(C, false);
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_keyframe_delete(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
2019-09-20 14:31:24 +02:00
|
|
|
ot->name = "Delete Keyframe";
|
2013-09-09 11:55:52 +00:00
|
|
|
ot->description = "Delete a keyframe from selected tracks at current frame";
|
|
|
|
|
ot->idname = "CLIP_OT_keyframe_delete";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2013-09-09 11:55:52 +00:00
|
|
|
ot->poll = ED_space_clip_tracking_poll;
|
|
|
|
|
ot->exec = keyframe_delete_exec;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
2021-06-19 19:41:44 +10:00
|
|
|
|
|
|
|
|
/** \} */
|
2022-06-28 16:03:35 +02:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Image from plane track marker
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static ImBuf *sample_plane_marker_image_for_operator(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
const int clip_frame_number = ED_space_clip_get_clip_frame_number(space_clip);
|
|
|
|
|
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
|
|
|
|
const MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(
|
|
|
|
|
tracking_object->active_plane_track, clip_frame_number);
|
2022-06-28 16:03:35 +02:00
|
|
|
|
|
|
|
|
ImBuf *frame_ibuf = ED_space_clip_get_buffer(space_clip);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (frame_ibuf == nullptr) {
|
|
|
|
|
return nullptr;
|
2022-06-28 16:03:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImBuf *plane_ibuf = BKE_tracking_get_plane_imbuf(frame_ibuf, plane_marker);
|
|
|
|
|
|
|
|
|
|
IMB_freeImBuf(frame_ibuf);
|
|
|
|
|
|
|
|
|
|
return plane_ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool new_image_from_plane_marker_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
if (!ED_space_clip_tracking_poll(C)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
const MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2022-06-28 16:03:35 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
if (tracking_object->active_plane_track == nullptr) {
|
2022-06-28 16:03:35 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus new_image_from_plane_marker_exec(bContext *C, wmOperator * /*op*/)
|
2022-06-28 16:03:35 +02:00
|
|
|
{
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
|
|
|
|
MovieTrackingPlaneTrack *plane_track = tracking_object->active_plane_track;
|
2022-06-28 16:03:35 +02:00
|
|
|
|
|
|
|
|
ImBuf *plane_ibuf = sample_plane_marker_image_for_operator(C);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (plane_ibuf == nullptr) {
|
2022-06-28 16:03:35 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
plane_track->image = BKE_image_add_from_imbuf(CTX_data_main(C), plane_ibuf, plane_track->name);
|
|
|
|
|
|
|
|
|
|
IMB_freeImBuf(plane_ibuf);
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_new_image_from_plane_marker(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "New Image from Plane Marker";
|
|
|
|
|
ot->description = "Create new image from the content of the plane marker";
|
|
|
|
|
ot->idname = "CLIP_OT_new_image_from_plane_marker";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2022-06-28 16:03:35 +02:00
|
|
|
ot->poll = new_image_from_plane_marker_poll;
|
|
|
|
|
ot->exec = new_image_from_plane_marker_exec;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool update_image_from_plane_marker_poll(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
if (!ED_space_clip_tracking_poll(C)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
const MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
2022-06-28 16:03:35 +02:00
|
|
|
|
2023-03-01 12:32:15 +01:00
|
|
|
if (tracking_object->active_plane_track == nullptr ||
|
|
|
|
|
tracking_object->active_plane_track->image == nullptr)
|
|
|
|
|
{
|
2022-06-28 16:03:35 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 17:39:57 +02:00
|
|
|
const Image *image = tracking_object->active_plane_track->image;
|
2022-06-28 16:03:35 +02:00
|
|
|
return image->type == IMA_TYPE_IMAGE && ELEM(image->source, IMA_SRC_FILE, IMA_SRC_GENERATED);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-20 21:11:06 +00:00
|
|
|
static wmOperatorStatus update_image_from_plane_marker_exec(bContext *C, wmOperator * /*op*/)
|
2022-06-28 16:03:35 +02:00
|
|
|
{
|
|
|
|
|
SpaceClip *space_clip = CTX_wm_space_clip(C);
|
|
|
|
|
MovieClip *clip = ED_space_clip_get_clip(space_clip);
|
|
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2022-10-04 17:39:57 +02:00
|
|
|
MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking);
|
|
|
|
|
MovieTrackingPlaneTrack *plane_track = tracking_object->active_plane_track;
|
2022-06-28 16:03:35 +02:00
|
|
|
|
|
|
|
|
ImBuf *plane_ibuf = sample_plane_marker_image_for_operator(C);
|
2023-03-01 12:32:15 +01:00
|
|
|
if (plane_ibuf == nullptr) {
|
2022-06-28 16:03:35 +02:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_image_replace_imbuf(plane_track->image, plane_ibuf);
|
|
|
|
|
|
|
|
|
|
IMB_freeImBuf(plane_ibuf);
|
|
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
|
|
|
|
|
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, plane_track->image);
|
|
|
|
|
|
|
|
|
|
BKE_image_partial_update_mark_full_update(plane_track->image);
|
|
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CLIP_OT_update_image_from_plane_marker(wmOperatorType *ot)
|
|
|
|
|
{
|
|
|
|
|
/* identifiers */
|
|
|
|
|
ot->name = "Update Image from Plane Marker";
|
|
|
|
|
ot->description =
|
|
|
|
|
"Update current image used by plane marker from the content of the plane marker";
|
|
|
|
|
ot->idname = "CLIP_OT_update_image_from_plane_marker";
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* API callbacks. */
|
2022-06-28 16:03:35 +02:00
|
|
|
ot->poll = update_image_from_plane_marker_poll;
|
|
|
|
|
ot->exec = update_image_from_plane_marker_exec;
|
|
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|