Compare commits
No commits in common. "88b1caf88548183967d51f13bd3dfae48b53211b" and "095f1e5d0cead88e4f06ddc0d88066efc1e12098" have entirely different histories.
88b1caf885
...
095f1e5d0c
@ -146,7 +146,7 @@ void BLTAnimationGraph::_graph_changed(const StringName &node_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLTAnimationGraph::_notification(int p_what) {
|
void BLTAnimationGraph::_notification(int p_what) {
|
||||||
GodotProfileZone("BLTAnimationGraph::_notification");
|
GodotProfileZone("SyncedAnimationGraph::_notification");
|
||||||
|
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
case NOTIFICATION_ENTER_TREE: {
|
case NOTIFICATION_ENTER_TREE: {
|
||||||
@ -295,7 +295,7 @@ void BLTAnimationGraph::_process_graph(double p_delta, bool p_update_only) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GodotProfileZone("BLTAnimationGraph::_process_graph");
|
GodotProfileZone("SyncedAnimationGraph::_process_graph");
|
||||||
|
|
||||||
_update_properties();
|
_update_properties();
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ void BLTAnimationGraph::_process_graph(double p_delta, bool p_update_only) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BLTAnimationGraph::_apply_animation_data(const AnimationData &output_data) const {
|
void BLTAnimationGraph::_apply_animation_data(const AnimationData &output_data) const {
|
||||||
GodotProfileZone("BLTAnimationGraph::_apply_animation_data");
|
GodotProfileZone("SyncedAnimationGraph::_apply_animation_data");
|
||||||
|
|
||||||
for (const KeyValue<Animation::TypeHash, size_t> &K : output_data.value_buffer_offset) {
|
for (const KeyValue<Animation::TypeHash, size_t> &K : output_data.value_buffer_offset) {
|
||||||
const AnimationData::TrackValue *track_value = output_data.get_value<AnimationData::TrackValue>(K.key);
|
const AnimationData::TrackValue *track_value = output_data.get_value<AnimationData::TrackValue>(K.key);
|
||||||
|
|||||||
@ -385,10 +385,6 @@ StringName BLTAnimationNodeSampler::get_animation() const {
|
|||||||
return animation_name;
|
return animation_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationPlayer *BLTAnimationNodeSampler::get_animation_player() const {
|
|
||||||
return animation_player;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypedArray<StringName> BLTAnimationNodeSampler::get_animations_as_typed_array() const {
|
TypedArray<StringName> BLTAnimationNodeSampler::get_animations_as_typed_array() const {
|
||||||
TypedArray<StringName> typed_arr;
|
TypedArray<StringName> typed_arr;
|
||||||
|
|
||||||
@ -421,7 +417,6 @@ TypedArray<StringName> BLTAnimationNodeSampler::get_animations_as_typed_array()
|
|||||||
void BLTAnimationNodeSampler::_bind_methods() {
|
void BLTAnimationNodeSampler::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_animation", "name"), &BLTAnimationNodeSampler::set_animation);
|
ClassDB::bind_method(D_METHOD("set_animation", "name"), &BLTAnimationNodeSampler::set_animation);
|
||||||
ClassDB::bind_method(D_METHOD("get_animation"), &BLTAnimationNodeSampler::get_animation);
|
ClassDB::bind_method(D_METHOD("get_animation"), &BLTAnimationNodeSampler::get_animation);
|
||||||
ClassDB::bind_method(D_METHOD("get_animation_player"), &BLTAnimationNodeSampler::get_animation_player);
|
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation");
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by martin on 20.02.26.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef MASTER_BLENDALOT_MATH_HELPER_H
|
|
||||||
#define MASTER_BLENDALOT_MATH_HELPER_H
|
|
||||||
|
|
||||||
inline int greatest_common_divisor(int a, int b) {
|
|
||||||
while (b != 0) {
|
|
||||||
int temp = b;
|
|
||||||
b = a % b;
|
|
||||||
a = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int least_common_multiple(int a, int b) {
|
|
||||||
return (a / greatest_common_divisor(a, b)) * b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //MASTER_BLENDALOT_MATH_HELPER_H
|
|
||||||
34
sync_track.h
34
sync_track.h
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "core/templates/local_vector.h"
|
#include "core/templates/local_vector.h"
|
||||||
|
|
||||||
#include "blendalot_math_helper.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -22,7 +21,7 @@
|
|||||||
* duration. Blended SyncTracks always have their first interval start at t = 0.0s.
|
* duration. Blended SyncTracks always have their first interval start at t = 0.0s.
|
||||||
*/
|
*/
|
||||||
struct SyncTrack {
|
struct SyncTrack {
|
||||||
static constexpr int cSyncTrackMaxIntervals = 32;
|
static constexpr int cSyncTrackMaxIntervals = 8;
|
||||||
|
|
||||||
SyncTrack() :
|
SyncTrack() :
|
||||||
duration(0.f), num_intervals(1) {
|
duration(0.f), num_intervals(1) {
|
||||||
@ -60,12 +59,6 @@ struct SyncTrack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double calc_ratio_from_sync_time(double sync_time) const {
|
double calc_ratio_from_sync_time(double sync_time) const {
|
||||||
// When blending SyncTracks with differing numbers of intervals the resulting SyncTrack may have
|
|
||||||
// additional repeats of the animation (=> "virtual sync periods", https://youtu.be/Jkv0pbp0ckQ?t=8178).
|
|
||||||
//
|
|
||||||
// Therefore, we first have to transform it back to the numbers of intervals we actually have.
|
|
||||||
sync_time = fmod(sync_time, num_intervals);
|
|
||||||
|
|
||||||
float interval_ratio = fmod(sync_time, 1.0f);
|
float interval_ratio = fmod(sync_time, 1.0f);
|
||||||
int interval = int(sync_time - interval_ratio);
|
int interval = int(sync_time - interval_ratio);
|
||||||
|
|
||||||
@ -133,32 +126,19 @@ struct SyncTrack {
|
|||||||
*/
|
*/
|
||||||
static SyncTrack
|
static SyncTrack
|
||||||
blend(float weight, const SyncTrack &track_A, const SyncTrack &track_B) {
|
blend(float weight, const SyncTrack &track_A, const SyncTrack &track_B) {
|
||||||
if (Math::is_zero_approx(weight)) {
|
assert(track_A.num_intervals == track_B.num_intervals);
|
||||||
return track_A;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math::is_zero_approx(1.0 - weight)) {
|
|
||||||
return track_B;
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncTrack result;
|
SyncTrack result;
|
||||||
|
|
||||||
if (track_A.num_intervals != track_B.num_intervals) {
|
|
||||||
result.num_intervals = least_common_multiple(track_A.num_intervals, track_B.num_intervals);
|
|
||||||
} else {
|
|
||||||
result.num_intervals = track_A.num_intervals;
|
result.num_intervals = track_A.num_intervals;
|
||||||
}
|
|
||||||
assert(result.num_intervals < cSyncTrackMaxIntervals);
|
|
||||||
|
|
||||||
int track_A_repeats = result.num_intervals / track_A.num_intervals;
|
result.duration =
|
||||||
int track_B_repeats = result.num_intervals / track_B.num_intervals;
|
(1.0f - weight) * track_A.duration + weight * track_B.duration;
|
||||||
|
|
||||||
result.duration = (1.0f - weight) * (track_A.duration * track_A_repeats) + weight * (track_B.duration * track_B_repeats);
|
|
||||||
result.interval_start_ratio[0] = 0.f;
|
result.interval_start_ratio[0] = 0.f;
|
||||||
|
|
||||||
for (int i = 0; i < result.num_intervals; i++) {
|
for (int i = 0; i < result.num_intervals; i++) {
|
||||||
float interval_duration_A = track_A.interval_duration_ratio[i % track_A.num_intervals];
|
float interval_duration_A = track_A.interval_duration_ratio[i];
|
||||||
float interval_duration_B = track_B.interval_duration_ratio[i % track_B.num_intervals];
|
float interval_duration_B = track_B.interval_duration_ratio[i];
|
||||||
result.interval_duration_ratio[i] =
|
result.interval_duration_ratio[i] =
|
||||||
(1.0f - weight) * interval_duration_A + weight * interval_duration_B;
|
(1.0f - weight) * interval_duration_A + weight * interval_duration_B;
|
||||||
|
|
||||||
@ -172,6 +152,8 @@ struct SyncTrack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(result.num_intervals < cSyncTrackMaxIntervals);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace TestBlendalotAnimationGraph {
|
namespace TestBlendalotAnimationGraph {
|
||||||
|
|
||||||
TEST_CASE("[Blendalot][SyncTrack] Basic") {
|
TEST_CASE("[SyncedAnimationGraph][SyncTrack] Basic") {
|
||||||
SyncTrack track_a;
|
SyncTrack track_a;
|
||||||
track_a.num_intervals = 2;
|
track_a.num_intervals = 2;
|
||||||
track_a.duration = 2.0;
|
track_a.duration = 2.0;
|
||||||
@ -84,7 +84,7 @@ TEST_CASE("[Blendalot][SyncTrack] Basic") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Blendalot][SyncTrack] Create Sync Track from markers") {
|
TEST_CASE("[SyncedAnimationGraph][SyncTrack] Create Sync Track from markers") {
|
||||||
SyncTrack track = SyncTrack::create_from_markers(2.0f, { 0.9f, 0.2f });
|
SyncTrack track = SyncTrack::create_from_markers(2.0f, { 0.9f, 0.2f });
|
||||||
|
|
||||||
WHEN("Querying Ratios") {
|
WHEN("Querying Ratios") {
|
||||||
@ -138,7 +138,7 @@ TEST_CASE("[Blendalot][SyncTrack] Create Sync Track from markers") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Blendalot][SyncTrack] Sync Track blending") {
|
TEST_CASE("[SyncedAnimationGraph][SyncTrack] Sync Track blending") {
|
||||||
SyncTrack track_a = SyncTrack::create_from_markers(2.0, { 0., 0.6, 1.8 });
|
SyncTrack track_a = SyncTrack::create_from_markers(2.0, { 0., 0.6, 1.8 });
|
||||||
SyncTrack track_b = SyncTrack::create_from_markers(1.5f, { 1.05, 1.35, 0.3 });
|
SyncTrack track_b = SyncTrack::create_from_markers(1.5f, { 1.05, 1.35, 0.3 });
|
||||||
|
|
||||||
@ -203,46 +203,4 @@ TEST_CASE("[Blendalot][SyncTrack] Sync Track blending") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Blendalot][SyncTrack] Sync Track blending non-matching interval count") {
|
} //namespace TestSyncedAnimationGraph
|
||||||
SyncTrack track_a = SyncTrack::create_from_markers(2.0, { 0., 0.6, 1.8 });
|
|
||||||
SyncTrack track_b = SyncTrack::create_from_markers(1.5f, { 1.05 });
|
|
||||||
|
|
||||||
WHEN("Blending two synctracks with weight 0.") {
|
|
||||||
SyncTrack blended = SyncTrack::blend(0.f, track_a, track_b);
|
|
||||||
|
|
||||||
blended.duration = track_a.duration;
|
|
||||||
blended.interval_start_ratio[0] = 0.0;
|
|
||||||
for (int i = 0; i < track_a.num_intervals; i++) {
|
|
||||||
CHECK(blended.interval_duration_ratio[i] == track_a.interval_duration_ratio[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WHEN("Blending two synctracks with weight 1.") {
|
|
||||||
SyncTrack blended = SyncTrack::blend(1.f, track_a, track_b);
|
|
||||||
|
|
||||||
blended.duration = track_b.duration;
|
|
||||||
blended.interval_start_ratio[0] = 0.0;
|
|
||||||
for (int i = 0; i < track_b.num_intervals; i++) {
|
|
||||||
CHECK(blended.interval_duration_ratio[i] == track_b.interval_duration_ratio[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WHEN("Blending with weight 0.2") {
|
|
||||||
float weight = 0.2f;
|
|
||||||
SyncTrack blended = SyncTrack::blend(weight, track_a, track_b);
|
|
||||||
|
|
||||||
int track_b_repeats = 3;
|
|
||||||
|
|
||||||
REQUIRE(
|
|
||||||
blended.duration == (1.0f - weight) * track_a.duration + weight * track_b.duration * track_b_repeats);
|
|
||||||
REQUIRE(
|
|
||||||
blended.interval_start_ratio[0] == 0.0);
|
|
||||||
REQUIRE(
|
|
||||||
blended.interval_duration_ratio[0] == (1.0f - weight) * (track_a.interval_duration_ratio[0]) + weight * (track_b.interval_duration_ratio[0]));
|
|
||||||
REQUIRE(
|
|
||||||
blended.interval_duration_ratio[1] == (1.0f - weight) * (track_a.interval_duration_ratio[1]) + weight * (track_b.interval_duration_ratio[0]));
|
|
||||||
REQUIRE(
|
|
||||||
blended.interval_duration_ratio[2] == (1.0f - weight) * (track_a.interval_duration_ratio[2]) + weight * (track_b.interval_duration_ratio[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace TestBlendalotAnimationGraph
|
|
||||||
Loading…
x
Reference in New Issue
Block a user