diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml new file mode 100644 index 0000000..fbedfb5 --- /dev/null +++ b/.github/workflows/Linux.yml @@ -0,0 +1,34 @@ +name: Linux CI + +on: [push, pull_request] + +jobs: + Linux: + name: ubuntu-latest + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + run: python -m pip install meson==1.4.0 ninja + + - name: Configure project + run: | + meson setup build + + - name: Build and test + run: | + meson test -C build/ -v + + - name: Upload Test Log + uses: actions/upload-artifact@v4 + if: failure() + with: + name: Meson_Testlog + path: builddir/meson-logs/testlog.txt diff --git a/.gitignore b/.gitignore index 8399abe..df6c16c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +# Vim +.*.swp # XCode gitignore build/ diff --git a/README.md b/README.md index 6632be6..b3fec34 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ v0.4.0 Choreograph is designed to describe motion. With it, you compose motion Phrases into Sequences that can be used to animate arbitrary properties on a Timeline. +This is a maintained fork, after [the original project](https://github.com/sansumbrella/Choreograph) stopped being maintained. + ## Basic Usage Simple things are simple. You can animate a variable through a sequence of values in Choreograph by creating a sequence of ramps. diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..42483ab --- /dev/null +++ b/meson.build @@ -0,0 +1,4 @@ +project('Choreograph', 'cpp') + +subdir('src/choreograph') +subdir('tests') diff --git a/src/choreograph/Easing.h b/src/choreograph/Easing.h index 8bc8da5..24591cc 100644 --- a/src/choreograph/Easing.h +++ b/src/choreograph/Easing.h @@ -665,7 +665,7 @@ inline float easeInAtan( float t, float a = 15 ) //! Easing equation for an atan ease-in, accelerating from zero velocity. Functor edition. Used by permssion from Chris McKenzie. struct EaseInAtan { - EaseInAtan( float a = 15 ) : mInvM( 1.0f / std::atan( a ) ), mA( a ) {} + EaseInAtan( float a = 15 ) : mA( a ), mInvM( 1.0f / std::atan( a ) ) {} float operator()( float t ) const { return ( std::atan( (t - 1) * mA ) * mInvM ) + 1; } float mA, mInvM; }; @@ -679,7 +679,7 @@ inline float easeOutAtan( float t, float a = 15 ) //! Easing equation for an atan ease-out, decelerating from zero velocity. Functor edition. Used by permssion from Chris McKenzie. struct EaseOutAtan { - EaseOutAtan( float a = 15 ) : mInvM( 1.0f / std::atan( a ) ), mA( a ) {} + EaseOutAtan( float a = 15 ) : mA( a ), mInvM( 1.0f / std::atan( a ) ) {} float operator()( float t ) const { return std::atan( t * mA ) * mInvM; } float mA, mInvM; }; @@ -693,7 +693,7 @@ inline float easeInOutAtan( float t, float a = 15 ) //! Easing equation for an atan ease-in/out, accelerating until halfway, then decelerating. Functor edition. Used by permssion from Chris McKenzie. struct EaseInOutAtan { - EaseInOutAtan( float a = 15 ) : mInv2M( 1.0f / ( 2 * std::atan( 0.5f * a ) ) ), mA( a ) {} + EaseInOutAtan( float a = 15 ) : mA( a ), mInv2M( 1.0f / ( 2 * std::atan( 0.5f * a ) ) ) {} float operator()( float t ) const { return ( std::atan((t - 0.5f)*mA) * mInv2M ) + 0.5f; } float mA, mInv2M; }; diff --git a/src/choreograph/Motion.hpp b/src/choreograph/Motion.hpp index 97cb3fb..82a9d05 100644 --- a/src/choreograph/Motion.hpp +++ b/src/choreograph/Motion.hpp @@ -56,6 +56,11 @@ class Motion : public TimelineItem Motion() = delete; + Motion( T *target ): + _source( *target ), + _target( target ) + {} + Motion( T *target, const SequenceT &sequence ): _target( target ), _source( sequence ) @@ -131,7 +136,7 @@ class Motion : public TimelineItem Callback _finish_fn; Callback _start_fn; Callback _update_fn; - std::vector> _inflection_callbacks; + std::vector> _inflection_callbacks; /// Sets the output to a different output. /// Used by Output's move assignment and move constructor. @@ -173,7 +178,7 @@ void Motion::update() auto bottom = std::min( points.first, points.second ); for( const auto &fn : _inflection_callbacks ) { - auto inflection = fn.first; + unsigned int inflection = fn.first; if( inflection > bottom && inflection <= top ) { fn.second(); } @@ -200,7 +205,7 @@ void Motion::update() template void Motion::addInflectionCallback( size_t inflection_point, const Callback &callback ) { - _inflection_callbacks.emplace_back( std::make_pair( (int)inflection_point, callback ) ); + _inflection_callbacks.emplace_back( std::make_pair( inflection_point, callback ) ); } template @@ -212,7 +217,7 @@ void Motion::sliceSequence( Time from, Time to ) fn.first -= inflection; } - detail::erase_if( &_inflection_callbacks, [] (const std::pair &p) { + detail::erase_if( &_inflection_callbacks, [] (const std::pair &p) { return p.first < 0; } ); diff --git a/src/choreograph/meson.build b/src/choreograph/meson.build new file mode 100644 index 0000000..8b2cff0 --- /dev/null +++ b/src/choreograph/meson.build @@ -0,0 +1,16 @@ +src = [ + 'Cue.cpp', + 'Timeline.cpp', + 'TimelineItem.cpp', +] + +choreograph = library('choreograph', + sources: src, + include_directories: '..', + install: true, +) + +choreograph_dep = declare_dependency( + link_with: choreograph, + include_directories: '..', +) diff --git a/tests/Benchmarks_test.cpp b/tests/Benchmarks_test.cpp index aef2739..cfff89d 100644 --- a/tests/Benchmarks_test.cpp +++ b/tests/Benchmarks_test.cpp @@ -4,18 +4,51 @@ #include "choreograph/Choreograph.h" +#if TEST_WITH_CINDER #include "cinder/Vector.h" #include "cinder/Timeline.h" #include "cinder/Timer.h" +using cinder::Timeline; +#endif + #include using namespace std; -using cinder::Timeline; -using cinder::vec2; -using cinder::Timer; using namespace choreograph; +class Timer: public Catch::Timer +{ +public: + Timer(bool start_on_creation = false): + Catch::Timer() + { + if (start_on_creation) + start(); + } + + void stop() {} + double getSeconds() const { return getElapsedSeconds(); } +}; + +struct vec2 +{ + vec2(double x = 0.0f, double y = 0.0f): x(x), y(y) {} + + vec2 operator+(const vec2 &o) const { + return { x + o.x, y + o.y }; + } + vec2 operator-(const vec2 &o) const { + return { x - o.x, y - o.y }; + } + vec2 operator*(double s) const { + return { x * s, y *s }; + } + +private: + double x, y; +}; + void printTiming( const std::string &text, double milliseconds, const std::string &suffix = "ms" ) { string message = "[" + text + "] "; @@ -41,7 +74,7 @@ TEST_CASE( "Sequence Manipulation Timing" ) { printHeading( "Sequence Creation and Slicing" ); - Timer create_medium( true ); + Timer create_medium; Sequence medium_sequence( 0.0f ); medium_sequence.then( 10.0f, 1.0f, EaseInOutQuad() ) .then( 1.0f, 1.0f, EaseInOutQuad() ) @@ -161,21 +194,24 @@ TEST_CASE( "Choreograph Timeline Basic Performance" ) TEST_CASE( "Comparative Performance with cinder::Timeline" ) { ch::Timeline choreograph_timeline; - ci::TimelineRef cinder_timeline = ci::Timeline::create(); const int tween_count = 5000; vector> targets; while ( targets.size() < tween_count ) { targets.emplace_back( vec2( 0 ) ); } - vector> cinder_targets( tween_count, vec2( 0 ) ); - double ci_step_avg = 0; double ch_step_avg = 0; - double ci_create_avg = 0; double ch_create_avg = 0; double iterations = 4; +#if TEST_WITH_CINDER + ci::TimelineRef cinder_timeline = ci::Timeline::create(); + vector> cinder_targets( tween_count, vec2( 0 ) ); + double ci_step_avg = 0; + double ci_create_avg = 0; +#endif + SECTION( "Tween many targets" ) { printHeading( "Comparative Performance: many targets, short animations." ); @@ -193,6 +229,7 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) } ch_create.stop(); +#if TEST_WITH_CINDER // Create Cinder Tweens Timer ci_create( true ); for( int i = 0; i < tween_count; ++i ) { @@ -200,6 +237,7 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) .delay( 1.0f ); } ci_create.stop(); +#endif Timer ch_step( true ); // Step through Choreograph Motions @@ -208,6 +246,7 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) } ch_step.stop(); +#if TEST_WITH_CINDER Timer ci_step( true ); // Step through Cinder Tweens for( float t = 0.0f; t <= total_time; t += dt ) { @@ -217,22 +256,27 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) ci_create_avg += ci_create.getSeconds() * 1000; ci_step_avg += ci_step.getSeconds() * 1000; +#endif ch_create_avg += ch_create.getSeconds() * 1000; ch_step_avg += ch_step.getSeconds() * 1000; } +#if TEST_WITH_CINDER ci_create_avg /= iterations; ci_step_avg /= iterations; +#endif ch_create_avg /= iterations; ch_step_avg /= iterations; printTiming( "Choreograph Create Average", ch_create_avg ); - printTiming( "Cinder Create Average", ci_create_avg ); printTiming( "Choreograph Step Average", ch_step_avg ); +#if TEST_WITH_CINDER + printTiming( "Cinder Create Average", ci_create_avg ); printTiming( "Cinder Step Average", ci_step_avg ); printTiming( "Create Performance (Choreograph / Cinder)", (ch_create_avg / ci_create_avg), "" ); printTiming( "Step Performance (Choreograph / Cinder)", (ch_step_avg / ci_step_avg), "" ); +#endif } SECTION( "Tween one target many times" ) @@ -244,7 +288,6 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) for( int j = 0; j < iterations; j += 1 ) { Output target( vec2( 0 ) ); - ci::Anim cinder_target( vec2( 0 ) ); // Create Choreograph Motions Timer ch_create( true ); @@ -253,12 +296,15 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) } ch_create.stop(); +#if TEST_WITH_CINDER + ci::Anim cinder_target( vec2( 0 ) ); // Create Cinder Tweens Timer ci_create( true ); for( int i = 0; i < tween_count; ++i ) { cinder_timeline->appendTo( &cinder_target, vec2( i * 5, i * 20 ), 2.0f ).delay( 1.0f ); } ci_create.stop(); +#endif // Step through Choreograph Motions Timer ch_step( true ); @@ -267,6 +313,7 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) } ch_step.stop(); +#if TEST_WITH_CINDER // Step through Cinder Tweens Timer ci_step( true ); for( float t = 0.0f; t <= total_time; t += dt ) { @@ -276,21 +323,26 @@ TEST_CASE( "Comparative Performance with cinder::Timeline" ) ci_create_avg += ci_create.getSeconds() * 1000; ci_step_avg += ci_step.getSeconds() * 1000; +#endif ch_create_avg += ch_create.getSeconds() * 1000; ch_step_avg += ch_step.getSeconds() * 1000; } +#if TEST_WITH_CINDER ci_create_avg /= iterations; ci_step_avg /= iterations; +#endif ch_create_avg /= iterations; ch_step_avg /= iterations; printTiming( "Choreograph Create Average", ch_create_avg ); - printTiming( "Cinder Create Average", ci_create_avg ); printTiming( "Choreograph Step Average", ch_step_avg ); +#if TEST_WITH_CINDER printTiming( "Cinder Step Average", ci_step_avg ); + printTiming( "Cinder Create Average", ci_create_avg ); printTiming( "Create Performance (Choreograph / Cinder)", (ch_create_avg / ci_create_avg), "" ); printTiming( "Step Performance (Choreograph / Cinder)", (ch_step_avg / ci_step_avg), "" ); +#endif } } diff --git a/tests/Choreograph_test.cpp b/tests/Choreograph_test.cpp deleted file mode 100644 index 32217ad..0000000 --- a/tests/Choreograph_test.cpp +++ /dev/null @@ -1,3 +0,0 @@ - -#define CATCH_CONFIG_MAIN -#include "catch.hpp" diff --git a/tests/Cue_test.cpp b/tests/Cue_test.cpp index e683301..b9eb210 100644 --- a/tests/Cue_test.cpp +++ b/tests/Cue_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Ease_test.cpp b/tests/Ease_test.cpp index 24c426b..45e1432 100644 --- a/tests/Ease_test.cpp +++ b/tests/Ease_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/ForumMiscellany_test.cpp b/tests/ForumMiscellany_test.cpp index 4c7c098..baf083d 100644 --- a/tests/ForumMiscellany_test.cpp +++ b/tests/ForumMiscellany_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Grouping_test.cpp b/tests/Grouping_test.cpp index 832ec2e..68d5c16 100644 --- a/tests/Grouping_test.cpp +++ b/tests/Grouping_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Motion_test.cpp b/tests/Motion_test.cpp index 25ff3d0..6a71763 100644 --- a/tests/Motion_test.cpp +++ b/tests/Motion_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Numbers_test.cpp b/tests/Numbers_test.cpp index a06b8a7..d7269c0 100644 --- a/tests/Numbers_test.cpp +++ b/tests/Numbers_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Phrase_test.cpp b/tests/Phrase_test.cpp index 17250a2..79a7de0 100644 --- a/tests/Phrase_test.cpp +++ b/tests/Phrase_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Sequence_test.cpp b/tests/Sequence_test.cpp index f9f8a97..d32ba52 100644 --- a/tests/Sequence_test.cpp +++ b/tests/Sequence_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/Timeline_test.cpp b/tests/Timeline_test.cpp index a87d6cc..47a0804 100644 --- a/tests/Timeline_test.cpp +++ b/tests/Timeline_test.cpp @@ -5,6 +5,8 @@ // // +#define CATCH_CONFIG_MAIN + #include "catch.hpp" #include "choreograph/Choreograph.h" diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..c34c9b0 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,21 @@ +tests = [ + 'Benchmarks_test', + 'Cue_test', + 'Ease_test', + 'ForumMiscellany_test', + 'Grouping_test', + 'Motion_test', + 'Numbers_test', + 'Phrase_test', + 'Sequence_test', + 'Timeline_test', +] + +foreach t: tests + exe = executable(t, + t + '.cpp', + dependencies: [ + choreograph_dep, + ]) + test(t, exe) +endforeach