KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pl_selection_tool.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <advanced_config.h>
26#include <view/view.h>
27#include <view/view_controls.h>
29#include <tool/tool_event.h>
30#include <tool/tool_manager.h>
31#include <tool/selection.h>
34#include <tools/pl_actions.h>
38#include <collector.h>
39#include <math/util.h> // for KiROUND
40
41#include "pl_editor_frame.h"
42
43
44#define HITTEST_THRESHOLD_PIXELS 3
45
46
48 SELECTION_TOOL( "common.InteractiveSelection" ),
49 m_frame( nullptr )
50{
51}
52
53
55{
57
58 auto& menu = m_menu->GetMenu();
59
60 menu.AddSeparator( 200 );
65
66 menu.AddSeparator( 1000 );
67 m_frame->AddStandardSubMenus( *m_menu.get() );
68
69 m_disambiguateTimer.SetOwner( this );
70 Connect( m_disambiguateTimer.GetId(), wxEVT_TIMER,
71 wxTimerEventHandler( PL_SELECTION_TOOL::onDisambiguationExpire ), nullptr, this );
72
73 return true;
74}
75
76
82
83
85{
86 // Main loop: keep receiving events
87 while( TOOL_EVENT* evt = Wait() )
88 {
89 // on left click, a selection is made, depending on modifiers ALT, SHIFT, CTRL:
90 setModifiersState( evt->Modifier( MD_SHIFT ), evt->Modifier( MD_CTRL ),
91 evt->Modifier( MD_ALT ) );
92
93 if( evt->IsMouseDown( BUT_LEFT ) )
94 {
95 // Avoid triggering when running under other tools
96 PL_POINT_EDITOR *pt_tool = m_toolMgr->GetTool<PL_POINT_EDITOR>();
97
98 if( m_frame->ToolStackIsEmpty() && pt_tool && !pt_tool->HasPoint() )
99 {
100 m_originalCursor = m_toolMgr->GetMousePosition();
101 m_disambiguateTimer.StartOnce( ADVANCED_CFG::GetCfg().m_DisambiguationMenuDelay );
102 }
103 }
104 // Single click? Select single object
105 else if( evt->IsClick( BUT_LEFT ) )
106 {
107 // If the timer has stopped, then we have already run the disambiguate routine
108 // and we don't want to register an extra click here
109 if( !m_disambiguateTimer.IsRunning() )
110 {
111 evt->SetPassEvent();
112 continue;
113 }
114
115 m_disambiguateTimer.Stop();
116 SelectPoint( evt->Position() );
117 }
118
119 // right click? if there is any object - show the context menu
120 else if( evt->IsClick( BUT_RIGHT ) )
121 {
122 m_disambiguateTimer.Stop();
123 bool selectionCancelled = false;
124
125 if( m_selection.Empty() )
126 {
127 SelectPoint( evt->Position(), &selectionCancelled );
128 m_selection.SetIsHover( true );
129 }
130
131 // Show selection before opening menu
132 m_frame->GetCanvas()->ForceRefresh();
133
134 if( !selectionCancelled )
135 m_menu->ShowContextMenu( m_selection );
136 }
137
138 // double click? Display the properties window
139 else if( evt->IsDblClick( BUT_LEFT ) )
140 {
141 // No double-click actions currently defined
142 }
143
144 // drag with LMB? Select multiple objects (or at least draw a selection box) or drag them
145 else if( evt->IsDrag( BUT_LEFT ) )
146 {
147 m_disambiguateTimer.Stop();
148
149 if( hasModifier() || m_selection.Empty() )
150 {
152 }
153 else
154 {
155 // Check if dragging has started within any of selected items bounding box
156 if( selectionContains( evt->Position() ) )
157 {
158 // Yes -> run the move tool and wait till it finishes
159 m_toolMgr->RunAction( "plEditor.InteractiveMove.move" );
160 }
161 else
162 {
163 // No -> clear the selection list
165 }
166 }
167 }
168
169 // Middle double click? Do zoom to fit or zoom to objects
170 else if( evt->IsDblClick( BUT_MIDDLE ) )
171 {
172 m_toolMgr->RunAction( ACTIONS::zoomFitScreen );
173 }
174
175 else if( evt->IsCancelInteractive() )
176 {
177 m_disambiguateTimer.Stop();
179 }
180
181 else if( evt->Action() == TA_UNDO_REDO_PRE )
182 {
184 }
185
186 else
187 evt->SetPassEvent();
188
189
190 if( m_frame->ToolStackIsEmpty() )
191 {
192 if( !hasModifier()
193 && !m_selection.Empty()
194 && m_frame->GetDragAction() == MOUSE_DRAG_ACTION::DRAG_SELECTED
195 && evt->HasPosition()
196 && selectionContains( evt->Position() ) )
197 {
198 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::MOVING );
199 }
200 else
201 {
202 if( m_additive )
203 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ADD );
204 else if( m_subtractive )
205 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::SUBTRACT );
206 else if( m_exclusive_or )
207 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::XOR );
208 else
209 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
210 }
211 }
212 }
213
214 return 0;
215}
216
217
219{
220 wxMouseState keyboardState = wxGetMouseState();
221
222 setModifiersState( keyboardState.ShiftDown(), keyboardState.ControlDown(),
223 keyboardState.AltDown() );
224
225 m_skip_heuristics = true;
227 m_skip_heuristics = false;
228
229 return 0;
230}
231
232
237
238
239void PL_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, bool* aSelectionCancelledFlag )
240{
241 int threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
242
243 // locate items.
244 COLLECTOR collector;
245
246 for( DS_DATA_ITEM* dataItem : DS_DATA_MODEL::GetTheInstance().GetItems() )
247 {
248 for( DS_DRAW_ITEM_BASE* drawItem : dataItem->GetDrawItems() )
249 {
250 if( drawItem->HitTest( aWhere, threshold ) )
251 collector.Append( drawItem );
252 }
253 }
254
255 m_selection.ClearReferencePoint();
256
257 // Apply some ugly heuristics to avoid disambiguation menus whenever possible
258 if( collector.GetCount() > 1 && !m_skip_heuristics )
259 guessSelectionCandidates( collector, aWhere );
260
261 // If still more than one item we're going to have to ask the user.
262 if( collector.GetCount() > 1 )
263 {
264 doSelectionMenu( &collector );
265
266 if( collector.m_MenuCancelled )
267 {
268 if( aSelectionCancelledFlag )
269 *aSelectionCancelledFlag = true;
270
271 return;
272 }
273 }
274
275 bool anyAdded = false;
276 bool anySubtracted = false;
277
278
280 {
281 if( collector.GetCount() == 0 )
282 anySubtracted = true;
283
285 }
286
287 if( collector.GetCount() > 0 )
288 {
289 for( int i = 0; i < collector.GetCount(); ++i )
290 {
291 if( m_subtractive || ( m_exclusive_or && collector[i]->IsSelected() ) )
292 {
293 unselect( collector[i] );
294 anySubtracted = true;
295 }
296 else
297 {
298 select( collector[i] );
299 anyAdded = true;
300 }
301 }
302 }
303
304 if( anyAdded )
305 m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
306
307 if( anySubtracted )
308 m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
309}
310
311
313{
314 // There are certain conditions that can be handled automatically.
315
316 // Prefer an exact hit to a sloppy one
317 for( int i = 0; collector.GetCount() == 2 && i < 2; ++i )
318 {
319 EDA_ITEM* item = collector[ i ];
320 EDA_ITEM* other = collector[ ( i + 1 ) % 2 ];
321
322 if( item->HitTest( aPos, 0 ) && !other->HitTest( aPos, 0 ) )
323 collector.Transfer( other );
324 }
325}
326
327
329{
330 // If nothing is selected do a hover selection
331 if( m_selection.Empty() )
332 {
333 VECTOR2D cursorPos = getViewControls()->GetCursorPosition( true );
334
336 SelectPoint( cursorPos );
337 m_selection.SetIsHover( true );
338 }
339
340 return m_selection;
341}
342
343
345{
346 bool cancelled = false; // Was the tool cancelled while it was running?
347 m_multiple = true; // Multiple selection mode is active
348 KIGFX::VIEW* view = getView();
349
351 view->Add( &area );
352
353 while( TOOL_EVENT* evt = Wait() )
354 {
355 /* Selection mode depends on direction of drag-selection:
356 * Left > Right : Select objects that are fully enclosed by selection
357 * Right > Left : Select objects that are crossed by selection
358 */
359 bool windowSelection = area.GetEnd().x > area.GetOrigin().x;
360
361 m_frame->GetCanvas()->SetCurrentCursor( windowSelection ? KICURSOR::SELECT_WINDOW
363
364 if( evt->IsCancelInteractive() || evt->IsActivate() )
365 {
366 cancelled = true;
367 break;
368 }
369
370 if( evt->IsDrag( BUT_LEFT ) )
371 {
374
375 // Start drawing a selection box
376 area.SetOrigin( evt->DragOrigin() );
377 area.SetEnd( evt->Position() );
380 area.SetExclusiveOr( false );
381 area.SetMode( windowSelection ? SELECTION_MODE::INSIDE_RECTANGLE
383
384 view->SetVisible( &area, true );
385 view->Update( &area );
386 getViewControls()->SetAutoPan( true );
387 }
388
389 if( evt->IsMouseUp( BUT_LEFT ) )
390 {
391 getViewControls()->SetAutoPan( false );
392
393 // End drawing the selection box
394 view->SetVisible( &area, false );
395
396 bool anyAdded = false;
397 bool anySubtracted = false;
398
399 // Construct a BOX2I to determine EDA_ITEM selection
400 BOX2I selectionRect( area.ViewBBox() );
401
402 selectionRect.Normalize();
403
404 for( DS_DATA_ITEM* dataItem : DS_DATA_MODEL::GetTheInstance().GetItems() )
405 {
406 for( DS_DRAW_ITEM_BASE* item : dataItem->GetDrawItems() )
407 {
408 if( item->HitTest( selectionRect, windowSelection ) )
409 {
410 if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
411 {
412 unselect( item );
413 anySubtracted = true;
414 }
415 else
416 {
417 select( item );
418 anyAdded = true;
419 }
420 }
421 }
422 }
423
424 // Inform other potentially interested tools
425 if( anyAdded )
426 m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
427
428 if( anySubtracted )
429 m_toolMgr->ProcessEvent( EVENTS::UnselectedEvent );
430
431 break; // Stop waiting for events
432 }
433 }
434
435 getViewControls()->SetAutoPan( false );
436
437 // Stop drawing the selection box
438 view->Remove( &area );
439 m_multiple = false; // Multiple selection mode is inactive
440
441 if( !cancelled )
442 m_selection.ClearReferencePoint();
443
444 return cancelled;
445}
446
447
449{
451 return 0;
452}
453
454
456{
457 m_selection.Clear();
458
459 for( DS_DATA_ITEM* dataItem : DS_DATA_MODEL::GetTheInstance().GetItems() )
460 {
461 for( DS_DRAW_ITEM_BASE* item : dataItem->GetDrawItems() )
462 {
463 if( item->IsSelected() )
464 select( item );
465 }
466 }
467}
468
469
471{
472 if( m_selection.Empty() )
473 return;
474
475 while( m_selection.GetSize() )
477
479
480 m_selection.SetIsHover( false );
481 m_selection.ClearReferencePoint();
482
483 // Inform other potentially interested tools
484 m_toolMgr->ProcessEvent( EVENTS::ClearedEvent );
485}
486
487
489{
490 highlight( aItem, SELECTED, &m_selection );
491}
492
493
495{
496 unhighlight( aItem, SELECTED, &m_selection );
497}
498
499
500void PL_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
501{
502 if( aMode == SELECTED )
503 aItem->SetSelected();
504 else if( aMode == BRIGHTENED )
505 aItem->SetBrightened();
506
507 if( aGroup )
508 aGroup->Add( aItem );
509
510 getView()->Update( aItem );
511}
512
513
514void PL_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, SELECTION* aGroup )
515{
516 if( aMode == SELECTED )
517 aItem->ClearSelected();
518 else if( aMode == BRIGHTENED )
519 aItem->ClearBrightened();
520
521 if( aGroup )
522 aGroup->Remove( aItem );
523
524 getView()->Update( aItem );
525}
526
527
529{
530 const unsigned GRIP_MARGIN = 20;
531 VECTOR2I margin = getView()->ToWorld( VECTOR2I( GRIP_MARGIN, GRIP_MARGIN ), false );
532
533 // Check if the point is located within any of the currently selected items bounding boxes
534 for( EDA_ITEM* item : m_selection )
535 {
536 BOX2I itemBox = item->ViewBBox();
537 itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item
538
539 if( itemBox.Contains( aPoint ) )
540 return true;
541 }
542
543 return false;
544}
545
546
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
static TOOL_ACTION selectItem
Select an item (specified as the event parameter).
Definition actions.h:226
static TOOL_ACTION unselectItem
Definition actions.h:227
static TOOL_ACTION selectionActivate
Activation of the selection tool.
Definition actions.h:213
static TOOL_ACTION selectionMenu
Run a selection menu to select from a list of items.
Definition actions.h:235
static TOOL_ACTION updateMenu
Definition actions.h:271
static TOOL_ACTION zoomFitScreen
Definition actions.h:141
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION unselectItems
Definition actions.h:232
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:231
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:146
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
An abstract class that will find and hold all the objects according to an inspection done by the Insp...
Definition collector.h:49
void Transfer(int aIndex)
Move the item at aIndex (first position is 0) to the backup list.
Definition collector.h:153
bool m_MenuCancelled
Definition collector.h:239
int GetCount() const
Return the number of objects in the list.
Definition collector.h:83
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition collector.h:101
Drawing sheet structure type definitions.
static DS_DATA_MODEL & GetTheInstance()
Return the instance of DS_DATA_MODEL used in the application.
Base class to handle basic graphic items.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
void ClearSelected()
Definition eda_item.h:137
void SetSelected()
Definition eda_item.h:134
void ClearBrightened()
Definition eda_item.h:138
void SetBrightened()
Definition eda_item.h:135
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if aPosition is inside or on the boundary of this item.
Definition eda_item.h:233
static const TOOL_EVENT DisambiguatePoint
Used for hotkey feedback.
Definition actions.h:363
static const TOOL_EVENT ClearedEvent
Definition actions.h:348
static const TOOL_EVENT SelectedEvent
Definition actions.h:346
static const TOOL_EVENT UnselectedEvent
Definition actions.h:347
Represent a selection area (currently a rectangle) in a VIEW, drawn corner-to-corner between two poin...
void SetMode(SELECTION_MODE aMode)
void SetSubtractive(bool aSubtractive)
void SetAdditive(bool aAdditive)
void SetOrigin(const VECTOR2I &aOrigin)
const BOX2I ViewBBox() const override
Set the origin of the rectangle (the fixed corner)
void SetExclusiveOr(bool aExclusiveOr)
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the corner that moves with the cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:66
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:298
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:341
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition view.cpp:1685
VECTOR2D ToWorld(const VECTOR2D &aCoord, bool aAbsolute=true) const
Converts a screen space point/vector to a point/vector in world space coordinates.
Definition view.cpp:467
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1612
static TOOL_ACTION placeImage
Definition pl_actions.h:41
static TOOL_ACTION drawRectangle
Definition pl_actions.h:42
static TOOL_ACTION placeText
Definition pl_actions.h:40
static TOOL_ACTION drawLine
Definition pl_actions.h:43
Tool that displays edit points allowing to modify items by dragging the points.
bool HasPoint()
Indicate the cursor is over an edit point.
void select(EDA_ITEM *aItem) override
Takes necessary action mark an item as selected.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
bool Init() override
Init() is called once upon a registration of the tool.
int disambiguateCursor(const TOOL_EVENT &aEvent)
Handle disambiguation actions including displaying the menu.
int ClearSelection(const TOOL_EVENT &aEvent)
void SelectPoint(const VECTOR2I &aWhere, bool *aSelectionCancelledFlag=nullptr)
Select an item pointed by the parameter aWhere.
void guessSelectionCandidates(COLLECTOR &collector, const VECTOR2I &aWhere)
Apply heuristics to try and determine a single object when multiple are found under the cursor.
bool selectionContains(const VECTOR2I &aPoint) const
Set up handlers for various events.
void unselect(EDA_ITEM *aItem) override
Take necessary action mark an item as unselected.
bool selectMultiple()
Handle drawing a selection box that allows one to select many items at the same time.
PL_SELECTION & GetSelection()
Return the set of currently selected items.
PL_SELECTION & RequestSelection()
Return either an existing selection (filtered), or the selection at the current cursor if the existin...
void highlight(EDA_ITEM *aItem, int aHighlightMode, SELECTION *aGroup=nullptr) override
Highlight the item visually.
void unhighlight(EDA_ITEM *aItem, int aHighlightMode, SELECTION *aGroup=nullptr) override
Unhighlight the item visually.
PL_EDITOR_FRAME * m_frame
int Main(const TOOL_EVENT &aEvent)
The main loop.
void RebuildSelection()
Rebuild the selection from the flags in the view items.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
static bool Empty(const SELECTION &aSelection)
Test if there are no items selected.
bool m_multiple
Multiple selection mode is active.
int RemoveItemFromSel(const TOOL_EVENT &aEvent)
bool doSelectionMenu(COLLECTOR *aCollector)
wxTimer m_disambiguateTimer
Timer to show the disambiguate menu.
bool m_drag_additive
Add multiple items to selection.
bool m_exclusive_or
Items' selection state should be toggled.
int AddItemsToSel(const TOOL_EVENT &aEvent)
int AddItemToSel(const TOOL_EVENT &aEvent)
int UpdateMenu(const TOOL_EVENT &aEvent)
Update a menu's state based on the current selection.
void setModifiersState(bool aShiftState, bool aCtrlState, bool aAltState)
Set the configuration of m_additive, m_subtractive, m_exclusive_or, m_skip_heuristics from the state ...
VECTOR2I m_originalCursor
Location of original cursor when starting click.
int SelectionMenu(const TOOL_EVENT &aEvent)
Show a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single item.
int RemoveItemsFromSel(const TOOL_EVENT &aEvent)
bool m_subtractive
Items should be removed from selection.
SELECTION_TOOL(const std::string &aName)
bool m_skip_heuristics
Show disambiguation menu for all items under the cursor rather than trying to narrow them down first ...
bool m_drag_subtractive
Remove multiple from selection.
bool m_additive
Items should be added to sel (instead of replacing).
bool hasModifier()
True if a selection modifier is enabled, false otherwise.
bool m_canceledMenu
Sets to true if the disambiguation menu was canceled.
void onDisambiguationExpire(wxTimerEvent &aEvent)
Start the process to show our disambiguation menu once the user has kept the mouse down for the minim...
virtual void Add(EDA_ITEM *aItem)
Definition selection.cpp:42
virtual void Remove(EDA_ITEM *aItem)
Definition selection.cpp:60
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:44
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition tool_base.cpp:38
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:78
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:80
Generic, UI-independent tool event.
Definition tool_event.h:171
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
std::unique_ptr< TOOL_MENU > m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
@ SUBTRACT
Definition cursors.h:70
@ SELECT_WINDOW
Definition cursors.h:84
@ SELECT_LASSO
Definition cursors.h:86
@ MOVING
Definition cursors.h:48
@ ARROW
Definition cursors.h:46
#define BRIGHTENED
item is drawn with a bright contour
#define SELECTED
Item was manually selected by the user.
#define HITTEST_THRESHOLD_PIXELS
@ TA_UNDO_REDO_PRE
This event is sent before undo/redo command is performed.
Definition tool_event.h:106
@ MD_ALT
Definition tool_event.h:145
@ MD_CTRL
Definition tool_event.h:144
@ MD_SHIFT
Definition tool_event.h:143
@ BUT_MIDDLE
Definition tool_event.h:134
@ BUT_LEFT
Definition tool_event.h:132
@ BUT_RIGHT
Definition tool_event.h:133
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694