mirror of
https://github.com/google/pebble.git
synced 2025-11-22 23:40:54 -05:00
Import of the watch repository from Pebble
This commit is contained in:
179
src/fw/applib/ui/animation_interpolate.c
Normal file
179
src/fw/applib/ui/animation_interpolate.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "animation.h"
|
||||
#include "animation_interpolate.h"
|
||||
#include "animation_private.h"
|
||||
|
||||
#include "applib/graphics/gtypes.h"
|
||||
#include "system/passert.h"
|
||||
#include "util/math.h"
|
||||
#include "util/size.h"
|
||||
|
||||
int64_t interpolate_int64_linear(int32_t normalized, int64_t from, int64_t to) {
|
||||
return from + ((normalized * (to - from)) / ANIMATION_NORMALIZED_MAX);
|
||||
}
|
||||
|
||||
int64_t interpolate_int64(int32_t normalized, int64_t from, int64_t to) {
|
||||
InterpolateInt64Function interpolate =
|
||||
animation_private_current_interpolate_override() ?: interpolate_int64_linear;
|
||||
return interpolate(normalized, from, to);
|
||||
}
|
||||
|
||||
int16_t interpolate_int16(int32_t normalized, int16_t from, int16_t to) {
|
||||
const int64_t interpolated = interpolate_int64(normalized, from, to);
|
||||
return (int16_t)CLIP(interpolated, INT16_MIN, INT16_MAX);
|
||||
}
|
||||
|
||||
uint32_t interpolate_uint32(int32_t normalized, uint32_t from, uint32_t to) {
|
||||
const int64_t interpolated = interpolate_int64(normalized, from, to);
|
||||
return (uint32_t)CLIP(interpolated, 0, UINT32_MAX);
|
||||
}
|
||||
|
||||
Fixed_S32_16 interpolate_fixed32(int32_t normalized, Fixed_S32_16 from, Fixed_S32_16 to) {
|
||||
const int64_t interpolated = interpolate_int64(normalized, from.raw_value, to.raw_value);
|
||||
const int32_t raw_value =
|
||||
(int32_t) CLIP(interpolated, INT32_MIN, INT32_MAX);
|
||||
return Fixed_S32_16(raw_value);
|
||||
}
|
||||
|
||||
GSize interpolate_gsize(int32_t normalized, GSize from, GSize to) {
|
||||
return (GSize) {
|
||||
.w = interpolate_int16(normalized, from.w, to.w),
|
||||
.h = interpolate_int16(normalized, from.w, to.w),
|
||||
};
|
||||
}
|
||||
|
||||
GPoint interpolate_gpoint(int32_t normalized, GPoint from, GPoint to) {
|
||||
return (GPoint) {
|
||||
.x = interpolate_int16(normalized, from.x, to.x),
|
||||
.y = interpolate_int16(normalized, from.y, to.y),
|
||||
};
|
||||
}
|
||||
|
||||
int16_t scale_int16(int16_t value, int16_t from, int16_t to) {
|
||||
return (int16_t) ((int32_t) value * to / from);
|
||||
}
|
||||
|
||||
int32_t scale_int32(int32_t value, int32_t from, int32_t to) {
|
||||
return (int32_t) ((int64_t) value * to / from);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
|
||||
// these values are directly taken from "easing red line 001.mov"
|
||||
// _in will be added to first value (easing in, anticipation)
|
||||
// _out will be added to second value (overshoot, swing-back)
|
||||
static const int32_t s_delta_moook_in[] = {0, 1, 20};
|
||||
static const int32_t s_delta_moook_out[] = {INTERPOLATE_MOOOK_BOUNCE_BACK, 2, 1, 0};
|
||||
|
||||
// TODO: export these as interpolation functions as well
|
||||
uint32_t interpolate_moook_in_duration() {
|
||||
return ARRAY_LENGTH(s_delta_moook_in) * ANIMATION_TARGET_FRAME_INTERVAL_MS;
|
||||
}
|
||||
|
||||
uint32_t interpolate_moook_out_duration() {
|
||||
return ARRAY_LENGTH(s_delta_moook_out) * ANIMATION_TARGET_FRAME_INTERVAL_MS;
|
||||
}
|
||||
|
||||
uint32_t interpolate_moook_duration() {
|
||||
return interpolate_moook_in_duration() + interpolate_moook_out_duration();
|
||||
}
|
||||
|
||||
uint32_t interpolate_moook_soft_duration(int32_t num_frames_mid) {
|
||||
return interpolate_moook_duration() + num_frames_mid * ANIMATION_TARGET_FRAME_INTERVAL_MS;
|
||||
}
|
||||
|
||||
uint32_t interpolate_moook_custom_duration(const MoookConfig *config) {
|
||||
PBL_ASSERTN(config);
|
||||
return ((config->num_frames_in + config->num_frames_mid + config->num_frames_out) *
|
||||
ANIMATION_TARGET_FRAME_INTERVAL_MS);
|
||||
}
|
||||
|
||||
static int64_t prv_interpolate_moook(
|
||||
int32_t normalized, int64_t from, int64_t to, const int32_t *frames_in, int32_t num_frames_in,
|
||||
const int32_t *frames_out, int32_t num_frames_out, int32_t num_frames_mid, bool bounce_back) {
|
||||
const int32_t direction = ((from == to) ? 0 : ((from < to) ? 1 : -1));
|
||||
if (direction == 0) {
|
||||
return from;
|
||||
}
|
||||
|
||||
const int32_t direction_out = direction * (bounce_back ? 1 : -1);
|
||||
const size_t num_frames_total = num_frames_in + num_frames_mid + num_frames_out;
|
||||
int32_t frame_idx =
|
||||
((normalized * num_frames_total + (ANIMATION_NORMALIZED_MAX / (2 * num_frames_total))) /
|
||||
ANIMATION_NORMALIZED_MAX);
|
||||
frame_idx = CLIP(frame_idx, 0, (int)num_frames_total - 1);
|
||||
|
||||
|
||||
if (normalized == ANIMATION_NORMALIZED_MAX) {
|
||||
return to;
|
||||
} else if (frame_idx < 0) {
|
||||
return from;
|
||||
} else if (frame_idx < num_frames_in) {
|
||||
return from + (frames_in ? (direction * frames_in[frame_idx]) : 0);
|
||||
} else if ((frame_idx < (num_frames_in + num_frames_mid)) && (num_frames_mid > 0)) {
|
||||
const int64_t shifted_normalized = normalized -
|
||||
(((int64_t) num_frames_in * ANIMATION_NORMALIZED_MAX) / num_frames_total);
|
||||
const int32_t mid_normalized = ((int64_t) num_frames_total * shifted_normalized) /
|
||||
num_frames_mid;
|
||||
return interpolate_int64_linear(mid_normalized,
|
||||
from + (direction * frames_in[num_frames_in - 1]),
|
||||
to + (direction_out * frames_out[0]));
|
||||
} else {
|
||||
return to + (frames_out ? (direction_out *
|
||||
frames_out[frame_idx - (num_frames_in + num_frames_mid)]) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t interpolate_moook_in(int32_t normalized, int64_t from, int64_t to, int32_t num_frames_to) {
|
||||
return prv_interpolate_moook(normalized, from, to, s_delta_moook_in,
|
||||
ARRAY_LENGTH(s_delta_moook_in), NULL, num_frames_to, 0, true);
|
||||
}
|
||||
|
||||
int64_t interpolate_moook_in_only(int32_t normalized, int64_t from, int64_t to) {
|
||||
return prv_interpolate_moook(normalized, from, to, s_delta_moook_in,
|
||||
ARRAY_LENGTH(s_delta_moook_in), NULL, 0, 0, true);
|
||||
}
|
||||
|
||||
int64_t interpolate_moook_out(int32_t normalized, int64_t from, int64_t to,
|
||||
int32_t num_frames_from, bool bounce_back) {
|
||||
return prv_interpolate_moook(normalized, from, to, NULL, num_frames_from, s_delta_moook_out,
|
||||
ARRAY_LENGTH(s_delta_moook_out), 0, bounce_back);
|
||||
}
|
||||
|
||||
int64_t interpolate_moook(int32_t normalized, int64_t from, int64_t to) {
|
||||
return prv_interpolate_moook(normalized, from, to,
|
||||
s_delta_moook_in, ARRAY_LENGTH(s_delta_moook_in),
|
||||
s_delta_moook_out, ARRAY_LENGTH(s_delta_moook_out), 0, true);
|
||||
}
|
||||
|
||||
int64_t interpolate_moook_soft(int32_t normalized, int64_t from, int64_t to,
|
||||
int32_t num_frames_mid) {
|
||||
return prv_interpolate_moook(normalized, from, to,
|
||||
s_delta_moook_in, ARRAY_LENGTH(s_delta_moook_in),
|
||||
s_delta_moook_out, ARRAY_LENGTH(s_delta_moook_out),
|
||||
num_frames_mid, true);
|
||||
}
|
||||
|
||||
int64_t interpolate_moook_custom(int32_t normalized, int64_t from, int64_t to,
|
||||
const MoookConfig *config) {
|
||||
PBL_ASSERTN(config);
|
||||
return prv_interpolate_moook(normalized, from, to,
|
||||
config->frames_in, config->num_frames_in,
|
||||
config->frames_out, config->num_frames_out,
|
||||
config->num_frames_mid, !config->no_bounce_back);
|
||||
}
|
||||
Reference in New Issue
Block a user