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