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
|
#include "Animation.h"
#include <stdlib.h>
struct AnimationEventNode {
AnimationEventNode* next;
u32 startFrame;
u32 endFrame;
PixelRenderer renderCallback;
void* privateData;
};
AnimationEventNode*
AnimationEventNode_new(u32 startFrame, u32 endFrame, PixelRenderer renderCallback, void* privateData) {
AnimationEventNode* aen = (AnimationEventNode*)malloc(sizeof(AnimationEventNode));
aen->next = NULL;
aen->startFrame = startFrame;
aen->endFrame = endFrame;
aen->renderCallback = renderCallback;
aen->privateData = privateData;
return aen;
}
Animation
Animation_new(u32 width, u32 height, u32 frameCount) {
return (Animation){
.width = width,
.height = height,
.frameCount = frameCount,
.duplicateFrames = 0,
.frameBuffer = RGBImage_new(width, height),
.events = NULL,
};
}
void
Animation_free(Animation anim) {
RGBImage_free(anim.frameBuffer);
while (anim.events != NULL) {
AnimationEventNode* toFree = anim.events;
anim.events = anim.events->next;
free(toFree);
}
}
void
Animation_delete(Animation* anim) {
Animation_free(*anim);
anim->width = anim->height = anim->frameCount = 0;
RGBImage_delete(&anim->frameBuffer);
}
void
Animation_pushEvent(Animation* anim, u32 startFrame, u32 endFrame, PixelRenderer renderer, void* privateData) {
if (anim->events == NULL) {
anim->events = AnimationEventNode_new(startFrame, endFrame, renderer, privateData);
return;
}
AnimationEventNode* prevNode = NULL, *currNode = anim->events;
while (currNode != NULL) {
if (startFrame < currNode->startFrame) {
prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData);
prevNode->next->next = currNode;
return;
}
prevNode = currNode;
currNode = currNode->next;
}
prevNode->next = AnimationEventNode_new(startFrame, endFrame, renderer, privateData);
}
void
Animation_render(Animation* anim) {
for (int currFrame = 0; currFrame < anim->frameCount; ++currFrame) {
if (anim->events != NULL)
for (i32 r = 0; r < anim->frameBuffer.width; ++r)
for (i32 c = 0; c < anim->frameBuffer.height; ++c) {
for (AnimationEventNode* aen = anim->events; aen != NULL && aen->startFrame <= currFrame; aen = aen->next) {
ARGB* pixel = RGBImage_at(anim->frameBuffer, r, c);
ARGB newPixel = aen->renderCallback(anim, currFrame, *pixel, r, c, aen->privateData);
ARGB_merge(pixel, newPixel);
}
AnimationEventNode* prevNode = NULL, *currNode = anim->events;
while (currNode != NULL && currNode->startFrame <= currFrame) {
if (currNode->endFrame <= currFrame) {
if (prevNode != NULL)
prevNode->next = currNode->next;
else
anim->events = NULL;
free(currNode);
}
else {
prevNode = currNode;
currNode = currNode->next;
}
}
}
ppm6_write(stdout, anim->frameBuffer);
for (u32 duplicates = 0; duplicates < anim->duplicateFrames; ++duplicates)
ppm6_write(stdout, anim->frameBuffer);
}
}
|