summaryrefslogtreecommitdiff
path: root/main.h
blob: 50242c318ce6ea07ad80054cb82effdb8ce58d6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
enum instruction_mode {
    instruction_mode_scalar,
#if ARM
    instruction_mode_neon,
#else
    instruction_mode_sse,
    instruction_mode_avx
#endif
};

enum memory_table_list {

    // F = file attributes
    // P = persistent data, but not file-based
    // B = cached data, often cleared

    P_AVInfo,
    P_VectorPoints,
    P_UndoBuffer,
    P_MiscCache,

    // The structs that these four blocks correspond to (project_layer, effect,
    // keyframe_block, char[STRING_SIZE]) are guranteed equal size.
    F_Layers,
    F_Effects,
    F_Keyframes,
    F_Strings,

    B_LayerBitmaps,
    B_LoadedBitmaps,
};

struct memory_table {
    char *Name;
    void *Address;
    uint64 CurrentPosition;
    uint64 Size;
    uint32 NumberOfPointers;
    uint32 PointerIndex;
};

struct global_memory {
    void *Address;
    uint64 CurrentPosition;
    uint64 Size;
};

struct source;

struct cached_bitmap {
    source *SourceOwner;     // Which source it belongs to. Currently used to dereference the bitmap.
    void *Data;             // Unpacked data loaded from the source file.
    uint32 Frame;           // What frame it is.
};

enum action_type {
    action_type_change_u16,
    action_type_change_i16,
    action_type_change_u32,
    action_type_change_i32,
    action_type_change_r32,
    action_type_change_u64,
    action_type_change_ptr,
    action_type_change_string,
    action_type_shift_keyframe
};

enum action_entry_type {
    action_entry_layerinit,
    action_entry_default
};

struct action_entry {
    char *Name;
    action_entry_type Type;
    void *ExtraPointer;
    uint16 NumberOfActions;
};

struct action_entries {
    action_entry Entry[1024];
    uint16 Index;
    uint16 NumberOfEntries;
};

struct memory {
    memory_table Slot[16];
    cached_bitmap Bitmap[4096];
    void *Scratch;                  // 64 MB of data
    action_entries Action;
};

struct property_channel;
struct project_layer;

enum keyframe_type
{
    linear,
    bezier,
    hold
};

// NOTE(fox): One val slot holds 16 bytes of data.

enum var_type
{
    type_real,
    type_color,
    type_blendmode
};


static char* BlendmodeNames[] = {
    "Normal",
    "Multiply",
    "Color Burn",
    "Linear Burn",
    "Add",
    "Screen",
    "Overlay",
    "Soft Light",
    "Hard Light",
    "Subtract",
    "Divide",
    "Difference"
};

enum blend_mode
{
    blend_normal,
    blend_multiply,
    blend_colorburn,
    blend_linearburn,
    blend_add,
    blend_screen,
    blend_overlay,
    blend_softlight,
    blend_hardlight,
    blend_subtract,
    blend_divide,
    blend_difference
};


union val {
    real32 f;
    v4 col;
    blend_mode blendmode;
};

struct keyframe {
    val Value;
    // NOTE(fox): Frame values are relative to the layer's FrameOffset! This is
    // done to reduce the footprint of layer moving in the undo tree.
    int32 FrameNumber;
    keyframe_type Type;
    bool32 IsSelected;
    // The X coordinate for the tangent is in keyframes, and the Y is in units.
    // Probably should think of something smarter.
    v2 TangentLeft;
    v2 TangentRight;
    // NOTE(fox): We need some sort of unique constant to give to ImGui in
    // order for dragging to work.
    uint32 ImguiID;
};

struct keyframe_block {
    keyframe Keyframe[MAX_KEYFRAMES_PER_BLOCK];
};

struct property_channel {
    char *Name;
    keyframe_block *KeyframeBlock[MAX_KEYFRAME_BLOCKS];
    uint16 NumberOfKeyframeBlocks;
    uint16 NumberOfSelectedKeyframes;
    uint16 NumberOfTotalKeyframes;
    val CurrentValue;
    val MaxVal;
    val MinVal;
    val ScrubVal;           // increment when dragging on sliders, etc.
    var_type VarType;

    bool32 IsToggled;
};

struct property_header
{
    char *Name;
    val Value;
    var_type VarType;
    val MinVal;
    val MaxVal;
};

// Information about a particular file.

enum source_type {
    source_type_none,
    source_type_video,
    source_type_image
};

// Probably best to consider source_info a part of the file data so we don't
// have to re-check each source on every project load. (except for AVInfo)

struct source_info {
    // Image and video
    uint16 Width;
    uint16 Height;
    uint16 BytesPerPixel;

    // Video only
    real32 FPS;
    real32 AvgPTSPerFrame; // set by Libav
};

struct source {
    char *Path;
    source_type SourceType;
    source_info Info;
};

// Bitmaps from files are loaded into these temporary cache blocks.

struct gl_effect_layer {
    bool32 Initialized;
    GLuint Texture;
    GLuint FramebufferObject;
    uint32 Color_Renderbuffer;
    uint32 Stencil_Renderbuffer;
};

struct layer_bitmap_info {
    // Image and video
    void *BitmapBuffer;       // Each layer has a persistent bitmap that the source data gets packed into.
    int32 FrameOffset;        // The "true" position of the layer, separate from StartFrame. Starts at zero and only gets incremented when the layer is moved.
    bool32 ToUpdate = 1;

    gl_effect_layer Test;
    gl_effect_layer TestM;

    // TODO(fox): Find a better place to store this. Either give effects a more
    // fleshed-out API to add things to a struct like this or integrate into ImGui.
    void *HistogramVals;        // 256*5 floats (all channel average + RGBA).
    uint16 LevelsSelector;      // Which channel is currently active

    // Video only
    int32 CurrentFrame = -1;  // The last frame number rendered to the bitmap. -1 gurantees a load upon layer creation.
    void *AVInfo;        // Internal data containing current frame info
};

// NOTE(fox): I use the term "comp" (composition) to mean the canvas that is
// being rendered to, since it's what I'm used to from AE.
struct comp_buffer {
    uint16 Width;
    uint16 Height;
    uint16 BytesPerPixel;
    void *PackedBuffer;
    void *UnpackedBuffer;
};

struct transform_info {
    real32 XAxisPX;
    real32 XAxisPY;
    real32 YAxisPX;
    real32 YAxisPY;
    real32 LayerWidth;
    real32 LayerHeight;
    uint32 FullLayerWidth;
    uint32 FullLayerHeight;
    real32 LayerOpacity;
    blend_mode BlendMode;
    real32 OriginX;
    real32 OriginY;
    uint32 BufferPitch;
    uint32 LayerPitch;
    rectangle ClipRect;
    void *SourceBuffer;
};

struct mask_point {
    v2 Pos;
    bool32 HandleBezier;
    bool32 IsSelected;
    v2 TangentLeft;
    v2 TangentRight;
};

struct mask {
    mask_point Point[16];
    bool32 IsClosed;
    uint16 NumberOfPoints;
    uint16 NumberOfSelectedPoints;
    void *TriangulatedPointCache;
    uint32 NumberOfVerts;
};

struct project_layer {
    char *Name;
    blend_mode BlendMode;

    union
    {
        property_channel Property[8];
        struct
        {
            property_channel x;
            property_channel y;
            property_channel ax;
            property_channel ay;
            property_channel rotation;
            property_channel scale;
            property_channel opacity;
            property_channel time;
        };
    };

    bool32 IsSelected;

    source *Source;
    layer_bitmap_info BitmapInfo;

    effect *Effect[MAX_EFFECTS];
    uint16 NumberOfEffects;

    mask Mask[MAX_MASKS];
    uint16 NumberOfMasks;

    int32 StartFrame;
    int32 EndFrame;

    uint32 LayerColor;

    // For rendering
    transform_info TransformInfo;
};


// NOTE(fox): I have no idea how people normally do selection; currently I'm
// treating it more "immediate." Instead of updating a selection state as
// things are selected, I'm just calling functions that go through all the
// layers and keyframes to look for the IsSelected bool. If this causes
// lag I'll switch it to the former.

struct temp_layer_list {
    int16 LayerIndex[MAX_LAYERS];
};

struct temp_keyframe_list {
    keyframe *SelectedKeyframe[50];
    uint16 Amount;
};

struct project_data
{
    uint16 Width;
    uint16 Height;
    uint16 FPS;
    uint32 NumberOfFrames;
    int32 StartFrame;
    int32 EndFrame;
    int32 CurrentFrame;

    // NOTE(fox): Currently I'm handling layer sorting by just saying that
    // their order in memory is the order of the index and manually moving
    // their positions.

    project_layer *Layer[MAX_LAYERS];
    uint16 NumberOfSelectedLayers;
    uint16 NumberOfLayers;

    source Source[MAX_SOURCES];
    uint32 SourceSelected;
    uint16 NumberOfSources;
};

enum transforms_hotkey_interact {
    sliding_position,
    sliding_anchorpoint,
    sliding_scale,
    sliding_rotation
};

struct main_sdl
{
    SDL_Texture *Texture;
    SDL_Event Event;
    SDL_Window *Window;
    SDL_Renderer *Renderer;
};

// used to determine what to copy/paste, delete, etc
enum selection_type
{
    selection_none,
    selection_layer,
    selection_effect,
    selection_keyframe,
    selection_maskpoint,
    selection_source
};

char *ToolName[] {
    "Move",
    "Pen"
};

enum tool {
    tool_default,
    tool_pen,
    tool_count
};

struct pen_state {
    bool32 IsActive;
};

struct project_state
{
    bool32 UpdateKeyframes = 1;
    bool32 UpdateFrame = 1;                    // only refreshes frame; set UpdateKeyframes to update animation
    bool32 DebugDisableCache = 1;

    tool Tool = tool_default;
    pen_state Pen = {};

    uint16 LayersToRender[MAX_LAYERS];
    uint16 NumberOfLayersToRender;

    bool32 IsRunning = 1;
    bool32 IsPlaying;
    bool32 DemoButton = 1;
    bool32 GridButton = 1;

    uint16 NumberOfSelectedLayers;
    int16 MostRecentlySelectedLayer = -1;        // convenience for the properties panel
    selection_type RecentSelectionType = selection_none;

    bool32 IsInteracting;
    real32 InteractCache[4];        // we need to store the initial position in order to record it in the undo tree
    transforms_hotkey_interact TransformsHotkeyInteract;

    int32 MsgTime; // currently in "frames"
    char *Msg;

    ImGuiTextFilter filter;     // This filter API is pretty ballin'.
    bool32 RerouteEffects;      // Allows shift+space hotkey to gain focus on the effects panel.
};

struct brush_tool
{
      real32 Size;
      real32 Opacity;
      real32 Hardness;
};

enum focused_window
{
    focus_viewport,
    focus_properties,
    focus_timeline
};

struct ui_graph {
    property_channel *ChannelViewed;
    real32 WindowYOffset = 300;
    real32 UpperVal;
    real32 LowerVal;
    uint16 GraphWindowHeight;     // The size of the window enclosing the graph
};

struct ui
{
    real32 TimelineSplit = 600;
    real32 TimelineZoom;

    // Note that I don't use "zoom" to mean the scale in relation to the
    // original (i.e. default = 1.0f); it's the literal screen size in pixels
    // of the composition in the UI.
    ImVec2 CompZoom;
    ImVec2 CompPos;

    // Used to set UI values on the first frame. Some UI setup in Docking takes
    // more than 1 frame for some reason, so I'm temporarily extending it.
    bool32 Initializing = 4;

    // Custom scrolling for the timeline, as ImGui's didn't work well
    real32 ScrollXOffset;
    real32 ScrollYOffset;

    // NOTE(fox): Keeping track of mouse delta myself since the ImGui threshold
    // dragging API doesn't let you do things like subtract the delta easily.
    real32 DraggingKeyframeThreshold;
    real32 DraggingLayerThreshold;
    real32 DraggingTimelineThreshold;
    real32 KeyframeSpacing = 6;

    ImVec2 BoxStart = ImVec2(0,0);
    ImVec2 BoxEnd = ImVec2(0,0);
    bool32 BoxSelectActive = false;

    // Temporary varibles used when zooming in/out
    v2 TempZoomRatio = V2(1, 1);
    real32 TempZoomRatioTimeline = 0;
    real32 TempZoomRatioGraph = 0;

    focused_window FocusedWindow;           // Convenience for adding window-specific hotkeys.

    ui_graph Graph[4];
    uint16 NumberOfGraphsEnabled;

    bool32 TemporaryUpdateOverride;
};

struct imgui_buttonstate
{
    bool32 IsItemHovered;
    bool32 IsItemActive;
    bool32 IsItemActivated;
    bool32 IsItemDeactivated;
    bool32 LeftClick;
    bool32 RightClick;
};

struct timeline_properties
{
    rectangle Timeline;

    v2i MainWindow;
    uint16 WindowPadding;

    rectangle EffectPanel;

    rectangle Toolbar;
    rectangle ColorPanel;

    bool32 RenderSlidingBrush;

    uint16 CompX;
    uint16 CompY;
    uint16 TimelineZoom;
    uint16 CompScale;
    uint16 FramePadding;
    uint16 LayerPadding;
    uint16 TimelineCurrentFrame;
    int16 TimelineCurrentLayer;     // Signed as a shortcut for invalid on -1
    uint16 InfoTimelineSplit;
    bool32 DrawTimeline;
    bool32 DrawEffectPanel;
    bool32 DrawComp;
};

struct sdl_button
{
    bool32 IsDown;
    bool32 SingleClick; // More precisely, when button is released and no dragging/selecting events are happening.
    int HeldLength;
};

struct sdl_input
{
    v2i Mouse;
    sdl_button MouseButton[3];
    rectangle Selection;
};

struct render_queue
{
    project_data *File;
    project_state *State;
    comp_buffer *CompBuffer;
};

struct thread_info
{
    render_queue *RenderInfo;
    uint16 Index;
};

struct work_queue_entry {
    char *StringToPrint;
};

struct render_entry {
    rectangle RenderRegion;
};