Skip to content

Commit

Permalink
first
Browse files Browse the repository at this point in the history
  • Loading branch information
hideakitai committed Jun 23, 2020
1 parent cb7b283 commit 35b8a0a
Show file tree
Hide file tree
Showing 79 changed files with 6,327 additions and 0 deletions.
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,98 @@
# Tween

Tween library for Arduino


## Usage

```C++
#include <Tween.h>

Tween::Timeline timeline;
float target = 0.f;

void setup()
{
timeline.add(target, 10, 5000) // target tweens to 10 in 5000[ms]
.then(5, 5000) // then to 5 in 5000[ms]
.wait(1000) // then stops 1000[ms]
.then(0, 5000); // then to 0 in 5000[ms]

timeline.start();
}

void loop()
{
timline.update(); // must be called to tween target

Serial.println(target); // target value tweens automatically
}
```

### Use Easing Function in Tween

```C++
timeline.add<Ease::Sine>(f, 10, 5000)
.then<Ease::Elastic>(5, 5000)
.wait(1000)
.then<Ease::Bounce>(0, 5000);
```


## Easing Types

If you haven't specify the easing type, default value is `Ease::Linear`.

- BackIn, BackOut, BackInOut
- BounceIn, BounceOut, BounceInOut
- CircIn, CircOut, CircInOut
- CubicIn, CubicOut, CubicInOut
- ElasticIn, ElasticOut, ElasticInOut
- ExpoIn, ExpoOut, ExpoInOut
- LinearIn, LinearOut, LinearInOut
- QuadIn, QuadOut, QuadInOut
- QuartIn, QuartOut, QuartInOut
- QuintIn, QuintOut, QuintInOut
- SineIn, SineOut, SineInOut

```C++
// alias
using Back = BackInOut;
using Bounce = BounceInOut;
using Circ = CircInOut;
using Cubic = CubicInOut;
using Elastic = ElasticInOut;
using Expo = ExpoInOut;
using Linear = LinearInOut;
using Quad = QuadInOut;
using Quart = QuartInOut;
using Quint = QuintInOut;
using Sine = SineInOut;
```


## Custom Class Adaptation

You can use custom classes if you have implemented following operators.

- `operator+(const T&)`
- `operator-(const T&)`
- `operator*(const double)`

If you have these operator overloads, you can use that variable completely as same as other built-in variables.
Please see `custom_class` example for details.


## Embedded Libraries

- [Easing v0.1.0](https://github.com/hideakitai/Easing)
- [PollingTimer v0.2.0](https://github.com/hideakitai/PollingTimer)
- [ArxTypeTraits v0.1.11](https://github.com/hideakitai/ArxTypeTraits)
- [ArxContainer v0.3.6](https://github.com/hideakitai/ArxContainer)
- [ArxSmartPtr v0.1.1](https://github.com/hideakitai/ArxSmartPtr)
- [TeensyDirtySTLErrorSolution v0.1.0](https://github.com/hideakitai/TeensyDirtySTLErrorSolution)


## License

MIT
8 changes: 8 additions & 0 deletions Tween.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef ARDUINOTWEEN_H
#define ARDUINOTWEEN_H

#include "Tween/Timeline.h"

namespace Tween = ht::tween;

#endif // ARDUINOTWEEN_H
107 changes: 107 additions & 0 deletions Tween/Sequence.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once
#ifndef HT_TWEEN_SEQUENCE_H
#define HT_TWEEN_SEQUENCE_H

#include "Types.h"
#include "Transition.h"

namespace ht {
namespace tween {

namespace sequence {

struct Base
{
virtual ~Base() {}
virtual void update(const uint32_t curr_ms) = 0;
};


template <typename T>
class Sequence : public Base
{
struct trans_t
{
int32_t begin_ms;
int32_t end_ms;
TransitionRef ref;
};

T& target;
T prev_target;
Vec<trans_t> transitions;

public:

virtual ~Sequence() {}

template <typename EasingType = Ease::Linear, typename U = T>
Sequence(T& from, const U& to, const int32_t in, const EasingType&,
typename std::enable_if<std::is_convertible<U, T>::value>::type* = nullptr
)
: target(from)
{
transitions.emplace_back(trans_t{0, in, make_shared<Transition<T, EasingType>>(target, from, to, in)});
prev_target = (T)to;
}

template <typename EasingType = Ease::Linear, typename U = T>
auto then(const U& to, const int32_t in)
-> typename std::enable_if<std::is_convertible<U, T>::value, Sequence<T>&>::type
{
transitions.emplace_back(trans_t{duration(), duration() + in, make_shared<Transition<T, EasingType>>(target, prev_target, to, in)});
prev_target = (T)to;
return *this;
}

Sequence<T>& wait(const int32_t in)
{
transitions.emplace_back(trans_t{duration(), duration() + in, make_shared<Transition<T, Ease::Linear>>(target, prev_target, prev_target, in)});
return *this;
}

virtual void update(const uint32_t curr_ms) override
{
if (transitions.empty()) return;

const size_t idx = from_time_to_index(curr_ms);
if (idx >= transitions.size()) return;

transitions[idx].ref->update(curr_ms - transitions[idx].begin_ms);
}

int32_t duration() const
{
int32_t duration_ms = 0;
for (const auto& t : transitions)
duration_ms += t.ref->duration();
return duration_ms;
}

size_t size() const { return transitions.size(); }
bool empty() const { return transitions.size() == 0; }
void clear() { transitions.clear(); }

private:

size_t from_time_to_index(const int32_t ms) const
{
if (ms < 0) return 0;
for (size_t i = 0; i < transitions.size(); ++i)
if (transitions[i].end_ms > ms)
return i;
return transitions.size();
}

};

} // sequence

template <typename T>
using Sequence = sequence::Sequence<T>;
using SequenceRef = Ref<sequence::Base>;

} // tween
} // ht

#endif // HT_TWEEN_SEQUENCE_H
44 changes: 44 additions & 0 deletions Tween/Timeline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

#ifndef TWEEN_DUINO_TIMELINE_H
#define TWEEN_DUINO_TIMELINE_H

#include "Types.h"
#include "Sequence.h"
#include "util/PollingTimer/PollingTimer.h"

namespace ht {
namespace tween {

class Timeline : public PollingTimer
{
Map<void*, SequenceRef> seqs;

public:

template <typename EasingType = Ease::Linear, typename T, typename U>
auto add(T& target, const U& to, const int32_t in)
-> typename std::enable_if<std::is_convertible<U, T>::value, Sequence<T>&>::type
{
auto p = make_shared<Sequence<T>>(target, to, in, EasingType());
seqs.insert(make_pair((void*)&target, (SequenceRef)p));
return *p;
}

void update()
{
if (!isRunning()) return;
for (auto& s : seqs)
s.second->update(msec());
}

void clear()
{
seqs.clear();
PollingTimer::stop();
}
};

} // tween
} // ht

#endif
99 changes: 99 additions & 0 deletions Tween/Transition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once
#ifndef HT_TWEEN_TRANSITION_H
#define HT_TWEEN_TRANSITION_H

#include "Types.h"
#include "util/Easing/Easing.h"

struct CRGB;
struct CHSV;

namespace ht {
namespace tween {

namespace transition
{
struct Base
{
virtual ~Base() {}
virtual bool update(const int32_t t) = 0;
virtual int32_t duration() const = 0;
};


template <typename T, typename EasingType>
class Transition : public Base
{
T& ref;
const T from;
const T to;
const T diff;
const int32_t duration_ms;
EasingFunc<EasingType> ease;

public:

Transition(T& target, const T& from, const T& to, const int32_t in)
: ref(target)
, from(from)
, to(to)
, diff(to - from)
, duration_ms(in)
{
}

virtual ~Transition() {}

virtual bool update(const int32_t t) override
{
if (t < 0)
ref = from;
else if (t > duration_ms)
ref = to;
else
{
ref = lerp(t);
return true;
}
return false;
}

virtual int32_t duration() const { return duration_ms; }

private:

template <typename U = T>
auto lerp(const float t)
-> typename std::enable_if<
!std::is_same<U, CRGB>::value && !std::is_same<U, CHSV>::value,
U
>::type
{
return diff * ease.get((float)t / (float)duration_ms) + from;
}

template <typename U = T>
auto lerp(const float t)
-> typename std::enable_if<
std::is_same<U, CRGB>::value || std::is_same<U, CHSV>::value,
U
>::type
{
float rgb[3];
const float rate = ease.get((float)t / (float)duration_ms);
for (size_t i = 0; i < 3; ++i)
rgb[i] = ((float)to[i] - (float)from[i]) * rate + (float)from[i];
return U(rgb[0], rgb[1], rgb[2]);
}
};

} // transition

template <typename T, typename EasingType>
using Transition = transition::Transition<T, EasingType>;
using TransitionRef = Ref<transition::Base>;

} // tween
} // ht

#endif // HT_TWEEN_TRANSITION_H
Loading

0 comments on commit 35b8a0a

Please sign in to comment.