1 // Copyright (c) 2015 Sergio Gonzalez. All rights reserved.
2 // License: https://github.com/serge-rgb/milton#license
3 
4 
5 #pragma once
6 
7 #include "memory.h"
8 #include "system_includes.h"
9 #include "canvas.h"
10 #include "DArray.h"
11 #include "profiler.h"
12 
13 #define STROKE_MAX_POINTS           2048
14 #define MILTON_DEFAULT_SCALE        (1 << 10)
15 #define NO_PRESSURE_INFO            -1.0f
16 #define MAX_INPUT_BUFFER_ELEMS      32
17 #define MILTON_MAX_BRUSH_SIZE       300
18 #define HOVER_FLASH_THRESHOLD_MS    500  // How long does the hidden brush hover show when it has changed size.
19 #define MODE_STACK_MAX 64
20 
21 struct MiltonGLState
22 {
23     GLuint quad_program;
24     GLuint texture;
25     GLuint vbo;
26 };
27 
28 enum class MiltonMode
29 {
30     PEN,
31     ERASER,
32     PRIMITIVE, // Lines, circles, etc.
33     EXPORTING,
34     EYEDROPPER,
35     HISTORY,
36     PEEK_OUT,
37     DRAG_BRUSH_SIZE,
38     TRANSFORM,  // Scale and rotate
39 
40     MODE_COUNT,
41 };
42 
43 enum BrushEnum
44 {
45     BrushEnum_PEN,
46     BrushEnum_ERASER,
47     BrushEnum_PRIMITIVE,
48 
49     BrushEnum_NOBRUSH,  // Non-painting modes
50 
51     BrushEnum_COUNT,
52 };
53 
54 enum HistoryElementType
55 {
56     HistoryElement_STROKE_ADD,
57     //HistoryElement_LAYER_DELETE,
58 };
59 
60 struct HistoryElement
61 {
62     int type;
63     i32 layer_id;  // HistoryElement_STROKE_ADD
64 };
65 
66 struct MiltonGui;
67 struct RenderBackend;
68 struct CanvasView;
69 struct Layer;
70 struct MiltonPersist;
71 struct MiltonBindings;
72 
73 // Stuff than can be reset when unloading a canvas
74 struct CanvasState
75 {
76     Arena  arena;
77 
78     i32         layer_guid;  // to create unique ids;
79     Layer*      root_layer;
80     Layer*      working_layer;
81 
82     DArray<HistoryElement> history;
83     DArray<HistoryElement> redo_stack;
84     //Layer**         layer_graveyard;
85     DArray<Stroke>         stroke_graveyard;
86 
87     i32         stroke_id_count;
88 };
89 
90 enum PrimitiveFSM
91 {
92     Primitive_WAITING,
93     Primitive_DRAWING,
94     Primitive_DONE,
95 };
96 
97 #pragma pack(push, 1)
98 struct MiltonSettings
99 {
100     v3f background_color;
101     float peek_out_increment;
102 
103     MiltonBindings bindings;
104 };
105 #pragma pack(pop)
106 
107 struct Eyedropper
108 {
109     u8* buffer;
110 };
111 
112 struct SmoothFilter
113 {
114     b32 first;
115     v2f prediction;
116     v2l center;
117 };
118 
119 enum PeekOutFlags
120 {
121     PeekOut_CLICK_TO_EXIT = (1<<0),
122 };
123 
124 struct PeekOut
125 {
126     WallTime begin_anim_time;
127     b32 peek_out_ended;
128 
129     i64 high_scale;
130     i64 low_scale;
131 
132     v2l begin_pan;
133     v2l end_pan;
134 
135     int flags /*PeekOutFlags*/;
136 };
137 
138 struct RenderSettings
139 {
140     b32 do_full_redraw;
141 };
142 
143 struct MiltonDragBrush
144 {
145     i32 start_size;
146     i32 brush_idx;
147     v2i start_point;
148 };
149 
150 enum class TransformModeFSM
151 {
152     START,
153     ROTATING,
154 };
155 
156 struct TransformMode
157 {
158     TransformModeFSM fsm;
159     v2f last_point;
160 };
161 
162 struct Milton
163 {
164     u32 flags;  // See MiltonStateFlags
165 
166     i32 max_width;
167     i32 max_height;
168 
169 #if MILTON_SAVE_ASYNC
170     SDL_mutex*  save_mutex;
171     i64         save_flag;   // See SaveEnum
172     SDL_cond*   save_cond;
173     SDL_Thread* save_thread;
174 #endif
175     PlatformState* platform;
176 
177     // ---- The Painting
178     CanvasState*    canvas;
179     CanvasView*     view;
180 
181     Eyedropper* eyedropper;
182 
183     Brush       brushes[BrushEnum_COUNT];
184     i32         brush_sizes[BrushEnum_COUNT];  // In screen pixels
185 
186     Stroke      working_stroke;
187     // ----  // gui->picker.info also stored
188 
189     // Read only
190     // Set these with milton_switch_mode and milton_leave_mode
191     MiltonMode current_mode;
192     MiltonMode mode_stack[MODE_STACK_MAX];
193     sz n_mode_stack;
194 
195     enum GuiVisibleCategory {
196         GuiVisibleCategory_DRAWING,
197         GuiVisibleCategory_EXPORTING,
198         GuiVisibleCategory_OTHER,
199 
200         GuiVisibleCategory_COUNT,
201     };
202     bool mode_gui_visibility[GuiVisibleCategory_COUNT];
203 
204     PrimitiveFSM primitive_fsm;
205 
206     SmoothFilter* smooth_filter;
207 
208     RenderSettings render_settings;
209     RenderBackend* renderer;
210 
211     // Heap
212     Arena       root_arena;     // Lives forever
213     Arena       canvas_arena;   // Gets reset every canvas.
214 
215     // Subsystems
216     MiltonGLState* gl;
217     MiltonGui* gui;
218     MiltonSettings* settings;  // User settings
219     MiltonPersist* persist;
220     MiltonDragBrush* drag_brush;
221     PeekOut* peek_out;
222     TransformMode* transform;
223 
224 #if MILTON_ENABLE_PROFILING
225     b32 viz_window_visible;
226     GraphData graph_frame;
227 #endif
228 };
229 
230 enum MiltonStateFlags
231 {
232     MiltonStateFlags_RUNNING                = 1 << 0,
233     MiltonStateFlags_FINISH_CURRENT_STROKE  = 1 << 1,
234                                             // 1 << 2 unused
235     MiltonStateFlags_JUST_SAVED             = 1 << 3,
236     MiltonStateFlags_NEW_CANVAS             = 1 << 4,
237     MiltonStateFlags_DEFAULT_CANVAS         = 1 << 5,
238                                             // 1 << 6 unused
239                                             // 1 << 7 unused
240                                             // 1 << 8 unused
241     MiltonStateFlags_LAST_SAVE_FAILED       = 1 << 9,
242     MiltonStateFlags_MOVE_FILE_FAILED       = 1 << 10,
243     MiltonStateFlags_BRUSH_SMOOTHING        = 1 << 11,
244 };
245 
246 enum MiltonInputFlags
247 {
248     MiltonInputFlags_NONE = 0,
249 
250     MiltonInputFlags_FULL_REFRESH        = 1 << 0,
251     MiltonInputFlags_END_STROKE          = 1 << 1,
252     MiltonInputFlags_UNDO                = 1 << 2,
253     MiltonInputFlags_REDO                = 1 << 3,
254                                         // 1 << 4 free to use
255                                         // 1 << 5 free to use
256                                         // 1 << 6 free
257     MiltonInputFlags_PANNING             = 1 << 7,
258     MiltonInputFlags_IMGUI_GRABBED_INPUT = 1 << 8,
259     MiltonInputFlags_SAVE_FILE           = 1 << 9,
260     MiltonInputFlags_OPEN_FILE           = 1 << 10,
261                                         // 1 << 11 free
262     MiltonInputFlags_CLICKUP             = 1 << 12,
263 };
264 
265 struct MiltonInput
266 {
267     int flags;  // MiltonInputFlags
268     MiltonMode mode_to_set;
269 
270     v2l  points[MAX_INPUT_BUFFER_ELEMS];
271     f32  pressures[MAX_INPUT_BUFFER_ELEMS];
272     i32  input_count;
273 
274     v2i  click;
275     i32  scale;
276     v2l  pan_delta;
277 };
278 
279 
280 enum SaveEnum
281 {
282     SaveEnum_WAITING,
283     SaveEnum_SAVE_REQUESTED,
284     SaveEnum_KILL,
285 };
286 
287 enum MiltonInitFlags
288 {
289     MiltonInit_DEFAULT = 0,
290     MiltonInit_FOR_TEST = 1<<0,  // No graphics layer. No reading from disk
291 };
292 void milton_init(Milton* milton, i32 width, i32 height, f32 ui_scale, PATH_CHAR* file_to_open, MiltonInitFlags init_flags = MiltonInit_DEFAULT);
293 
294 // Expects absolute path
295 void milton_set_canvas_file(Milton* milton, PATH_CHAR* fname);
296 void milton_set_default_canvas_file(Milton* milton);
297 void milton_set_last_canvas_fname(PATH_CHAR* last_fname);
298 void milton_unset_last_canvas_fname();
299 
300 void milton_save_postlude(Milton* milton);
301 
302 
303 void milton_reset_canvas(Milton* milton);
304 void milton_reset_canvas_and_set_default(Milton* milton);
305 
306 void milton_gl_backend_draw(Milton* milton);
307 
308 b32 current_mode_is_for_drawing(Milton const* milton);
309 
310 void milton_toggle_gui_visibility(Milton* milton);
311 void milton_set_gui_visibility(Milton* milton, b32 visible);
312 
313 int     milton_get_brush_enum(Milton const* milton);
314 i32     milton_get_brush_radius(Milton const* milton);   // Between 0 and k_max_brush_size
315 void    milton_set_brush_size(Milton* milton, i32 size);
316 void    milton_increase_brush_size(Milton* milton);
317 void    milton_decrease_brush_size(Milton* milton);
318 float   milton_get_brush_alpha(Milton const* milton);
319 void    milton_set_brush_alpha(Milton* milton, float alpha);
320 
321 // Returns false if the pan_delta moves the pan vector outside of the canvas.
322 void milton_resize_and_pan(Milton* milton, v2l pan_delta, v2i new_screen_size);
323 
324 MiltonMode milton_leave_mode(Milton* milton);
325 void milton_enter_mode(Milton* milton, MiltonMode mode);
326 
327 // Our "game loop" inner function.
328 void milton_update_and_render(Milton* milton, MiltonInput const* input);
329 
330 void milton_try_quit(Milton* milton);
331 
332 void milton_new_layer(Milton* milton);
333 void milton_new_layer_with_id(Milton* milton, i32 new_id);
334 void milton_set_working_layer(Milton* milton, Layer* layer);
335 void milton_delete_working_layer(Milton* milton);
336 void milton_set_background_color(Milton* milton, v3f background_color);
337 
338 // Set the center of the zoom
339 void milton_set_zoom_at_point(Milton* milton, v2i zoom_center);
340 void milton_set_zoom_at_screen_center(Milton* milton);
341 
342 b32  milton_brush_smoothing_enabled(Milton* milton);
343 void milton_toggle_brush_smoothing(Milton* milton);
344 
345 
346 void peek_out_trigger_start(Milton* milton, int flags/* PeekOutFlags*/ = 0);
347 void peek_out_trigger_stop(Milton* milton);
348 
349 void transform_start(Milton* milton, v2i pointer);
350 void transform_stop(Milton* milton);
351 
352 void drag_brush_size_start(Milton* milton, v2i pointer);
353 void drag_brush_size_stop(Milton* milton);
354