1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * This file is part of openfx-supportext <https://github.com/devernay/openfx-supportext>,
4  * Copyright (C) 2013-2018 INRIA
5  *
6  * openfx-supportext is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * openfx-supportext is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with openfx-supportext.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
18  * ***** END LICENSE BLOCK ***** */
19 
20 /*
21  * OFX utilities for tracking.
22  */
23 
24 #ifndef openfx_supportext_ofxsTracking_h
25 #define openfx_supportext_ofxsTracking_h
26 
27 #include "ofxsImageEffect.h"
28 #ifdef OFX_EXTENSIONS_NATRON
29 #include "ofxNatron.h"
30 #endif
31 #include "ofxsMacros.h"
32 
33 #define kParamTrackingCenterPoint "center"
34 #define kParamTrackingCenterPointLabel "Center"
35 #define kParamTrackingCenterPointHint "The center point to track"
36 
37 #define kParamTrackingOffset "offset"
38 #define kParamTrackingOffsetLabel "Offset"
39 #define kParamTrackingOffsetHint "The offset applied to the center point relative to the real tracked position"
40 
41 #define kParamTrackingReferenceFrame "refFrame"
42 #define kParamTrackingReferenceFrameLabel "Reference Frame"
43 #define kParamTrackingReferenceFrameHint "The frame from which the pattern should be sampled"
44 
45 #define kParamTrackingEnableReferenceFrame "enableRefFrame"
46 #define kParamTrackingEnableReferenceFrameLabel "Enable Reference Frame"
47 #define kParamTrackingEnableReferenceFrameHint "When checked, the reference frame will be the frame indicated by the Reference Frame parameter"
48 
49 #define kParamTrackingCorrelationScore "correlation"
50 #define kParamTrackingCorrelationScoreLabel "Correlation"
51 #define kParamTrackingCorrelationScoreHint "The correlation score of the track with respect to the pattern"
52 
53 #define kParamTrackingPatternBoxBtmLeft "patternBoxBtmLeft"
54 #define kParamTrackingPatternBoxBtmLeftLabel "Pattern Bottom Left"
55 #define kParamTrackingPatternBoxBtmLeftHint "The bottom left corner of the inner pattern box. The coordinates are relative to the center point."
56 
57 #define kParamTrackingPatternBoxTopRight "patternBoxTopRight"
58 #define kParamTrackingPatternBoxTopRightLabel "Pattern Top Right"
59 #define kParamTrackingPatternBoxTopRightHint "The top right corner of the inner pattern box. The coordinates are relative to the center point."
60 
61 #define kParamTrackingSearchBoxBtmLeft "searchBoxBtmLeft"
62 #define kParamTrackingSearchBoxBtmLeftLabel "Search Area Bottom Left"
63 #define kParamTrackingSearchBoxBtmLeftHint "The bottom left corner of the search area. The coordinates are relative to the center point."
64 
65 #define kParamTrackingSearchBoxTopRight "searchBoxTopRight"
66 #define kParamTrackingSearchBoxTopRightLabel "Search Area Top Right"
67 #define kParamTrackingSearchBoxTopRightHint "The top right corner of the search area. The coordinates are relative to the center point."
68 
69 #define kParamTrackingPrevious kNatronParamTrackingPrevious
70 #define kParamTrackingPreviousLabel "Track Previous"
71 #define kParamTrackingPreviousHint "Track pattern to previous frame"
72 
73 #define kParamTrackingNext kNatronParamTrackingNext
74 #define kParamTrackingNextLabel "Track Next"
75 #define kParamTrackingNextHint "Track pattern to next frame"
76 
77 #define kParamTrackingBackward kNatronParamTrackingBackward
78 #define kParamTrackingBackwardLabel "Track Backward"
79 #define kParamTrackingBackwardHint "Track pattern to the beginning of the sequence"
80 
81 #define kParamTrackingForward kNatronParamTrackingForward
82 #define kParamTrackingForwardLabel "Track Forward"
83 #define kParamTrackingForwardHint "Track pattern to the end of the sequence"
84 
85 #define kParamTrackingLabel kNatronOfxParamStringSublabelName // defined in ofxNatron.h
86 #define kParamTrackingLabelLabel "Track Name"
87 #define kParamTrackingLabelHint "The name of the track, as it appears in the user interface."
88 #define kParamTrackingLabelDefault "Track"
89 
90 namespace OFX {
91 struct TrackArguments
92 {
93     ///first is not necesserarily lesser than last.
94     OfxTime first;     //<! the first frame to track *from*
95     OfxTime last;     //<! the last frame to track *from* (can be the same as first)
96     bool forward;     //<! tracking direction
97     InstanceChangeReason reason;
98     OfxPointD renderScale;
99 };
100 
101 class GenericTrackerPlugin
102     : public OFX::ImageEffect
103 {
104 public:
105     /** @brief ctor */
106     GenericTrackerPlugin(OfxImageEffectHandle handle);
107 
108     /**
109      * @brief Nothing to do since we're identity. The host should always render the image of the input.
110      **/
render(const OFX::RenderArguments &)111     virtual void render(const OFX::RenderArguments & /*args*/) OVERRIDE
112     {
113     }
114 
115     /**
116      * @brief Returns true always at the same time and for the source clip.
117      **/
118     virtual bool isIdentity(const OFX::IsIdentityArguments &args, OFX::Clip * &identityClip, double &identityTime, int& view, std::string& plane) OVERRIDE;
119 
120     /**
121      * @brief Handles the push buttons actions.
122      **/
123     virtual void changedParam(const OFX::InstanceChangedArgs &args, const std::string &paramName) OVERRIDE;
124     virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE;
125 
126 protected:
127 
128     /**
129      * @brief Override to track the entire range between [first,last].
130      * @param forward If true then it should track from first to last, otherwise it should track
131      * from last to first.
132      * @param currentTime The current time at which the track has been requested.
133      **/
134     virtual void trackRange(const OFX::TrackArguments & args) = 0;
135 
136     // do not need to delete these, the ImageEffect is managing them for us
137     OFX::Clip *_dstClip;
138     OFX::Clip *_srcClip;
139     OFX::PushButtonParam* _backwardButton;
140     OFX::PushButtonParam* _prevButton;
141     OFX::PushButtonParam* _nextButton;
142     OFX::PushButtonParam* _forwardButton;
143     OFX::StringParam* _instanceName;
144 };
145 
146 void genericTrackerDescribe(OFX::ImageEffectDescriptor &desc);
147 
148 OFX::PageParamDescriptor* genericTrackerDescribeInContextBegin(OFX::ImageEffectDescriptor &desc, OFX::ContextEnum context);
149 
150 void genericTrackerDescribePointParameters(OFX::ImageEffectDescriptor &desc, OFX::PageParamDescriptor* page);
151 
152 /**
153  * @brief This class represents the interact associated with one track.
154  * It is composed of the following elements:
155  * - A point which is the center point of the pattern to track
156  * - An inner rectangle which defines the bounding box of the pattern to track
157  * - An outer rectangle which defines the region where we should look for the pattern in the previous/following frames.
158  *
159  * The inner and outer rectangle are defined respectively by their bottom left corner and their size (width/height).
160  * The bottom left corner of these rectangles defines an offset relative to the center point instead of absolute coordinates.
161  * It makes it really easier everywhere in the tracker to manipulate coordinates.
162  **/
163 class TrackerRegionInteract
164     : public OFX::OverlayInteract
165 {
166     enum MouseStateEnum
167     {
168         eMouseStateIdle = 0,
169         eMouseStateDraggingCenter,
170         eMouseStateDraggingOffset,
171 
172         eMouseStateDraggingInnerTopLeft,
173         eMouseStateDraggingInnerTopRight,
174         eMouseStateDraggingInnerBtmLeft,
175         eMouseStateDraggingInnerBtmRight,
176         eMouseStateDraggingInnerTopMid,
177         eMouseStateDraggingInnerMidRight,
178         eMouseStateDraggingInnerBtmMid,
179         eMouseStateDraggingInnerMidLeft,
180 
181         eMouseStateDraggingOuterTopLeft,
182         eMouseStateDraggingOuterTopRight,
183         eMouseStateDraggingOuterBtmLeft,
184         eMouseStateDraggingOuterBtmRight,
185         eMouseStateDraggingOuterTopMid,
186         eMouseStateDraggingOuterMidRight,
187         eMouseStateDraggingOuterBtmMid,
188         eMouseStateDraggingOuterMidLeft
189     };
190 
191     enum DrawStateEnum
192     {
193         eDrawStateInactive = 0,
194         eDrawStateHoveringCenter,
195 
196         eDrawStateHoveringInnerTopLeft,
197         eDrawStateHoveringInnerTopRight,
198         eDrawStateHoveringInnerBtmLeft,
199         eDrawStateHoveringInnerBtmRight,
200         eDrawStateHoveringInnerTopMid,
201         eDrawStateHoveringInnerMidRight,
202         eDrawStateHoveringInnerBtmMid,
203         eDrawStateHoveringInnerMidLeft,
204 
205         eDrawStateHoveringOuterTopLeft,
206         eDrawStateHoveringOuterTopRight,
207         eDrawStateHoveringOuterBtmLeft,
208         eDrawStateHoveringOuterBtmRight,
209         eDrawStateHoveringOuterTopMid,
210         eDrawStateHoveringOuterMidRight,
211         eDrawStateHoveringOuterBtmMid,
212         eDrawStateHoveringOuterMidLeft
213     };
214 
215 public:
216 
TrackerRegionInteract(OfxInteractHandle handle,OFX::ImageEffect * effect)217     TrackerRegionInteract(OfxInteractHandle handle,
218                           OFX::ImageEffect* effect)
219         : OFX::OverlayInteract(handle)
220         , _lastMousePos()
221         , _ms(eMouseStateIdle)
222         , _ds(eDrawStateInactive)
223         , _center(NULL)
224         , _offset(NULL)
225         , _innerBtmLeft(NULL)
226         , _innerTopRight(NULL)
227         , _outerBtmLeft(NULL)
228         , _outerTopRight(NULL)
229         , _name(NULL)
230         , _centerDragPos()
231         , _offsetDragPos()
232         , _innerBtmLeftDragPos()
233         , _innerTopRightDragPos()
234         , _outerBtmLeftDragPos()
235         , _outerTopRightDragPos()
236         , _controlDown(0)
237         , _altDown(0)
238     {
239         _center = effect->fetchDouble2DParam(kParamTrackingCenterPoint);
240         _offset = effect->fetchDouble2DParam(kParamTrackingOffset);
241         _innerBtmLeft = effect->fetchDouble2DParam(kParamTrackingPatternBoxBtmLeft);
242         _innerTopRight = effect->fetchDouble2DParam(kParamTrackingPatternBoxTopRight);
243         _outerBtmLeft = effect->fetchDouble2DParam(kParamTrackingSearchBoxBtmLeft);
244         _outerTopRight = effect->fetchDouble2DParam(kParamTrackingSearchBoxTopRight);
245         _name = effect->fetchStringParam(kNatronOfxParamStringSublabelName);
246         addParamToSlaveTo(_center);
247         addParamToSlaveTo(_offset);
248         addParamToSlaveTo(_innerBtmLeft);
249         addParamToSlaveTo(_innerTopRight);
250         addParamToSlaveTo(_outerBtmLeft);
251         addParamToSlaveTo(_outerTopRight);
252         addParamToSlaveTo(_name);
253     }
254 
255     // overridden functions from OFX::Interact to do things
256     virtual bool draw(const OFX::DrawArgs &args);
257     virtual bool penMotion(const OFX::PenArgs &args);
258     virtual bool penDown(const OFX::PenArgs &args);
259     virtual bool penUp(const OFX::PenArgs &args);
260     virtual bool keyDown(const OFX::KeyArgs &args);
261     virtual bool keyUp(const OFX::KeyArgs &args);
262     virtual void loseFocus(const OFX::FocusArgs &args);
263 
264 private:
265     bool isDraggingInnerPoint() const;
266     bool isDraggingOuterPoint() const;
267 
268     OfxPointD _lastMousePos;
269     MouseStateEnum _ms;
270     DrawStateEnum _ds;
271     OFX::Double2DParam* _center;
272     OFX::Double2DParam* _offset;
273     OFX::Double2DParam* _innerBtmLeft;
274     OFX::Double2DParam* _innerTopRight;
275     OFX::Double2DParam* _outerBtmLeft;
276     OFX::Double2DParam* _outerTopRight;
277     OFX::StringParam* _name;
278     OfxPointD _centerDragPos;
279     OfxPointD _offsetDragPos;
280 
281     ///Here the btm left points are NOT relative to the center
282     ///The offset is applied to this points
283     OfxPointD _innerBtmLeftDragPos;
284     OfxPointD _innerTopRightDragPos;
285     OfxPointD _outerBtmLeftDragPos;
286     OfxPointD _outerTopRightDragPos;
287     int _controlDown;
288     int _altDown;
289 };
290 
291 class TrackerRegionOverlayDescriptor
292     : public OFX::DefaultEffectOverlayDescriptor<TrackerRegionOverlayDescriptor, TrackerRegionInteract>
293 {
294 };
295 } // OFX
296 
297 #endif /* defined(openfx_supportext_ofxsTracking_h) */
298