1// Aseprite
2// Copyright (C) 2019-2022 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_UI_EDITOR_DRAWING_STATE_H_INCLUDED
9#define APP_UI_EDITOR_DRAWING_STATE_H_INCLUDED
10#pragma once
11
12#include "app/tools/pointer.h"
13#include "app/tools/velocity.h"
14#include "app/ui/editor/delayed_mouse_move.h"
15#include "app/ui/editor/standby_state.h"
16#include "base/time.h"
17#include "obs/connection.h"
18#include <memory>
19
20namespace app {
21 namespace tools {
22 class ToolLoop;
23 class ToolLoopManager;
24 }
25
26 class CommandExecutionEvent;
27
28 class DrawingState : public StandbyState
29 , DelayedMouseMoveDelegate {
30 public:
31 DrawingState(Editor* editor,
32 tools::ToolLoop* loop,
33 const DrawingType type);
34 virtual ~DrawingState();
35 virtual void onBeforePopState(Editor* editor) override;
36 virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override;
37 virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
38 virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
39 virtual bool onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) override;
40 virtual bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override;
41 virtual bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override;
42 virtual bool onScrollChange(Editor* editor) override;
43 virtual bool onUpdateStatusBar(Editor* editor) override;
44 virtual void onExposeSpritePixels(const gfx::Region& rgn) override;
45
46 // Drawing state doesn't require the brush-preview because we are
47 // already drawing (viewing the real trace).
48 virtual bool requireBrushPreview() override { return false; }
49
50 // Don't show layer edges when we're drawing as the cel
51 // position/bounds is modified and the feedback is
52 // confusing. (This is the original behavior, maybe in the future
53 // we could fix this in other way and show how the edge of the cel
54 // is expanded dynamically while we paint.)
55 virtual bool allowLayerEdges() override { return false; }
56
57 virtual bool getGridBounds(Editor* editor, gfx::Rect& gridBounds) override;
58
59 void initToolLoop(Editor* editor,
60 const ui::MouseMessage* msg,
61 const tools::Pointer& pointer);
62
63 // Used to send a movement() to the ToolLoopManager when
64 // Shift+brush tool is used to paint a line.
65 void sendMovementToToolLoop(const tools::Pointer& pointer);
66
67 void notifyToolLoopModifiersChange(Editor* editor);
68
69 private:
70 void handleMouseMovement();
71 bool canInterpretMouseMovementAsJustOneClick();
72 bool canExecuteCommands();
73 void onBeforeCommandExecution(CommandExecutionEvent& ev);
74 void destroyLoopIfCanceled(Editor* editor);
75 void destroyLoop(Editor* editor);
76
77 // DelayedMouseMoveDelegate impl
78 void onCommitMouseMove(Editor* editor,
79 const gfx::PointF& spritePos) override;
80
81 Editor* m_editor;
82 DrawingType m_type;
83 DelayedMouseMove m_delayedMouseMove;
84
85 // The tool-loop.
86 std::unique_ptr<tools::ToolLoop> m_toolLoop;
87
88 // Tool-loop manager
89 std::unique_ptr<tools::ToolLoopManager> m_toolLoopManager;
90
91 // These fields are used to detect a selection tool cancelation
92 // (deselect command) when the user just click (press and release
93 // the mouse button in the "same location" approximately).
94 bool m_mouseMoveReceived;
95 gfx::Point m_mouseMaxDelta;
96 gfx::Point m_mouseDownPos;
97 base::tick_t m_mouseDownTime;
98
99 // Stores the last mouse pointer, used to re-use the latest mouse
100 // button when onScrollChange() event is received.
101 tools::Pointer m_lastPointer;
102
103 // Used to calculate the velocity of the mouse (whch is a sensor
104 // to generate dynamic parameters).
105 tools::VelocitySensor m_velocity;
106
107 // Used to know if the button was pressed after the DrawingState
108 // was initialized. In this way we can cancel the ToolLoop if the
109 // Shift press is used to draw a line, but then released without a
110 // mouse click.
111 bool m_mousePressedReceived;
112
113 // Locks the scroll
114 bool m_processScrollChange;
115
116 obs::scoped_connection m_beforeCmdConn;
117 };
118
119} // namespace app
120
121#endif // APP_UI_EDITOR_DRAWING_STATE_H_INCLUDED
122