Pencil2D Animation
Download Community News Docs Contribute
  • Overview
  • Articles
  • Code
  •  
  • Class List
  • Class Index
  • Class Hierarchy
  • Class Members
  • File List
Loading...
Searching...
No Matches
  • core_lib
  • src
  • managers
toolmanager.cpp
1/*
2
3Pencil2D - Traditional Animation Software
4Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5Copyright (C) 2012-2020 Matthew Chiawen Chang
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; version 2 of the License.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16*/
17#include "toolmanager.h"
18
19#include <cmath>
20#include <QDebug>
21#include "pentool.h"
22#include "penciltool.h"
23#include "brushtool.h"
24#include "buckettool.h"
25#include "erasertool.h"
26#include "eyedroppertool.h"
27#include "handtool.h"
28#include "movetool.h"
29#include "polylinetool.h"
30#include "selecttool.h"
31#include "smudgetool.h"
32#include "cameratool.h"
33#include "editor.h"
34
35
36ToolManager::ToolManager(Editor* editor) : BaseManager(editor, __FUNCTION__)
37{
38}
39
40ToolManager::~ToolManager()
41{
42 foreach(BaseTool* tool, mToolSetHash)
43 {
44 tool->saveSettings();
45 }
46}
47
48bool ToolManager::init()
49{
50 mToolSetHash.insert(PEN, new PenTool(this));
51 mToolSetHash.insert(PENCIL, new PencilTool(this));
52 mToolSetHash.insert(BRUSH, new BrushTool(this));
53 mToolSetHash.insert(ERASER, new EraserTool(this));
54 mToolSetHash.insert(BUCKET, new BucketTool(this));
55 mToolSetHash.insert(EYEDROPPER, new EyedropperTool(this));
56 mToolSetHash.insert(HAND, new HandTool(this));
57 mToolSetHash.insert(MOVE, new MoveTool(this));
58 mToolSetHash.insert(POLYLINE, new PolylineTool(this));
59 mToolSetHash.insert(SELECT, new SelectTool(this));
60 mToolSetHash.insert(SMUDGE, new SmudgeTool(this));
61 mToolSetHash.insert(CAMERA, new CameraTool(this));
62
63 foreach(BaseTool* pTool, mToolSetHash.values())
64 {
65 pTool->initialize(editor());
66 }
67
68 setDefaultTool();
69
70 return true;
71}
72
73Status ToolManager::load(Object*)
74{
75 setDefaultTool();
76 return Status::OK;
77}
78
79Status ToolManager::save(Object*)
80{
81 return Status::OK;
82}
83
84BaseTool* ToolManager::currentTool() const
85{
86 if (mTemporaryTool != nullptr)
87 {
88 return mTemporaryTool;
89 }
90 else if (mTabletEraserTool != nullptr)
91 {
92 return mTabletEraserTool;
93 }
94 return mCurrentTool;
95}
96
97BaseTool* ToolManager::getTool(ToolType eToolType)
98{
99 return mToolSetHash[eToolType];
100}
101
102void ToolManager::setDefaultTool()
103{
104 // Set default tool
105 // (called by the main window init)
106 ToolType defaultToolType = PENCIL;
107
108 setCurrentTool(defaultToolType);
109 mTabletEraserTool = nullptr;
110 mTemporaryTool = nullptr;
111}
112
113void ToolManager::setCurrentTool(ToolType eToolType)
114{
115 // We're already using this tool
116 if (mCurrentTool == getTool(eToolType)) { return; }
117
118 if (mCurrentTool != nullptr)
119 {
120 mCurrentTool->leavingThisTool();
121 }
122
123 mCurrentTool = getTool(eToolType);
124 mCurrentTool->enteringThisTool();
125 if (mTemporaryTool == nullptr && mTabletEraserTool == nullptr)
126 {
127 emit toolChanged(eToolType);
128 }
129}
130
131bool ToolManager::leavingThisTool()
132{
133 return currentTool()->leavingThisTool();
134}
135
136void ToolManager::cleanupAllToolsData()
137{
138 foreach(BaseTool* tool, mToolSetHash)
139 {
140 tool->clearToolData();
141 }
142}
143
144void ToolManager::resetAllTools()
145{
146 // Reset can be useful to solve some pencil settings problems.
147 // Beta-testers should be recommended to reset before sending tool related issues.
148 // This can prevent from users to stop working on their project.
149
150 foreach(BaseTool* tool, mToolSetHash)
151 {
152 tool->resetToDefault();
153 }
154 qDebug("tools restored to default settings");
155}
156
157void ToolManager::setWidth(float newWidth)
158{
159 if (std::isnan(newWidth) || newWidth < 0)
160 {
161 newWidth = 1.f;
162 }
163
164 currentTool()->setWidth(static_cast<qreal>(newWidth));
165 emit toolPropertyChanged(currentTool()->type(), WIDTH);
166}
167
168void ToolManager::setFeather(float newFeather)
169{
170 if (std::isnan(newFeather) || newFeather < 0)
171 {
172 newFeather = 0.f;
173 }
174
175 currentTool()->setFeather(static_cast<qreal>(newFeather));
176 emit toolPropertyChanged(currentTool()->type(), FEATHER);
177}
178
179void ToolManager::setUseFeather(bool usingFeather)
180{
181 int usingAA = currentTool()->properties.useAA;
182 int value = propertySwitch(usingFeather, usingAA);
183
184 currentTool()->setAA(value);
185 currentTool()->setUseFeather(usingFeather);
186 emit toolPropertyChanged(currentTool()->type(), USEFEATHER);
187 emit toolPropertyChanged(currentTool()->type(), ANTI_ALIASING);
188}
189
190void ToolManager::setInvisibility(bool isInvisible)
191{
192 currentTool()->setInvisibility(isInvisible);
193 emit toolPropertyChanged(currentTool()->type(), INVISIBILITY);
194}
195
196void ToolManager::setPreserveAlpha(bool isPreserveAlpha)
197{
198 currentTool()->setPreserveAlpha(isPreserveAlpha);
199 emit toolPropertyChanged(currentTool()->type(), PRESERVEALPHA);
200}
201
202void ToolManager::setVectorMergeEnabled(bool isVectorMergeEnabled)
203{
204 currentTool()->setVectorMergeEnabled(isVectorMergeEnabled);
205 emit toolPropertyChanged(currentTool()->type(), VECTORMERGE);
206}
207
208void ToolManager::setBezier(bool isBezierOn)
209{
210 currentTool()->setBezier(isBezierOn);
211 emit toolPropertyChanged(currentTool()->type(), BEZIER);
212}
213
214void ToolManager::setClosedPath(bool isPathClosed)
215{
216 currentTool()->setClosedPath(isPathClosed);
217 emit toolPropertyChanged(currentTool()->type(), CLOSEDPATH);
218}
219
220void ToolManager::setPressure(bool isPressureOn)
221{
222 currentTool()->setPressure(isPressureOn);
223 emit toolPropertyChanged(currentTool()->type(), PRESSURE);
224}
225
226void ToolManager::setAA(int usingAA)
227{
228 currentTool()->setAA(usingAA);
229 emit toolPropertyChanged(currentTool()->type(), ANTI_ALIASING);
230}
231
232void ToolManager::setFillMode(int mode)
233{
234 currentTool()->setFillMode(mode);
235 emit toolPropertyChanged(currentTool()->type(), FILL_MODE);
236}
237
238void ToolManager::setStabilizerLevel(int level)
239{
240 currentTool()->setStabilizerLevel(level);
241 emit toolPropertyChanged(currentTool()->type(), STABILIZATION);
242}
243
244void ToolManager::setTolerance(int newTolerance)
245{
246 newTolerance = qMax(0, newTolerance);
247
248 currentTool()->setTolerance(newTolerance);
249 emit toolPropertyChanged(currentTool()->type(), TOLERANCE);
250}
251
252void ToolManager::setBucketColorToleranceEnabled(bool enabled)
253{
254 currentTool()->setToleranceEnabled(enabled);
255 emit toolPropertyChanged(currentTool()->type(), USETOLERANCE);
256}
257
258void ToolManager::setBucketFillExpandEnabled(bool expandValue)
259{
260 currentTool()->setFillExpandEnabled(expandValue);
261 emit toolPropertyChanged(currentTool()->type(), USEBUCKETFILLEXPAND);
262}
263
264void ToolManager::setBucketFillExpand(int expandValue)
265{
266 currentTool()->setFillExpand(expandValue);
267 emit toolPropertyChanged(currentTool()->type(), BUCKETFILLEXPAND);
268}
269
270void ToolManager::setBucketFillReferenceMode(int referenceMode)
271{
272 currentTool()->setFillReferenceMode(referenceMode);
273 emit toolPropertyChanged(currentTool()->type(), BUCKETFILLLAYERREFERENCEMODE);
274}
275
276void ToolManager::setUseFillContour(bool useFillContour)
277{
278 currentTool()->setUseFillContour(useFillContour);
279 emit toolPropertyChanged(currentTool()->type(), FILLCONTOUR);
280}
281
282void ToolManager::setShowSelectionInfo(bool b)
283{
284 currentTool()->setShowSelectionInfo(b);
285}
286
287void ToolManager::setShowCameraPath(bool enabled)
288{
289 CameraTool* cameraTool = static_cast<CameraTool*>(getTool(CAMERA));
290 cameraTool->setShowCameraPath(enabled);
291 emit toolPropertyChanged(cameraTool->type(), CAMERAPATH);
292}
293
294void ToolManager::resetCameraPath()
295{
296 CameraTool* cameraTool = static_cast<CameraTool*>(getTool(CAMERA));
297 cameraTool->resetCameraPath();
298 emit toolPropertyChanged(cameraTool->type(), CAMERAPATH);
299}
300
301void ToolManager::resetCameraTransform(CameraFieldOption option)
302{
303 CameraTool* cameraTool = static_cast<CameraTool*>(getTool(CAMERA));
304 cameraTool->resetTransform(option);
305}
306
307void ToolManager::setCameraPathDotColor(int dotColorNum)
308{
309 CameraTool* cameraTool = static_cast<CameraTool*>(getTool(CAMERA));
310 cameraTool->setPathDotColorType(static_cast<DotColorType>(dotColorNum));
311 emit toolPropertyChanged(cameraTool->type(), CAMERAPATH);
312}
313
314bool ToolManager::bucketReferenceModeIsCurrentLayer(int referenceMode) const
315{
316 return referenceMode == 0;
317}
318
319// Switches on/off two actions
320// eg. if x = true, then y = false
321int ToolManager::propertySwitch(bool condition, int tool)
322{
323 int value = 0;
324 int newValue = 0;
325
326 if (condition == true)
327 {
328 value = -1;
329 newValue = mOldValue;
330 mOldValue = tool;
331 }
332 else if (condition == false)
333 {
334 value = (newValue == 1) ? 1 : mOldValue;
335 }
336 return value;
337}
338
339void ToolManager::tabletSwitchToEraser()
340{
341 mTabletEraserTool = getTool(ERASER);
342
343 // We should only notify a tool change if we're positive that the state has changed and it should only happen once
344 // if the user for some reason is using another temporary tool at the same time, that takes first priority
345 if (mTemporaryTool == nullptr)
346 {
347 emit toolChanged(ERASER);
348 }
349}
350
351void ToolManager::tabletRestorePrevTool()
352{
353 if (mTemporaryTool == nullptr && mTabletEraserTool != nullptr)
354 {
355 mTabletEraserTool = nullptr;
356 emit toolChanged(currentTool()->type());
357 }
358}
359
360bool ToolManager::setTemporaryTool(ToolType eToolType, QFlags<Qt::Key> keys, Qt::KeyboardModifiers modifiers)
361{
362 if (mTemporaryTool != nullptr) return false;
363 mTemporaryTriggerKeys = keys;
364 mTemporaryTriggerModifiers = modifiers;
365 mTemporaryTriggerMouseButtons = Qt::NoButton;
366 setTemporaryTool(eToolType);
367 return true;
368}
369
370bool ToolManager::setTemporaryTool(ToolType eToolType, Qt::MouseButtons buttons)
371{
372 if (mTemporaryTool != nullptr) return false;
373 mTemporaryTriggerKeys = {};
374 mTemporaryTriggerModifiers = Qt::NoModifier;
375 mTemporaryTriggerMouseButtons = buttons;
376 setTemporaryTool(eToolType);
377 return true;
378}
379
380bool ToolManager::tryClearTemporaryTool(Qt::Key key)
381{
382 Qt::KeyboardModifier modifier = Qt::NoModifier;
383 switch(key)
384 {
385 case Qt::Key_Control:
386 modifier = Qt::ControlModifier;
387 break;
388 case Qt::Key_Shift:
389 modifier = Qt::ShiftModifier;
390 break;
391 case Qt::Key_Alt:
392 modifier = Qt::AltModifier;
393 break;
394 case Qt::Key_Meta:
395 modifier = Qt::MetaModifier;
396 break;
397 default:
398 break;
399 }
400
401 if (mTemporaryTriggerKeys.testFlag(key) ||
402 mTemporaryTriggerModifiers.testFlag(modifier))
403 {
404 clearTemporaryTool();
405 return true;
406 }
407 return false;
408}
409
410bool ToolManager::tryClearTemporaryTool(Qt::MouseButton button)
411{
412 if (mTemporaryTriggerMouseButtons != Qt::NoButton && mTemporaryTriggerMouseButtons.testFlag(button))
413 {
414 clearTemporaryTool();
415 return true;
416 }
417 return false;
418}
419
420void ToolManager::setTemporaryTool(ToolType eToolType)
421{
422 mTemporaryTool = getTool(eToolType);
423 emit toolChanged(eToolType);
424}
425
426void ToolManager::clearTemporaryTool()
427{
428 if (mTemporaryTool) {
429 mTemporaryTool->leavingThisTool();
430 mTemporaryTool = nullptr;
431 }
432 mTemporaryTriggerKeys = {};
433 mTemporaryTriggerModifiers = Qt::NoModifier;
434 mTemporaryTriggerMouseButtons = Qt::NoButton;
435 emit toolChanged(currentTool()->type());
436}
BaseManager
Definition: basemanager.h:29
BaseTool
Definition: basetool.h:70
BaseTool::leavingThisTool
virtual bool leavingThisTool()
Will clean up active connections.
Definition: basetool.cpp:69
BaseTool::enteringThisTool
virtual bool enteringThisTool()
Setup active connections here that should only emit while tool is active leavingThisTool will handle ...
Definition: basetool.h:140
BrushTool
Definition: brushtool.h:27
BucketTool
Definition: buckettool.h:30
CameraTool
Definition: cameratool.h:45
Editor
Definition: editor.h:71
EraserTool
Definition: erasertool.h:24
EyedropperTool
Definition: eyedroppertool.h:27
HandTool
Definition: handtool.h:26
MoveTool
Definition: movetool.h:31
Object
Definition: object.h:42
PenTool
Definition: pentool.h:26
PencilTool
Definition: penciltool.h:27
PolylineTool
Definition: polylinetool.h:26
SelectTool
Definition: selecttool.h:31
SmudgeTool
Definition: smudgetool.h:24
Status
Definition: pencilerror.h:40
ToolManager::bucketReferenceModeIsCurrentLayer
bool bucketReferenceModeIsCurrentLayer(int referenceMode) const
Layer mode will be enforced by the the choice the reference mode selected.
Definition: toolmanager.cpp:314
QFlags
QFlags::testFlag
bool testFlag(Enum flag) const const
QHash::insert
QHash::iterator insert(const Key &key, const T &value)
QHash::values
QList< T > values() const const
Qt::Key
Key
Qt::KeyboardModifiers
typedef KeyboardModifiers
Qt::NoButton
NoButton
Generated on Thu May 8 2025 04:47:53 for Pencil2D by doxygen 1.9.6 based on revision 4513250b1d5b1a3676ec0e67b06b7a885ceaae39