From 2202e87c466803eeaddd974006aa9950d8e0d067 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sun, 15 Mar 2026 12:23:21 +0200 Subject: feat!: Split into separate files --- Animation.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Animation.c (limited to 'Animation.c') diff --git a/Animation.c b/Animation.c new file mode 100644 index 0000000..3ce79dc --- /dev/null +++ b/Animation.c @@ -0,0 +1,110 @@ +#include "Animation.h" +#include + +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); + } +} -- cgit v1.2.3