Cleanup animation
This commit is contained in:
@@ -7,4 +7,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
PUBLIC
|
||||
easing.c
|
||||
animation.c
|
||||
animationproperty.c
|
||||
)
|
||||
|
||||
@@ -6,91 +6,74 @@
|
||||
#include "animation.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include <math.h>
|
||||
#include "util/math.h"
|
||||
|
||||
void animationInit(animation_t *anim) {
|
||||
memoryZero(anim, sizeof(animation_t));
|
||||
}
|
||||
|
||||
animationproperty_t *animationAddProperty(animation_t *anim, float_t *target) {
|
||||
animationproperty_t *animationAddProperty(animation_t *anim) {
|
||||
assertTrue(
|
||||
anim->propertyCount < ANIMATION_PROPERTY_COUNT_MAX,
|
||||
"Property count exceeds ANIMATION_PROPERTY_COUNT_MAX"
|
||||
);
|
||||
animationproperty_t *prop = &anim->properties[anim->propertyCount++];
|
||||
prop->target = target;
|
||||
prop->keyframeCount = 0;
|
||||
return prop;
|
||||
}
|
||||
|
||||
void animationPropertyAddKeyframe(
|
||||
animation_t *anim,
|
||||
animationproperty_t *prop,
|
||||
float_t time,
|
||||
float_t value,
|
||||
easingtype_t easing
|
||||
) {
|
||||
assertTrue(
|
||||
prop->keyframeCount < ANIMATION_KEYFRAME_COUNT_MAX,
|
||||
"Keyframe count exceeds ANIMATION_KEYFRAME_COUNT_MAX"
|
||||
);
|
||||
uint8_t i = prop->keyframeCount++;
|
||||
prop->keyframes[i].time = time;
|
||||
prop->keyframes[i].value = value;
|
||||
prop->keyframes[i].easing = easing;
|
||||
if(time > anim->duration) anim->duration = time;
|
||||
}
|
||||
|
||||
static float_t animationPropertyGetValue(
|
||||
const animationproperty_t *prop,
|
||||
float_t time
|
||||
) {
|
||||
if(prop->keyframeCount == 0) return 0.0f;
|
||||
|
||||
uint8_t last = prop->keyframeCount - 1;
|
||||
|
||||
if(prop->keyframeCount == 1) return prop->keyframes[0].value;
|
||||
if(time <= prop->keyframes[0].time) return prop->keyframes[0].value;
|
||||
if(time >= prop->keyframes[last].time) return prop->keyframes[last].value;
|
||||
|
||||
for(uint8_t i = 0; i < last; i++) {
|
||||
const keyframe_t *a = &prop->keyframes[i];
|
||||
const keyframe_t *b = &prop->keyframes[i + 1];
|
||||
if(time < a->time || time >= b->time) continue;
|
||||
float_t t = (time - a->time) / (b->time - a->time);
|
||||
t = easingApply(a->easing, t);
|
||||
return a->value + (b->value - a->value) * t;
|
||||
}
|
||||
|
||||
return prop->keyframes[last].value;
|
||||
}
|
||||
|
||||
void animationUpdate(animation_t *anim, float_t delta) {
|
||||
assertNotNull(anim, "Animation cannot be null");
|
||||
|
||||
// Anim done?
|
||||
if(
|
||||
(anim->flags & ANIMATION_FLAG_FINISHED) &&
|
||||
!(anim->flags & ANIMATION_FLAG_LOOP_ENABLED)
|
||||
) return;
|
||||
|
||||
// Start
|
||||
anim->flags |= ANIMATION_FLAG_STARTED;
|
||||
anim->time += delta;
|
||||
|
||||
if(anim->duration > 0.0f && anim->time >= anim->duration) {
|
||||
// Tick
|
||||
float_t duration = animationGetDuration(anim);
|
||||
if(anim->time >= duration) {
|
||||
// Done/Loop
|
||||
if(anim->flags & ANIMATION_FLAG_LOOP_ENABLED) {
|
||||
anim->time = fmodf(anim->time, anim->duration);
|
||||
anim->time = mathModFloat(anim->time, duration);
|
||||
} else {
|
||||
anim->time = anim->duration;
|
||||
anim->time = duration;
|
||||
anim->flags |= ANIMATION_FLAG_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < anim->propertyCount; i++) {
|
||||
animationproperty_t *prop = &anim->properties[i];
|
||||
if(!prop->target) continue;
|
||||
*prop->target = animationPropertyGetValue(prop, anim->time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void animationReset(animation_t *anim) {
|
||||
anim->time = 0.0f;
|
||||
anim->flags &= ~(ANIMATION_FLAG_FINISHED | ANIMATION_FLAG_STARTED);
|
||||
}
|
||||
|
||||
bool_t animationIsFinished(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_FINISHED) != 0;
|
||||
}
|
||||
|
||||
bool_t animationIsStarted(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_STARTED) != 0;
|
||||
}
|
||||
|
||||
bool_t animationIsLooping(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_LOOP_ENABLED) != 0;
|
||||
}
|
||||
|
||||
float_t animationGetDuration(const animation_t *anim) {
|
||||
float_t duration = 0.0f;
|
||||
for(uint8_t i = 0; i < anim->propertyCount; i++) {
|
||||
animationproperty_t *prop = &anim->properties[i];
|
||||
if(prop->keyframeCount == 0) continue;
|
||||
float_t lastKeyframeTime =
|
||||
prop->keyframes[prop->keyframeCount - 1].time;
|
||||
if(lastKeyframeTime > duration) duration = lastKeyframeTime;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
@@ -4,72 +4,83 @@
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "keyframe.h"
|
||||
#include "error/error.h"
|
||||
#include "animationproperty.h"
|
||||
|
||||
#define ANIMATION_PROPERTY_COUNT_MAX 8
|
||||
|
||||
typedef uint8_t animationflags_t;
|
||||
#define ANIMATION_FLAG_FINISHED ((animationflags_t)(1 << 0))
|
||||
#define ANIMATION_FLAG_STARTED ((animationflags_t)(1 << 1))
|
||||
#define ANIMATION_FLAG_LOOP_ENABLED ((animationflags_t)(1 << 2))
|
||||
|
||||
typedef struct {
|
||||
float_t *target;
|
||||
keyframe_t keyframes[ANIMATION_KEYFRAME_COUNT_MAX];
|
||||
uint8_t keyframeCount;
|
||||
} animationproperty_t;
|
||||
#define ANIMATION_FLAG_FINISHED (1 << 0)
|
||||
#define ANIMATION_FLAG_STARTED (1 << 1)
|
||||
#define ANIMATION_FLAG_LOOP_ENABLED (1 << 2)
|
||||
|
||||
typedef struct {
|
||||
animationproperty_t properties[ANIMATION_PROPERTY_COUNT_MAX];
|
||||
uint8_t propertyCount;
|
||||
float_t time;
|
||||
float_t duration;
|
||||
animationflags_t flags;
|
||||
uint8_t flags;
|
||||
} animation_t;
|
||||
|
||||
/**
|
||||
* Zeroes an animation struct.
|
||||
* Initializes an animation.
|
||||
*
|
||||
* @param anim The animation to initialize.
|
||||
*/
|
||||
void animationInit(animation_t *anim);
|
||||
|
||||
/**
|
||||
* Adds a new animated property. The caller owns target and must keep it valid
|
||||
* for the lifetime of the animation.
|
||||
*
|
||||
* @param anim The animation to add the property to.
|
||||
* @return A pointer to the new property.
|
||||
*/
|
||||
animationproperty_t *animationAddProperty(animation_t *anim, float_t *target);
|
||||
|
||||
/**
|
||||
* Appends a keyframe to a property. Keyframes must be added in ascending time
|
||||
* order. Updates the animation's duration.
|
||||
*/
|
||||
void animationPropertyAddKeyframe(
|
||||
animation_t *anim,
|
||||
animationproperty_t *prop,
|
||||
float_t time,
|
||||
float_t value,
|
||||
easingtype_t easing
|
||||
);
|
||||
animationproperty_t *animationAddProperty(animation_t *anim);
|
||||
|
||||
/**
|
||||
* Advances the animation by delta seconds and writes interpolated values to
|
||||
* each property's target pointer.
|
||||
*
|
||||
* @param anim The animation to update.
|
||||
* @param delta The time to advance the animation by, in seconds.
|
||||
*/
|
||||
void animationUpdate(animation_t *anim, float_t delta);
|
||||
|
||||
/**
|
||||
* Resets the animation to the beginning, clearing Started and Finished flags.
|
||||
*
|
||||
* @param anim The animation to reset.
|
||||
*/
|
||||
void animationReset(animation_t *anim);
|
||||
|
||||
static inline bool_t animationIsFinished(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_FINISHED) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns true if the animation has finished (i.e. reached the end of its
|
||||
* duration and is not looping).
|
||||
*
|
||||
* @param anim The animation to check.
|
||||
* @return true if the animation has finished, false otherwise.
|
||||
*/
|
||||
bool_t animationIsFinished(const animation_t *anim);
|
||||
|
||||
static inline bool_t animationIsStarted(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_STARTED) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns true if the animation has been started (i.e. animationUpdate has
|
||||
* been called at least once).
|
||||
*
|
||||
* @param anim The animation to check.
|
||||
* @return true if the animation has been started, false otherwise.
|
||||
*/
|
||||
bool_t animationIsStarted(const animation_t *anim);
|
||||
|
||||
static inline bool_t animationIsLooping(const animation_t *anim) {
|
||||
return (anim->flags & ANIMATION_FLAG_LOOP_ENABLED) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns true if the animation is set to loop.
|
||||
*
|
||||
* @param anim The animation to check.
|
||||
* @return true if the animation is set to loop, false otherwise.
|
||||
*/
|
||||
bool_t animationIsLooping(const animation_t *anim);
|
||||
|
||||
/**
|
||||
* Gets the total duration of the animation (based on the keyframes).
|
||||
*
|
||||
* @param anim The animation to get the duration of.
|
||||
* @return The total duration of the animation, in seconds.
|
||||
*/
|
||||
float_t animationGetDuration(const animation_t *anim);
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "animationproperty.h"
|
||||
#include "assert/assert.h"
|
||||
|
||||
void animationPropertyAddKeyframe(
|
||||
animationproperty_t *prop,
|
||||
const float_t time,
|
||||
const float_t value,
|
||||
const easingtype_t easing
|
||||
) {
|
||||
assertNotNull(prop, "Property cannot be null");
|
||||
assertTrue(
|
||||
prop->keyframeCount < ANIMATION_PROPERTY_KEYFRAME_COUNT_MAX,
|
||||
"Too many keyframes added to property"
|
||||
);
|
||||
assertTrue(time >= 0.0f, "Keyframe time cannot be negative");
|
||||
|
||||
keyframe_t *frame = &prop->keyframes[prop->keyframeCount++];
|
||||
frame->time = time;
|
||||
frame->value = value;
|
||||
frame->easing = easing;
|
||||
}
|
||||
|
||||
float_t animationPropertyGetValue(
|
||||
const animationproperty_t *prop,
|
||||
const float_t time
|
||||
) {
|
||||
assertNotNull(prop, "Property cannot be null");
|
||||
assertTrue(time >= 0.0f, "Time cannot be negative");
|
||||
|
||||
if(prop->keyframeCount == 0) return 0.0f;
|
||||
|
||||
uint8_t last = prop->keyframeCount - 1;
|
||||
|
||||
if(prop->keyframeCount == 1) return prop->keyframes[0].value;
|
||||
if(time <= prop->keyframes[0].time) return prop->keyframes[0].value;
|
||||
if(time >= prop->keyframes[last].time) return prop->keyframes[last].value;
|
||||
|
||||
for(uint8_t i = 0; i < last; i++) {
|
||||
const keyframe_t *a = &prop->keyframes[i];
|
||||
const keyframe_t *b = &prop->keyframes[i + 1];
|
||||
if(time < a->time || time >= b->time) continue;
|
||||
float_t t = (time - a->time) / (b->time - a->time);
|
||||
t = easingApply(a->easing, t);
|
||||
return a->value + (b->value - a->value) * t;
|
||||
}
|
||||
|
||||
return prop->keyframes[last].value;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "keyframe.h"
|
||||
|
||||
#define ANIMATION_PROPERTY_KEYFRAME_COUNT_MAX 16
|
||||
|
||||
typedef struct {
|
||||
keyframe_t keyframes[ANIMATION_PROPERTY_KEYFRAME_COUNT_MAX];
|
||||
uint8_t keyframeCount;
|
||||
} animationproperty_t;
|
||||
|
||||
/**
|
||||
* Appends a keyframe to a property. Keyframes must be added in ascending time
|
||||
* order. Updates the animation's duration.
|
||||
*
|
||||
* @param property The property to add the keyframe to.
|
||||
* @param time The time of the keyframe, in seconds.
|
||||
* @param value The value of the keyframe.
|
||||
* @param easing The easing type to use when interpolating to the next keyframe.
|
||||
*/
|
||||
void animationPropertyAddKeyframe(
|
||||
animationproperty_t *property,
|
||||
const float_t time,
|
||||
const float_t value,
|
||||
const easingtype_t easing
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the property's value at a given time.
|
||||
*
|
||||
* @param prop The property to get the value from.
|
||||
* @param time The time at which to get the value, in seconds.
|
||||
* @return The value of the property at the given time.
|
||||
*/
|
||||
float_t animationPropertyGetValue(
|
||||
const animationproperty_t *prop,
|
||||
const float_t time
|
||||
);
|
||||
+39
-34
@@ -7,82 +7,101 @@
|
||||
#include "assert/assert.h"
|
||||
#include <math.h>
|
||||
|
||||
#define EASING_PI 3.14159265358979323846f
|
||||
#define EASING_C1 1.70158f
|
||||
#define EASING_C2 (EASING_C1 * 1.525f)
|
||||
#define EASING_C3 (EASING_C1 + 1.0f)
|
||||
const easingfn_t EASING_FUNCTIONS[EASING_COUNT] = {
|
||||
easingLinear,
|
||||
easingInSine,
|
||||
easingOutSine,
|
||||
easingInOutSine,
|
||||
easingInQuad,
|
||||
easingOutQuad,
|
||||
easingInOutQuad,
|
||||
easingInCubic,
|
||||
easingOutCubic,
|
||||
easingInOutCubic,
|
||||
easingInQuart,
|
||||
easingOutQuart,
|
||||
easingInOutQuart,
|
||||
easingInBack,
|
||||
easingOutBack,
|
||||
easingInOutBack,
|
||||
};
|
||||
|
||||
float_t easingLinear(float_t t) {
|
||||
float_t easingApply(const easingtype_t type, const float_t t) {
|
||||
assertTrue(type < EASING_COUNT, "Invalid easing type");
|
||||
return EASING_FUNCTIONS[type](t);
|
||||
}
|
||||
|
||||
float_t easingLinear(const float_t t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
float_t easingInSine(float_t t) {
|
||||
float_t easingInSine(const float_t t) {
|
||||
return 1.0f - cosf(t * EASING_PI * 0.5f);
|
||||
}
|
||||
|
||||
float_t easingOutSine(float_t t) {
|
||||
float_t easingOutSine(const float_t t) {
|
||||
return sinf(t * EASING_PI * 0.5f);
|
||||
}
|
||||
|
||||
float_t easingInOutSine(float_t t) {
|
||||
float_t easingInOutSine(const float_t t) {
|
||||
return -(cosf(EASING_PI * t) - 1.0f) * 0.5f;
|
||||
}
|
||||
|
||||
float_t easingInQuad(float_t t) {
|
||||
float_t easingInQuad(const float_t t) {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
float_t easingOutQuad(float_t t) {
|
||||
float_t easingOutQuad(const float_t t) {
|
||||
float_t u = 1.0f - t;
|
||||
return 1.0f - u * u;
|
||||
}
|
||||
|
||||
float_t easingInOutQuad(float_t t) {
|
||||
float_t easingInOutQuad(const float_t t) {
|
||||
if(t < 0.5f) return 2.0f * t * t;
|
||||
float_t u = -2.0f * t + 2.0f;
|
||||
return 1.0f - u * u * 0.5f;
|
||||
}
|
||||
|
||||
float_t easingInCubic(float_t t) {
|
||||
float_t easingInCubic(const float_t t) {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
float_t easingOutCubic(float_t t) {
|
||||
float_t easingOutCubic(const float_t t) {
|
||||
float_t u = 1.0f - t;
|
||||
return 1.0f - u * u * u;
|
||||
}
|
||||
|
||||
float_t easingInOutCubic(float_t t) {
|
||||
float_t easingInOutCubic(const float_t t) {
|
||||
if(t < 0.5f) return 4.0f * t * t * t;
|
||||
float_t u = -2.0f * t + 2.0f;
|
||||
return 1.0f - u * u * u * 0.5f;
|
||||
}
|
||||
|
||||
float_t easingInQuart(float_t t) {
|
||||
float_t easingInQuart(const float_t t) {
|
||||
return t * t * t * t;
|
||||
}
|
||||
|
||||
float_t easingOutQuart(float_t t) {
|
||||
float_t easingOutQuart(const float_t t) {
|
||||
float_t u = 1.0f - t;
|
||||
return 1.0f - u * u * u * u;
|
||||
}
|
||||
|
||||
float_t easingInOutQuart(float_t t) {
|
||||
float_t easingInOutQuart(const float_t t) {
|
||||
if(t < 0.5f) return 8.0f * t * t * t * t;
|
||||
float_t u = -2.0f * t + 2.0f;
|
||||
return 1.0f - u * u * u * u * 0.5f;
|
||||
}
|
||||
|
||||
float_t easingInBack(float_t t) {
|
||||
float_t easingInBack(const float_t t) {
|
||||
return EASING_C3 * t * t * t - EASING_C1 * t * t;
|
||||
}
|
||||
|
||||
float_t easingOutBack(float_t t) {
|
||||
float_t easingOutBack(const float_t t) {
|
||||
float_t u = t - 1.0f;
|
||||
return 1.0f + EASING_C3 * u * u * u + EASING_C1 * u * u;
|
||||
}
|
||||
|
||||
float_t easingInOutBack(float_t t) {
|
||||
float_t easingInOutBack(const float_t t) {
|
||||
if(t < 0.5f) {
|
||||
float_t u = 2.0f * t;
|
||||
return u * u * ((EASING_C2 + 1.0f) * u - EASING_C2) * 0.5f;
|
||||
@@ -90,17 +109,3 @@ float_t easingInOutBack(float_t t) {
|
||||
float_t u = 2.0f * t - 2.0f;
|
||||
return (u * u * ((EASING_C2 + 1.0f) * u + EASING_C2) + 2.0f) * 0.5f;
|
||||
}
|
||||
|
||||
const easingfn_t EASING_FUNCTIONS[EASING_COUNT] = {
|
||||
easingLinear,
|
||||
easingInSine, easingOutSine, easingInOutSine,
|
||||
easingInQuad, easingOutQuad, easingInOutQuad,
|
||||
easingInCubic, easingOutCubic, easingInOutCubic,
|
||||
easingInQuart, easingOutQuart, easingInOutQuart,
|
||||
easingInBack, easingOutBack, easingInOutBack,
|
||||
};
|
||||
|
||||
float_t easingApply(easingtype_t type, float_t t) {
|
||||
assertTrue(type < EASING_COUNT, "Invalid easing type");
|
||||
return EASING_FUNCTIONS[type](t);
|
||||
}
|
||||
|
||||
+50
-36
@@ -6,44 +6,58 @@
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
#define EASING_LINEAR 0
|
||||
#define EASING_IN_SINE 1
|
||||
#define EASING_OUT_SINE 2
|
||||
#define EASING_IN_OUT_SINE 3
|
||||
#define EASING_IN_QUAD 4
|
||||
#define EASING_OUT_QUAD 5
|
||||
#define EASING_IN_OUT_QUAD 6
|
||||
#define EASING_IN_CUBIC 7
|
||||
#define EASING_OUT_CUBIC 8
|
||||
#define EASING_IN_OUT_CUBIC 9
|
||||
#define EASING_IN_QUART 10
|
||||
#define EASING_OUT_QUART 11
|
||||
#define EASING_IN_OUT_QUART 12
|
||||
#define EASING_IN_BACK 13
|
||||
#define EASING_OUT_BACK 14
|
||||
#define EASING_IN_OUT_BACK 15
|
||||
#define EASING_COUNT 16
|
||||
#define EASING_PI 3.14159265358979323846f
|
||||
#define EASING_C1 1.70158f
|
||||
#define EASING_C2 (EASING_C1 * 1.525f)
|
||||
#define EASING_C3 (EASING_C1 + 1.0f)
|
||||
|
||||
typedef uint8_t easingtype_t;
|
||||
typedef float_t (*easingfn_t)(float_t t);
|
||||
typedef enum {
|
||||
EASING_LINEAR,
|
||||
EASING_IN_SINE,
|
||||
EASING_OUT_SINE,
|
||||
EASING_IN_OUT_SINE,
|
||||
EASING_IN_QUAD,
|
||||
EASING_OUT_QUAD,
|
||||
EASING_IN_OUT_QUAD,
|
||||
EASING_IN_CUBIC,
|
||||
EASING_OUT_CUBIC,
|
||||
EASING_IN_OUT_CUBIC,
|
||||
EASING_IN_QUART,
|
||||
EASING_OUT_QUART,
|
||||
EASING_IN_OUT_QUART,
|
||||
EASING_IN_BACK,
|
||||
EASING_OUT_BACK,
|
||||
EASING_IN_OUT_BACK,
|
||||
|
||||
EASING_COUNT
|
||||
} easingtype_t;
|
||||
|
||||
typedef float_t (*easingfn_t)(const float_t t);
|
||||
|
||||
extern const easingfn_t EASING_FUNCTIONS[EASING_COUNT];
|
||||
|
||||
float_t easingApply(easingtype_t type, float_t t);
|
||||
/**
|
||||
* Applies the specified easing function to t.
|
||||
*
|
||||
* @param type The easing type to apply.
|
||||
* @param t The input time, in the range [0, 1].
|
||||
* @return The eased value, in the range [0, 1].
|
||||
*/
|
||||
float_t easingApply(const easingtype_t type, const float_t t);
|
||||
|
||||
float_t easingLinear(float_t t);
|
||||
float_t easingInSine(float_t t);
|
||||
float_t easingOutSine(float_t t);
|
||||
float_t easingInOutSine(float_t t);
|
||||
float_t easingInQuad(float_t t);
|
||||
float_t easingOutQuad(float_t t);
|
||||
float_t easingInOutQuad(float_t t);
|
||||
float_t easingInCubic(float_t t);
|
||||
float_t easingOutCubic(float_t t);
|
||||
float_t easingInOutCubic(float_t t);
|
||||
float_t easingInQuart(float_t t);
|
||||
float_t easingOutQuart(float_t t);
|
||||
float_t easingInOutQuart(float_t t);
|
||||
float_t easingInBack(float_t t);
|
||||
float_t easingOutBack(float_t t);
|
||||
float_t easingInOutBack(float_t t);
|
||||
float_t easingLinear(const float_t t);
|
||||
float_t easingInSine(const float_t t);
|
||||
float_t easingOutSine(const float_t t);
|
||||
float_t easingInOutSine(const float_t t);
|
||||
float_t easingInQuad(const float_t t);
|
||||
float_t easingOutQuad(const float_t t);
|
||||
float_t easingInOutQuad(const float_t t);
|
||||
float_t easingInCubic(const float_t t);
|
||||
float_t easingOutCubic(const float_t t);
|
||||
float_t easingInOutCubic(const float_t t);
|
||||
float_t easingInQuart(const float_t t);
|
||||
float_t easingOutQuart(const float_t t);
|
||||
float_t easingInOutQuart(const float_t t);
|
||||
float_t easingInBack(const float_t t);
|
||||
float_t easingOutBack(const float_t t);
|
||||
float_t easingInOutBack(const float_t t);
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#pragma once
|
||||
#include "easing.h"
|
||||
|
||||
#define ANIMATION_KEYFRAME_COUNT_MAX 16
|
||||
|
||||
typedef struct {
|
||||
float_t time;
|
||||
float_t value;
|
||||
|
||||
@@ -218,6 +218,8 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Static Assertions
|
||||
|
||||
#define assertStructSize(struct, size) \
|
||||
_Static_assert(sizeof(struct) == size, "Size of " #struct " must be " #size)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ errorret_t assetInit(void) {
|
||||
}
|
||||
|
||||
bool_t assetFileExists(const char_t *filename) {
|
||||
assertStrLenMax(filename, ASSET_FILE_PATH_MAX, "Filename too long.");
|
||||
assertStrLenMax(filename, ASSET_FILE_NAME_MAX, "Filename too long.");
|
||||
|
||||
zip_int64_t idx = zip_name_locate(ASSET.zip, filename, 0);
|
||||
if(idx < 0) return false;
|
||||
@@ -38,7 +38,7 @@ errorret_t assetLoad(
|
||||
void *params,
|
||||
void *output
|
||||
) {
|
||||
assertStrLenMax(filename, ASSET_FILE_PATH_MAX, "Filename too long.");
|
||||
assertStrLenMax(filename, ASSET_FILE_NAME_MAX, "Filename too long.");
|
||||
assertNotNull(output, "Output pointer cannot be NULL.");
|
||||
assertNotNull(loader, "Asset file loader cannot be NULL.");
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@ errorret_t assetFileInit(
|
||||
void *params,
|
||||
void *output
|
||||
) {
|
||||
memoryZero(file, sizeof(assetfile_t));
|
||||
assertNotNull(file, "Asset file cannot be NULL.");
|
||||
assertStrLenMax(filename, ASSET_FILE_NAME_MAX, "Filename too long.");
|
||||
|
||||
file->filename = filename;
|
||||
memoryZero(file, sizeof(assetfile_t));
|
||||
memoryCopy(file->filename, filename, ASSET_FILE_NAME_MAX);
|
||||
file->params = params;
|
||||
file->output = output;
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
#include "error/error.h"
|
||||
#include <zip.h>
|
||||
|
||||
#define ASSET_FILE_PATH_MAX FILENAME_MAX
|
||||
#define ASSET_FILE_NAME_MAX 48
|
||||
|
||||
typedef struct assetfile_s assetfile_t;
|
||||
|
||||
typedef errorret_t (*assetfileloader_t)(assetfile_t *file);
|
||||
|
||||
typedef struct assetfile_s {
|
||||
const char_t *filename;
|
||||
char_t filename[ASSET_FILE_NAME_MAX];
|
||||
void *params;
|
||||
void *output;
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ errorret_t sceneSetImmediate(const char_t *scene) {
|
||||
stringCopy(
|
||||
SCENE.sceneNext,
|
||||
scene == NULL ? "" : scene,
|
||||
ASSET_FILE_PATH_MAX
|
||||
ASSET_FILE_NAME_MAX
|
||||
);
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ errorret_t sceneSetImmediate(const char_t *scene) {
|
||||
stringCopy(
|
||||
SCENE.sceneCurrent,
|
||||
scene == NULL ? "" : scene,
|
||||
ASSET_FILE_PATH_MAX
|
||||
ASSET_FILE_NAME_MAX
|
||||
);
|
||||
|
||||
if(scene != NULL) {
|
||||
@@ -216,7 +216,7 @@ void sceneSet(const char_t *scene) {
|
||||
stringCopy(
|
||||
SCENE.sceneNext,
|
||||
scene == NULL ? "" : scene,
|
||||
ASSET_FILE_PATH_MAX
|
||||
ASSET_FILE_NAME_MAX
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
typedef struct {
|
||||
bool_t sceneActive;
|
||||
jerry_value_t scriptRef;
|
||||
char_t sceneCurrent[ASSET_FILE_PATH_MAX];
|
||||
char_t sceneNext[ASSET_FILE_PATH_MAX];
|
||||
char_t sceneCurrent[ASSET_FILE_NAME_MAX];
|
||||
char_t sceneNext[ASSET_FILE_NAME_MAX];
|
||||
} scene_t;
|
||||
|
||||
extern scene_t SCENE;
|
||||
|
||||
@@ -9,307 +9,307 @@
|
||||
#include "animation/animation.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
static scriptproto_t MODULE_ANIMATION_PROTO;
|
||||
// static scriptproto_t MODULE_ANIMATION_PROTO;
|
||||
|
||||
// JS animation wraps a single-property animation; value is the managed target.
|
||||
typedef struct {
|
||||
animation_t anim;
|
||||
float_t value;
|
||||
} jsAnimation_t;
|
||||
// // JS animation wraps a single-property animation; value is the managed target.
|
||||
// typedef struct {
|
||||
// animation_t anim;
|
||||
// float_t value;
|
||||
// } jsAnimation_t;
|
||||
|
||||
static inline jsAnimation_t *moduleAnimationGetWrapper(
|
||||
const jerry_call_info_t *callInfo
|
||||
) {
|
||||
return (jsAnimation_t *)scriptProtoGetValue(
|
||||
&MODULE_ANIMATION_PROTO, callInfo->this_value
|
||||
);
|
||||
}
|
||||
// static inline jsAnimation_t *moduleAnimationGetWrapper(
|
||||
// const jerry_call_info_t *callInfo
|
||||
// ) {
|
||||
// return (jsAnimation_t *)scriptProtoGetValue(
|
||||
// &MODULE_ANIMATION_PROTO, callInfo->this_value
|
||||
// );
|
||||
// }
|
||||
|
||||
// Returns the animation_t pointer (first field of jsAnimation_t — same address).
|
||||
static inline animation_t *moduleAnimationGet(
|
||||
const jerry_call_info_t *callInfo
|
||||
) {
|
||||
return (animation_t *)moduleAnimationGetWrapper(callInfo);
|
||||
}
|
||||
// // Returns the animation_t pointer (first field of jsAnimation_t — same address).
|
||||
// static inline animation_t *moduleAnimationGet(
|
||||
// const jerry_call_info_t *callInfo
|
||||
// ) {
|
||||
// return (animation_t *)moduleAnimationGetWrapper(callInfo);
|
||||
// }
|
||||
|
||||
// Extracts an easingtype_t from a JS value. Accepts either a plain number
|
||||
// or an Easing.xxx function (which has a .type numeric property).
|
||||
static easingtype_t moduleAnimationReadEasing(
|
||||
const jerry_value_t val
|
||||
) {
|
||||
if(jerry_value_is_number(val)) {
|
||||
return (easingtype_t)(uint32_t)jerry_value_as_number(val);
|
||||
}
|
||||
if(jerry_value_is_object(val) || jerry_value_is_function(val)) {
|
||||
jerry_value_t key = jerry_string_sz("type");
|
||||
jerry_value_t typeVal = jerry_object_get(val, key);
|
||||
jerry_value_free(key);
|
||||
easingtype_t result = EASING_LINEAR;
|
||||
if(jerry_value_is_number(typeVal)) {
|
||||
result = (easingtype_t)(uint32_t)jerry_value_as_number(typeVal);
|
||||
}
|
||||
jerry_value_free(typeVal);
|
||||
return result;
|
||||
}
|
||||
return EASING_LINEAR;
|
||||
}
|
||||
// // Extracts an easingtype_t from a JS value. Accepts either a plain number
|
||||
// // or an Easing.xxx function (which has a .type numeric property).
|
||||
// static easingtype_t moduleAnimationReadEasing(
|
||||
// const jerry_value_t val
|
||||
// ) {
|
||||
// if(jerry_value_is_number(val)) {
|
||||
// return (easingtype_t)(uint32_t)jerry_value_as_number(val);
|
||||
// }
|
||||
// if(jerry_value_is_object(val) || jerry_value_is_function(val)) {
|
||||
// jerry_value_t key = jerry_string_sz("type");
|
||||
// jerry_value_t typeVal = jerry_object_get(val, key);
|
||||
// jerry_value_free(key);
|
||||
// easingtype_t result = EASING_LINEAR;
|
||||
// if(jerry_value_is_number(typeVal)) {
|
||||
// result = (easingtype_t)(uint32_t)jerry_value_as_number(typeVal);
|
||||
// }
|
||||
// jerry_value_free(typeVal);
|
||||
// return result;
|
||||
// }
|
||||
// return EASING_LINEAR;
|
||||
// }
|
||||
|
||||
// Fires onReach callbacks for any keyframes crossed between prevTime and
|
||||
// newTime. Returns an exception value on error, or jerry_undefined().
|
||||
static jerry_value_t moduleAnimationFireKeyframes(
|
||||
const jerry_value_t thisVal,
|
||||
float_t prevTime,
|
||||
float_t newTime
|
||||
) {
|
||||
jerry_value_t kfKey = jerry_string_sz("_keyframes");
|
||||
jerry_value_t kfArr = jerry_object_get(thisVal, kfKey);
|
||||
jerry_value_free(kfKey);
|
||||
// // Fires onReach callbacks for any keyframes crossed between prevTime and
|
||||
// // newTime. Returns an exception value on error, or jerry_undefined().
|
||||
// static jerry_value_t moduleAnimationFireKeyframes(
|
||||
// const jerry_value_t thisVal,
|
||||
// float_t prevTime,
|
||||
// float_t newTime
|
||||
// ) {
|
||||
// jerry_value_t kfKey = jerry_string_sz("_keyframes");
|
||||
// jerry_value_t kfArr = jerry_object_get(thisVal, kfKey);
|
||||
// jerry_value_free(kfKey);
|
||||
|
||||
if(!jerry_value_is_array(kfArr)) {
|
||||
jerry_value_free(kfArr);
|
||||
return jerry_undefined();
|
||||
}
|
||||
// if(!jerry_value_is_array(kfArr)) {
|
||||
// jerry_value_free(kfArr);
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
jerry_length_t len = jerry_array_length(kfArr);
|
||||
for(jerry_length_t i = 0; i < len; i++) {
|
||||
jerry_value_t kfObj = jerry_object_get_index(kfArr, i);
|
||||
// jerry_length_t len = jerry_array_length(kfArr);
|
||||
// for(jerry_length_t i = 0; i < len; i++) {
|
||||
// jerry_value_t kfObj = jerry_object_get_index(kfArr, i);
|
||||
|
||||
jerry_value_t tKey = jerry_string_sz("time");
|
||||
jerry_value_t tVal = jerry_object_get(kfObj, tKey);
|
||||
jerry_value_free(tKey);
|
||||
float_t kfTime = (float_t)jerry_value_as_number(tVal);
|
||||
jerry_value_free(tVal);
|
||||
// jerry_value_t tKey = jerry_string_sz("time");
|
||||
// jerry_value_t tVal = jerry_object_get(kfObj, tKey);
|
||||
// jerry_value_free(tKey);
|
||||
// float_t kfTime = (float_t)jerry_value_as_number(tVal);
|
||||
// jerry_value_free(tVal);
|
||||
|
||||
if(prevTime < kfTime && newTime >= kfTime) {
|
||||
jerry_value_t cbKey = jerry_string_sz("onReach");
|
||||
jerry_value_t cb = jerry_object_get(kfObj, cbKey);
|
||||
jerry_value_free(cbKey);
|
||||
// if(prevTime < kfTime && newTime >= kfTime) {
|
||||
// jerry_value_t cbKey = jerry_string_sz("onReach");
|
||||
// jerry_value_t cb = jerry_object_get(kfObj, cbKey);
|
||||
// jerry_value_free(cbKey);
|
||||
|
||||
if(jerry_value_is_function(cb)) {
|
||||
jerry_value_t r = jerry_call(cb, thisVal, NULL, 0);
|
||||
jerry_value_free(cb);
|
||||
if(jerry_value_is_exception(r)) {
|
||||
jerry_value_free(kfObj);
|
||||
jerry_value_free(kfArr);
|
||||
return r;
|
||||
}
|
||||
jerry_value_free(r);
|
||||
} else {
|
||||
jerry_value_free(cb);
|
||||
}
|
||||
}
|
||||
// if(jerry_value_is_function(cb)) {
|
||||
// jerry_value_t r = jerry_call(cb, thisVal, NULL, 0);
|
||||
// jerry_value_free(cb);
|
||||
// if(jerry_value_is_exception(r)) {
|
||||
// jerry_value_free(kfObj);
|
||||
// jerry_value_free(kfArr);
|
||||
// return r;
|
||||
// }
|
||||
// jerry_value_free(r);
|
||||
// } else {
|
||||
// jerry_value_free(cb);
|
||||
// }
|
||||
// }
|
||||
|
||||
jerry_value_free(kfObj);
|
||||
}
|
||||
// jerry_value_free(kfObj);
|
||||
// }
|
||||
|
||||
jerry_value_free(kfArr);
|
||||
return jerry_undefined();
|
||||
}
|
||||
// jerry_value_free(kfArr);
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
// Fires onComplete once. Returns an exception on error or jerry_undefined().
|
||||
static jerry_value_t moduleAnimationFireComplete(
|
||||
const jerry_value_t thisVal
|
||||
) {
|
||||
jerry_value_t firedKey = jerry_string_sz("_completeFired");
|
||||
jerry_value_t firedVal = jerry_object_get(thisVal, firedKey);
|
||||
bool_t alreadyFired = jerry_value_is_true(firedVal);
|
||||
jerry_value_free(firedVal);
|
||||
// // Fires onComplete once. Returns an exception on error or jerry_undefined().
|
||||
// static jerry_value_t moduleAnimationFireComplete(
|
||||
// const jerry_value_t thisVal
|
||||
// ) {
|
||||
// jerry_value_t firedKey = jerry_string_sz("_completeFired");
|
||||
// jerry_value_t firedVal = jerry_object_get(thisVal, firedKey);
|
||||
// bool_t alreadyFired = jerry_value_is_true(firedVal);
|
||||
// jerry_value_free(firedVal);
|
||||
|
||||
if(alreadyFired) {
|
||||
jerry_value_free(firedKey);
|
||||
return jerry_undefined();
|
||||
}
|
||||
// if(alreadyFired) {
|
||||
// jerry_value_free(firedKey);
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
jerry_value_t trueVal = jerry_boolean(true);
|
||||
jerry_object_set(thisVal, firedKey, trueVal);
|
||||
jerry_value_free(firedKey);
|
||||
jerry_value_free(trueVal);
|
||||
// jerry_value_t trueVal = jerry_boolean(true);
|
||||
// jerry_object_set(thisVal, firedKey, trueVal);
|
||||
// jerry_value_free(firedKey);
|
||||
// jerry_value_free(trueVal);
|
||||
|
||||
jerry_value_t cbKey = jerry_string_sz("onComplete");
|
||||
jerry_value_t cb = jerry_object_get(thisVal, cbKey);
|
||||
jerry_value_free(cbKey);
|
||||
// jerry_value_t cbKey = jerry_string_sz("onComplete");
|
||||
// jerry_value_t cb = jerry_object_get(thisVal, cbKey);
|
||||
// jerry_value_free(cbKey);
|
||||
|
||||
if(jerry_value_is_function(cb)) {
|
||||
jerry_value_t r = jerry_call(cb, thisVal, NULL, 0);
|
||||
jerry_value_free(cb);
|
||||
if(jerry_value_is_exception(r)) return r;
|
||||
jerry_value_free(r);
|
||||
} else {
|
||||
jerry_value_free(cb);
|
||||
}
|
||||
// if(jerry_value_is_function(cb)) {
|
||||
// jerry_value_t r = jerry_call(cb, thisVal, NULL, 0);
|
||||
// jerry_value_free(cb);
|
||||
// if(jerry_value_is_exception(r)) return r;
|
||||
// jerry_value_free(r);
|
||||
// } else {
|
||||
// jerry_value_free(cb);
|
||||
// }
|
||||
|
||||
return jerry_undefined();
|
||||
}
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationConstructor) {
|
||||
jsAnimation_t *janim = (jsAnimation_t *)memoryAllocate(sizeof(jsAnimation_t));
|
||||
animationInit(&janim->anim);
|
||||
janim->value = 0.0f;
|
||||
// moduleBaseFunction(moduleAnimationConstructor) {
|
||||
// jsAnimation_t *janim = (jsAnimation_t *)memoryAllocate(sizeof(jsAnimation_t));
|
||||
// animationInit(&janim->anim);
|
||||
// janim->value = 0.0f;
|
||||
|
||||
if(argc > 0 && jerry_value_is_boolean(args[argc - 1])) {
|
||||
if(jerry_value_is_true(args[argc - 1])) {
|
||||
janim->anim.flags |= ANIMATION_FLAG_LOOP_ENABLED;
|
||||
}
|
||||
}
|
||||
// if(argc > 0 && jerry_value_is_boolean(args[argc - 1])) {
|
||||
// if(jerry_value_is_true(args[argc - 1])) {
|
||||
// janim->anim.flags |= ANIMATION_FLAG_LOOP_ENABLED;
|
||||
// }
|
||||
// }
|
||||
|
||||
animationproperty_t *prop = animationAddProperty(&janim->anim, &janim->value);
|
||||
// animationproperty_t *prop = animationAddProperty(&janim->anim, &janim->value);
|
||||
|
||||
if(argc > 0 && jerry_value_is_array(args[0])) {
|
||||
jerry_length_t len = jerry_array_length(args[0]);
|
||||
for(jerry_length_t i = 0; i < len; i++) {
|
||||
jerry_value_t kf = jerry_object_get_index(args[0], i);
|
||||
// if(argc > 0 && jerry_value_is_array(args[0])) {
|
||||
// jerry_length_t len = jerry_array_length(args[0]);
|
||||
// for(jerry_length_t i = 0; i < len; i++) {
|
||||
// jerry_value_t kf = jerry_object_get_index(args[0], i);
|
||||
|
||||
jerry_value_t tKey = jerry_string_sz("time");
|
||||
jerry_value_t vKey = jerry_string_sz("value");
|
||||
jerry_value_t eKey = jerry_string_sz("easing");
|
||||
// jerry_value_t tKey = jerry_string_sz("time");
|
||||
// jerry_value_t vKey = jerry_string_sz("value");
|
||||
// jerry_value_t eKey = jerry_string_sz("easing");
|
||||
|
||||
float_t t = (float_t)jerry_value_as_number(
|
||||
jerry_object_get(kf, tKey)
|
||||
);
|
||||
float_t v = (float_t)jerry_value_as_number(
|
||||
jerry_object_get(kf, vKey)
|
||||
);
|
||||
jerry_value_t eVal = jerry_object_get(kf, eKey);
|
||||
easingtype_t e = moduleAnimationReadEasing(eVal);
|
||||
// float_t t = (float_t)jerry_value_as_number(
|
||||
// jerry_object_get(kf, tKey)
|
||||
// );
|
||||
// float_t v = (float_t)jerry_value_as_number(
|
||||
// jerry_object_get(kf, vKey)
|
||||
// );
|
||||
// jerry_value_t eVal = jerry_object_get(kf, eKey);
|
||||
// easingtype_t e = moduleAnimationReadEasing(eVal);
|
||||
|
||||
jerry_value_free(tKey);
|
||||
jerry_value_free(vKey);
|
||||
jerry_value_free(eKey);
|
||||
jerry_value_free(eVal);
|
||||
jerry_value_free(kf);
|
||||
// jerry_value_free(tKey);
|
||||
// jerry_value_free(vKey);
|
||||
// jerry_value_free(eKey);
|
||||
// jerry_value_free(eVal);
|
||||
// jerry_value_free(kf);
|
||||
|
||||
animationPropertyAddKeyframe(&janim->anim, prop, t, v, e);
|
||||
}
|
||||
// animationPropertyAddKeyframe(&janim->anim, prop, t, v, e);
|
||||
// }
|
||||
|
||||
// Store the JS keyframes array for onReach callback detection.
|
||||
jerry_value_t kfKey = jerry_string_sz("_keyframes");
|
||||
jerry_object_set(callInfo->this_value, kfKey, args[0]);
|
||||
jerry_value_free(kfKey);
|
||||
}
|
||||
// // Store the JS keyframes array for onReach callback detection.
|
||||
// jerry_value_t kfKey = jerry_string_sz("_keyframes");
|
||||
// jerry_object_set(callInfo->this_value, kfKey, args[0]);
|
||||
// jerry_value_free(kfKey);
|
||||
// }
|
||||
|
||||
jerry_value_t firedKey = jerry_string_sz("_completeFired");
|
||||
jerry_value_t falseVal = jerry_boolean(false);
|
||||
jerry_object_set(callInfo->this_value, firedKey, falseVal);
|
||||
jerry_value_free(firedKey);
|
||||
jerry_value_free(falseVal);
|
||||
// jerry_value_t firedKey = jerry_string_sz("_completeFired");
|
||||
// jerry_value_t falseVal = jerry_boolean(false);
|
||||
// jerry_object_set(callInfo->this_value, firedKey, falseVal);
|
||||
// jerry_value_free(firedKey);
|
||||
// jerry_value_free(falseVal);
|
||||
|
||||
jerry_object_set_native_ptr(
|
||||
callInfo->this_value, &MODULE_ANIMATION_PROTO.info, janim
|
||||
);
|
||||
return jerry_undefined();
|
||||
}
|
||||
// jerry_object_set_native_ptr(
|
||||
// callInfo->this_value, &MODULE_ANIMATION_PROTO.info, janim
|
||||
// );
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationUpdate) {
|
||||
jsAnimation_t *janim = moduleAnimationGetWrapper(callInfo);
|
||||
if(!janim) return moduleBaseThrow("Invalid Animation instance");
|
||||
if(argc < 1 || !jerry_value_is_number(args[0])) {
|
||||
return moduleBaseThrow("update() expects a number delta");
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationUpdate) {
|
||||
// jsAnimation_t *janim = moduleAnimationGetWrapper(callInfo);
|
||||
// if(!janim) return moduleBaseThrow("Invalid Animation instance");
|
||||
// if(argc < 1 || !jerry_value_is_number(args[0])) {
|
||||
// return moduleBaseThrow("update() expects a number delta");
|
||||
// }
|
||||
|
||||
float_t prevTime = janim->anim.time;
|
||||
float_t delta = (float_t)jerry_value_as_number(args[0]);
|
||||
animationUpdate(&janim->anim, delta);
|
||||
// float_t prevTime = janim->anim.time;
|
||||
// float_t delta = (float_t)jerry_value_as_number(args[0]);
|
||||
// animationUpdate(&janim->anim, delta);
|
||||
|
||||
jerry_value_t kfResult = moduleAnimationFireKeyframes(
|
||||
callInfo->this_value, prevTime, janim->anim.time
|
||||
);
|
||||
if(jerry_value_is_exception(kfResult)) return kfResult;
|
||||
jerry_value_free(kfResult);
|
||||
// jerry_value_t kfResult = moduleAnimationFireKeyframes(
|
||||
// callInfo->this_value, prevTime, janim->anim.time
|
||||
// );
|
||||
// if(jerry_value_is_exception(kfResult)) return kfResult;
|
||||
// jerry_value_free(kfResult);
|
||||
|
||||
if(animationIsFinished(&janim->anim)) {
|
||||
jerry_value_t cResult = moduleAnimationFireComplete(
|
||||
callInfo->this_value
|
||||
);
|
||||
if(jerry_value_is_exception(cResult)) return cResult;
|
||||
jerry_value_free(cResult);
|
||||
}
|
||||
// if(animationIsFinished(&janim->anim)) {
|
||||
// jerry_value_t cResult = moduleAnimationFireComplete(
|
||||
// callInfo->this_value
|
||||
// );
|
||||
// if(jerry_value_is_exception(cResult)) return cResult;
|
||||
// jerry_value_free(cResult);
|
||||
// }
|
||||
|
||||
return jerry_number((double)janim->value);
|
||||
}
|
||||
// return jerry_number((double)janim->value);
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationGetValue) {
|
||||
jsAnimation_t *janim = moduleAnimationGetWrapper(callInfo);
|
||||
if(!janim) return moduleBaseThrow("Invalid Animation instance");
|
||||
return jerry_number((double)janim->value);
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationGetValue) {
|
||||
// jsAnimation_t *janim = moduleAnimationGetWrapper(callInfo);
|
||||
// if(!janim) return moduleBaseThrow("Invalid Animation instance");
|
||||
// return jerry_number((double)janim->value);
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationReset) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
if(!anim) return moduleBaseThrow("Invalid Animation instance");
|
||||
animationReset(anim);
|
||||
// moduleBaseFunction(moduleAnimationReset) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// if(!anim) return moduleBaseThrow("Invalid Animation instance");
|
||||
// animationReset(anim);
|
||||
|
||||
jerry_value_t key = jerry_string_sz("_completeFired");
|
||||
jerry_value_t falseVal = jerry_boolean(false);
|
||||
jerry_object_set(callInfo->this_value, key, falseVal);
|
||||
jerry_value_free(key);
|
||||
jerry_value_free(falseVal);
|
||||
// jerry_value_t key = jerry_string_sz("_completeFired");
|
||||
// jerry_value_t falseVal = jerry_boolean(false);
|
||||
// jerry_object_set(callInfo->this_value, key, falseVal);
|
||||
// jerry_value_free(key);
|
||||
// jerry_value_free(falseVal);
|
||||
|
||||
return jerry_undefined();
|
||||
}
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationGetComplete) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
return anim ? jerry_boolean(animationIsFinished(anim)) : jerry_boolean(false);
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationGetComplete) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// return anim ? jerry_boolean(animationIsFinished(anim)) : jerry_boolean(false);
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationGetLoop) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
return anim ? jerry_boolean(animationIsLooping(anim)) : jerry_boolean(false);
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationGetLoop) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// return anim ? jerry_boolean(animationIsLooping(anim)) : jerry_boolean(false);
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationSetLoop) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
if(!anim) return moduleBaseThrow("Invalid Animation instance");
|
||||
if(argc < 1) return moduleBaseThrow("Expected boolean");
|
||||
if(jerry_value_is_true(args[0])) {
|
||||
anim->flags |= ANIMATION_FLAG_LOOP_ENABLED;
|
||||
} else {
|
||||
anim->flags &= ~ANIMATION_FLAG_LOOP_ENABLED;
|
||||
}
|
||||
return jerry_undefined();
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationSetLoop) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// if(!anim) return moduleBaseThrow("Invalid Animation instance");
|
||||
// if(argc < 1) return moduleBaseThrow("Expected boolean");
|
||||
// if(jerry_value_is_true(args[0])) {
|
||||
// anim->flags |= ANIMATION_FLAG_LOOP_ENABLED;
|
||||
// } else {
|
||||
// anim->flags &= ~ANIMATION_FLAG_LOOP_ENABLED;
|
||||
// }
|
||||
// return jerry_undefined();
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationGetTime) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
return anim ? jerry_number((double)anim->time) : jerry_number(0.0);
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationGetTime) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// return anim ? jerry_number((double)anim->time) : jerry_number(0.0);
|
||||
// }
|
||||
|
||||
moduleBaseFunction(moduleAnimationGetDuration) {
|
||||
animation_t *anim = moduleAnimationGet(callInfo);
|
||||
return anim ? jerry_number((double)anim->duration) : jerry_number(0.0);
|
||||
}
|
||||
// moduleBaseFunction(moduleAnimationGetDuration) {
|
||||
// animation_t *anim = moduleAnimationGet(callInfo);
|
||||
// return anim ? jerry_number((double)anim->duration) : jerry_number(0.0);
|
||||
// }
|
||||
|
||||
static void moduleAnimation(void) {
|
||||
scriptProtoInit(
|
||||
&MODULE_ANIMATION_PROTO,
|
||||
"Animation",
|
||||
sizeof(jsAnimation_t),
|
||||
moduleAnimationConstructor
|
||||
);
|
||||
// scriptProtoInit(
|
||||
// &MODULE_ANIMATION_PROTO,
|
||||
// "Animation",
|
||||
// sizeof(jsAnimation_t),
|
||||
// moduleAnimationConstructor
|
||||
// );
|
||||
|
||||
scriptProtoDefineFunc(
|
||||
&MODULE_ANIMATION_PROTO, "update", moduleAnimationUpdate
|
||||
);
|
||||
scriptProtoDefineFunc(
|
||||
&MODULE_ANIMATION_PROTO, "getValue", moduleAnimationGetValue
|
||||
);
|
||||
scriptProtoDefineFunc(
|
||||
&MODULE_ANIMATION_PROTO, "reset", moduleAnimationReset
|
||||
);
|
||||
scriptProtoDefineProp(
|
||||
&MODULE_ANIMATION_PROTO, "complete",
|
||||
moduleAnimationGetComplete, NULL
|
||||
);
|
||||
scriptProtoDefineProp(
|
||||
&MODULE_ANIMATION_PROTO, "loop",
|
||||
moduleAnimationGetLoop, moduleAnimationSetLoop
|
||||
);
|
||||
scriptProtoDefineProp(
|
||||
&MODULE_ANIMATION_PROTO, "time",
|
||||
moduleAnimationGetTime, NULL
|
||||
);
|
||||
scriptProtoDefineProp(
|
||||
&MODULE_ANIMATION_PROTO, "duration",
|
||||
moduleAnimationGetDuration, NULL
|
||||
);
|
||||
// scriptProtoDefineFunc(
|
||||
// &MODULE_ANIMATION_PROTO, "update", moduleAnimationUpdate
|
||||
// );
|
||||
// scriptProtoDefineFunc(
|
||||
// &MODULE_ANIMATION_PROTO, "getValue", moduleAnimationGetValue
|
||||
// );
|
||||
// scriptProtoDefineFunc(
|
||||
// &MODULE_ANIMATION_PROTO, "reset", moduleAnimationReset
|
||||
// );
|
||||
// scriptProtoDefineProp(
|
||||
// &MODULE_ANIMATION_PROTO, "complete",
|
||||
// moduleAnimationGetComplete, NULL
|
||||
// );
|
||||
// scriptProtoDefineProp(
|
||||
// &MODULE_ANIMATION_PROTO, "loop",
|
||||
// moduleAnimationGetLoop, moduleAnimationSetLoop
|
||||
// );
|
||||
// scriptProtoDefineProp(
|
||||
// &MODULE_ANIMATION_PROTO, "time",
|
||||
// moduleAnimationGetTime, NULL
|
||||
// );
|
||||
// scriptProtoDefineProp(
|
||||
// &MODULE_ANIMATION_PROTO, "duration",
|
||||
// moduleAnimationGetDuration, NULL
|
||||
// );
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ moduleBaseFunction(moduleSceneSet) {
|
||||
if(argc < 1) return moduleBaseThrow("Expected at least 1 argument");
|
||||
moduleBaseRequireString(0);
|
||||
|
||||
char_t name[ASSET_FILE_PATH_MAX];
|
||||
char_t name[ASSET_FILE_NAME_MAX];
|
||||
moduleBaseToString(args[0], name, sizeof(name));
|
||||
if(name[0] == '\0') return moduleBaseThrow("Scene.set: name cannot be empty");
|
||||
|
||||
|
||||
@@ -18,4 +18,10 @@ uint32_t mathNextPowTwo(uint32_t value) {
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
float_t mathModFloat(float_t x, float_t y) {
|
||||
float_t result = fmodf(x, y);
|
||||
if(result < 0) result += y;
|
||||
return result;
|
||||
}
|
||||
+11
-1
@@ -50,4 +50,14 @@ uint32_t mathNextPowTwo(uint32_t value);
|
||||
* @param amt The number to get the absolute value of.
|
||||
* @return The absolute value of the number.
|
||||
*/
|
||||
#define mathAbs(amt) ((amt) < 0 ? -(amt) : (amt))
|
||||
#define mathAbs(amt) ((amt) < 0 ? -(amt) : (amt))
|
||||
|
||||
/**
|
||||
* Performs a modulus operation that always returns a non-negative result, even
|
||||
* if the dividend is negative.
|
||||
*
|
||||
* @param x The dividend.
|
||||
* @param y The divisor.
|
||||
* @return The result of the modulus operation.
|
||||
*/
|
||||
float_t mathModFloat(float_t x, float_t y);
|
||||
@@ -14,12 +14,12 @@ errorret_t assetInitLinux(void) {
|
||||
// Engine may have been provided the launch path
|
||||
if(ENGINE.argc > 0) {
|
||||
// Get the directory of the executable
|
||||
char_t buffer[ASSET_FILE_PATH_MAX];
|
||||
stringCopy(buffer, ENGINE.argv[0], ASSET_FILE_PATH_MAX);
|
||||
char_t buffer[ASSET_SYSTEM_PATH_MAX];
|
||||
stringCopy(buffer, ENGINE.argv[0], ASSET_SYSTEM_PATH_MAX);
|
||||
size_t len = strlen(buffer);
|
||||
|
||||
// Normalize slashes
|
||||
for(size_t i = 0; i < ASSET_FILE_PATH_MAX; i++) {
|
||||
for(size_t i = 0; i < ASSET_SYSTEM_PATH_MAX; i++) {
|
||||
if(buffer[i] == '\0') break;
|
||||
if(buffer[i] == '\\') buffer[i] = '/';
|
||||
}
|
||||
@@ -38,36 +38,36 @@ errorret_t assetInitLinux(void) {
|
||||
// Did we find a slash?
|
||||
if(end != buffer) {
|
||||
// We found the directory, set as system path
|
||||
stringCopy(ASSET.platform.systemPath, buffer, ASSET_FILE_PATH_MAX);
|
||||
stringCopy(ASSET.platform.systemPath, buffer, ASSET_SYSTEM_PATH_MAX);
|
||||
}
|
||||
} else {
|
||||
// Default system path, intended to be overridden by the platform
|
||||
stringCopy(ASSET.platform.systemPath, ".", ASSET_FILE_PATH_MAX);
|
||||
stringCopy(ASSET.platform.systemPath, ".", ASSET_SYSTEM_PATH_MAX);
|
||||
}
|
||||
|
||||
// Open zip file
|
||||
char_t searchPath[ASSET_FILE_PATH_MAX];
|
||||
char_t searchPath[ASSET_SYSTEM_PATH_MAX];
|
||||
const char_t **path = ASSET_LINUX_SEARCH_PATHS;
|
||||
int32_t error;
|
||||
do {
|
||||
char_t temp[ASSET_FILE_PATH_MAX];
|
||||
char_t temp[ASSET_SYSTEM_PATH_MAX];
|
||||
snprintf(
|
||||
temp,
|
||||
ASSET_FILE_PATH_MAX,
|
||||
ASSET_SYSTEM_PATH_MAX,
|
||||
*path,
|
||||
ASSET_FILE_NAME
|
||||
);
|
||||
|
||||
// Ensure combined length does not exceed ASSET_FILE_PATH_MAX
|
||||
// Ensure combined length does not exceed ASSET_SYSTEM_PATH_MAX
|
||||
size_t syslen = strlen(ASSET.platform.systemPath);
|
||||
size_t slashlen = 1; // for '/'
|
||||
size_t max_temp = ASSET_FILE_PATH_MAX - syslen - slashlen - 1;
|
||||
size_t max_temp = ASSET_SYSTEM_PATH_MAX - syslen - slashlen - 1;
|
||||
if(strlen(temp) > max_temp) {
|
||||
temp[max_temp] = '\0';
|
||||
}
|
||||
snprintf(
|
||||
searchPath,
|
||||
ASSET_FILE_PATH_MAX,
|
||||
ASSET_SYSTEM_PATH_MAX,
|
||||
"%s/%s",
|
||||
ASSET.platform.systemPath,
|
||||
temp
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "error/error.h"
|
||||
#include "asset/assetfile.h"
|
||||
|
||||
#define ASSET_SYSTEM_PATH_MAX FILENAME_MAX
|
||||
|
||||
static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
|
||||
"%s",
|
||||
"../%s",
|
||||
@@ -19,7 +21,7 @@ static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char_t systemPath[ASSET_FILE_PATH_MAX];
|
||||
char_t systemPath[ASSET_SYSTEM_PATH_MAX];
|
||||
} assetlinux_t;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user