1// Aseprite
2// Copyright (C) 2019-2021 Igara Studio S.A.
3// Copyright (C) 2001-2017 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifndef APP_TOOLS_TOOL_LOOP_MANAGER_H_INCLUDED
9#define APP_TOOLS_TOOL_LOOP_MANAGER_H_INCLUDED
10#pragma once
11
12#include "app/tools/dynamics.h"
13#include "app/tools/pointer.h"
14#include "app/tools/stroke.h"
15#include "doc/brush.h"
16#include "gfx/point.h"
17#include "gfx/region.h"
18
19#include <vector>
20
21namespace gfx { class Region; }
22
23namespace app {
24namespace tools {
25
26class ToolLoop;
27
28// Class to manage the drawing tool (editor <-> tool interface).
29//
30// The flow is this:
31// 1. The user press a mouse button in a Editor widget
32// 2. The Editor creates an implementation of ToolLoop and use it
33// with the ToolLoopManager constructor
34// 3. The ToolLoopManager is used to call
35// the following methods:
36// - ToolLoopManager::prepareLoop
37// - ToolLoopManager::pressButton
38// 4. If the user moves the mouse, the method
39// - ToolLoopManager::movement
40// is called.
41// 5. When the user release the mouse:
42// - ToolLoopManager::releaseButton
43//
44class ToolLoopManager {
45public:
46 // Contructs a manager for the ToolLoop delegate.
47 ToolLoopManager(ToolLoop* toolLoop);
48 virtual ~ToolLoopManager();
49
50 // Returns true if the loop was canceled by the user
51 bool isCanceled() const;
52
53 // Called when the tool loop must be canceled because another
54 // command was executed or the Esc key pressed.
55 void cancel();
56
57 // Called when the tool loop ends (this will commit or rollback the
58 // tool loop).
59 void end();
60
61 // Should be called when the user start a tool-trace (pressing the
62 // left or right button for first time in the editor).
63 void prepareLoop(const Pointer& pointer);
64
65 // Should be called when the ToolLoop::getModifiers()
66 // value was modified (e.g. when the user press/release a key).
67 void notifyToolLoopModifiersChange();
68
69 // Should be called each time the user presses a mouse button.
70 void pressButton(const Pointer& pointer);
71
72 // Should be called each time the user releases a mouse button.
73 //
74 // Returns true if the tool-loop should continue, or false
75 // if the editor should release the mouse capture.
76 bool releaseButton(const Pointer& pointer);
77
78 // Should be called each time the user moves the mouse inside the editor.
79 void movement(Pointer pointer);
80
81 const Pointer& lastPointer() const { return m_lastPointer; }
82
83private:
84 void doLoopStep(bool lastStep);
85 void snapToGrid(Stroke::Pt& pt);
86 Stroke::Pt getSpriteStrokePt(const Pointer& pointer);
87 bool useDynamics() const;
88 void adjustPointWithDynamics(const Pointer& pointer, Stroke::Pt& pt);
89
90 void calculateDirtyArea(const Strokes& strokes);
91
92 ToolLoop* m_toolLoop;
93 bool m_canceled;
94 Stroke m_stroke;
95 Pointer m_lastPointer;
96 gfx::Region m_dirtyArea;
97 gfx::Region m_nextDirtyArea;
98 doc::Brush m_brush0;
99 DynamicsOptions m_dynamics;
100 gfx::PointF m_stabilizerCenter;
101};
102
103} // namespace tools
104} // namespace app
105
106#endif
107