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 generic rectangle interact with 4 corner points + center point and 4 mid-points.
22  * You can use it to define any rectangle in an image resizable by the user.
23  */
24 
25 #ifndef openfx_supportext_ofxsRectangleInteract_h
26 #define openfx_supportext_ofxsRectangleInteract_h
27 
28 #include <ofxsInteract.h>
29 #include <ofxsImageEffect.h>
30 #include "ofxsMacros.h"
31 
32 // a secret parameter used to enable the interact, if it exists
33 #define kParamRectangleInteractEnable "rectangleInteractEnable"
34 
35 #define kParamRectangleInteractBtmLeft "bottomLeft"
36 #define kParamRectangleInteractBtmLeftLabel "Bottom Left"
37 #define kParamRectangleInteractBtmLeftHint "Coordinates of the bottom left corner of the rectangle"
38 
39 #define kParamRectangleInteractSize "size"
40 #define kParamRectangleInteractSizeLabel "Size"
41 #define kParamRectangleInteractSizeHint "Width and height of the rectangle"
42 #define kParamRectangleInteractSizeDim1 "w"
43 #define kParamRectangleInteractSizeDim2 "h"
44 
45 #define kParamRectangleInteractInteractive "interactive"
46 #define kParamRectangleInteractInteractiveLabel "Interactive Update"
47 #define kParamRectangleInteractInteractiveHint "If checked, update the parameter values during interaction with the image viewer, else update the values when pen is released."
48 
49 namespace OFX {
50 /**
51  * @brief In order to work the plug-in using this interact must have 2 parameters named after
52  * the defines above.
53  *
54  **/
55 class RectangleInteract
56     : public OFX::OverlayInteract
57 {
58 public:
59     enum MouseStateEnum
60     {
61         eMouseStateIdle = 0,
62         eMouseStateDraggingTopLeft,
63         eMouseStateDraggingTopRight,
64         eMouseStateDraggingBtmLeft,
65         eMouseStateDraggingBtmRight,
66         eMouseStateDraggingCenter,
67         eMouseStateDraggingTopMid,
68         eMouseStateDraggingMidRight,
69         eMouseStateDraggingBtmMid,
70         eMouseStateDraggingMidLeft
71     };
72 
73     enum DrawStateEnum
74     {
75         eDrawStateInactive = 0,
76         eDrawStateHoveringTopLeft,
77         eDrawStateHoveringTopRight,
78         eDrawStateHoveringBtmLeft,
79         eDrawStateHoveringBtmRight,
80         eDrawStateHoveringCenter,
81         eDrawStateHoveringTopMid,
82         eDrawStateHoveringMidRight,
83         eDrawStateHoveringBtmMid,
84         eDrawStateHoveringMidLeft
85     };
86 
87 public:
88 
RectangleInteract(OfxInteractHandle handle,OFX::ImageEffect * effect)89     RectangleInteract(OfxInteractHandle handle,
90                       OFX::ImageEffect* effect)
91         : OFX::OverlayInteract(handle)
92         , _effect(effect)
93         , _lastMousePos()
94         , _mouseState(eMouseStateIdle)
95         , _drawState(eDrawStateInactive)
96         , _modifierStateCtrl(0)
97         , _modifierStateShift(0)
98         , _enable(NULL)
99         , _btmLeft(NULL)
100         , _size(NULL)
101     {
102         if ( _effect->paramExists(kParamRectangleInteractEnable) ) {
103             _enable = effect->fetchBooleanParam(kParamRectangleInteractEnable);
104         }
105         _btmLeft = effect->fetchDouble2DParam(kParamRectangleInteractBtmLeft);
106         _size = effect->fetchDouble2DParam(kParamRectangleInteractSize);
107         addParamToSlaveTo(_btmLeft);
108         addParamToSlaveTo(_size);
109         assert(_btmLeft && _size);
110         _interactive = effect->paramExists(kParamRectangleInteractInteractive) ? effect->fetchBooleanParam(kParamRectangleInteractInteractive) : 0;
111         _btmLeftDragPos.x = _btmLeftDragPos.y = 0;
112         _sizeDrag.x = _sizeDrag.y = 0;
113         _interactiveDrag = false;
114     }
115 
116     // overridden functions from OFX::Interact to do things
117     virtual bool draw(const OFX::DrawArgs &args) OVERRIDE;
118     virtual bool penMotion(const OFX::PenArgs &args) OVERRIDE;
119     virtual bool penDown(const OFX::PenArgs &args) OVERRIDE;
120     virtual bool penUp(const OFX::PenArgs &args) OVERRIDE;
121     virtual bool keyDown(const OFX::KeyArgs &args) OVERRIDE;
122     virtual bool keyUp(const OFX::KeyArgs & args) OVERRIDE;
123     virtual void loseFocus(const FocusArgs &args) OVERRIDE;
124 
125 protected:
126 
127 
128     /**
129      * @brief This method returns the bottom left point. The base implementation just returns the value
130      * of the _btmLeft parameter at the given time.
131      * One could override this function to  do more complex stuff based on other parameters state like the Crop plug-in does.
132      **/
133     virtual OfxPointD getBtmLeft(OfxTime time) const;
134 
135     /**
136      * @brief This is called right before any call to allowXXX is made.
137      * This way you can query values of a parameter and store it away without having to do this
138      * at every allowXXX call.
139      **/
aboutToCheckInteractivity(OfxTime)140     virtual void aboutToCheckInteractivity(OfxTime /*time*/)
141     {
142     }
143 
144     /**
145      * @brif These can be overriden to disallow interaction with a point.
146      **/
allowTopLeftInteraction()147     virtual bool allowTopLeftInteraction() const
148     {
149         return true;
150     }
151 
allowTopRightInteraction()152     virtual bool allowTopRightInteraction() const
153     {
154         return true;
155     }
156 
allowBtmRightInteraction()157     virtual bool allowBtmRightInteraction() const
158     {
159         return true;
160     }
161 
allowBtmLeftInteraction()162     virtual bool allowBtmLeftInteraction() const
163     {
164         return true;
165     }
166 
allowTopMidInteraction()167     virtual bool allowTopMidInteraction() const
168     {
169         return true;
170     }
171 
allowMidRightInteraction()172     virtual bool allowMidRightInteraction() const
173     {
174         return true;
175     }
176 
allowBtmMidInteraction()177     virtual bool allowBtmMidInteraction() const
178     {
179         return true;
180     }
181 
allowMidLeftInteraction()182     virtual bool allowMidLeftInteraction() const
183     {
184         return true;
185     }
186 
allowCenterInteraction()187     virtual bool allowCenterInteraction() const
188     {
189         return true;
190     }
191 
192 private:
193     void setValue(OfxPointD btmLeft, OfxPointD size, const OfxPointD &pscale);
194 
195 private:
196     OFX::ImageEffect* _effect;
197     OfxPointD _lastMousePos;
198     MouseStateEnum _mouseState;
199     DrawStateEnum _drawState;
200     int _modifierStateCtrl;
201     int _modifierStateShift;
202     OFX::BooleanParam* _enable;
203     OFX::Double2DParam* _btmLeft;
204     OFX::Double2DParam* _size;
205     OFX::BooleanParam* _interactive;
206     OfxPointD _btmLeftDragPos;
207     OfxPointD _sizeDrag;
208     bool _interactiveDrag;
209 };
210 
211 class RectangleOverlayDescriptor
212     : public OFX::DefaultEffectOverlayDescriptor<RectangleOverlayDescriptor, RectangleInteract>
213 {
214 };
215 } // namespace OFX
216 
217 #endif /* defined(openfx_supportext_ofxsRectangleInteract_h) */
218