UI: Add delay to tweens.

Also allow them to start out in an invalid state and accept first divert.
This commit is contained in:
Unknown W. Brackets committed 2017-12-10 09:00:52 -08:00
1 parent cd2dfd5c9a
commit 46ea88e096
4 files changed
+55 -14

No files matched your search

+2
View File
@@ -831,7 +831,9 @@ void EmuScreen::CreateViews() {
// We start invisible here, in case of recreated views.
loadingViewColor_ = loadingView_->AddTween(new TextColorTween(0x00FFFFFF, 0x00FFFFFF, 0.2f, &bezierEaseInOut));
loadingViewColor_->Persist();
loadingViewVisible_ = loadingView_->AddTween(new VisibilityTween(UI::V_INVISIBLE, UI::V_INVISIBLE, 0.2f, &bezierEaseInOut));
loadingViewVisible_->Persist();
}
UI::EventReturn EmuScreen::OnDevTools(UI::EventParams &params) {
+10 -1
View File
@@ -5,7 +5,10 @@
namespace UI {
void Tween::Apply(View *view) {
if (time_now() >= start_ + duration_)
if (!valid_)
return;
if (DurationOffset() >= duration_)
finishApplied_ = true;
float pos = Position();
@@ -17,8 +20,10 @@ void TweenBase<Value>::PersistData(PersistStatus status, std::string anonId, Per
struct TweenData {
float start;
float duration;
float delay;
Value from;
Value to;
bool valid;
};
PersistBuffer &buffer = storage["TweenBase::" + anonId];
@@ -30,8 +35,10 @@ void TweenBase<Value>::PersistData(PersistStatus status, std::string anonId, Per
TweenData &data = *(TweenData *)&buffer[0];
data.start = start_;
data.duration = duration_;
data.delay = delay_;
data.from = from_;
data.to = to_;
data.valid = valid_;
}
break;
case UI::PERSIST_RESTORE:
@@ -39,8 +46,10 @@ void TweenBase<Value>::PersistData(PersistStatus status, std::string anonId, Per
TweenData data = *(TweenData *)&buffer[0];
start_ = data.start;
duration_ = data.duration;
delay_ = data.delay;
from_ = data.from;
to_ = data.to;
valid_ = data.valid;
// We skip finishApplied_ here so that the tween will reapply.
// This does mean it's important to remember to update tweens even after finish.
}
+35 -11
View File
@@ -10,7 +10,7 @@ namespace UI {
// This is the class to use in Update().
class Tween {
public:
Tween(float duration, float (*curve)(float)) : duration_(duration), curve_(curve) {
explicit Tween(float duration, float (*curve)(float)) : duration_(duration), curve_(curve) {
start_ = time_now();
}
virtual ~Tween() {
@@ -20,14 +20,25 @@ public:
void Apply(View *view);
bool Finished() {
return finishApplied_ && time_now() >= start_ + duration_;
return finishApplied_ && time_now() >= start_ + delay_ + duration_;
}
void Persist() {
persists_ = true;
}
bool Persists() {
return persists_;
}
void Delay(float s) {
delay_ = s;
}
virtual void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) = 0;
protected:
float DurationOffset() {
return time_now() - start_;
return time_now() - start_ - delay_;
}
float Position() {
@@ -38,7 +49,10 @@ protected:
float start_;
float duration_;
float delay_ = 0.0f;
bool finishApplied_ = false;
bool persists_ = false;
bool valid_ = false;
float (*curve_)(float);
};
@@ -47,29 +61,37 @@ protected:
template <typename Value>
class TweenBase: public Tween {
public:
TweenBase(float duration, float (*curve)(float) = [](float f) { return f; })
: Tween(duration, curve) {
}
TweenBase(Value from, Value to, float duration, float (*curve)(float) = [](float f) { return f; })
: Tween(duration, curve), from_(from), to_(to) {
valid_ = true;
}
// Use this to change the destination value.
// Useful when a state flips while the tween is half-way through.
void Divert(const Value &newTo, float newDuration = -1.0f) {
const Value newFrom = Current(Position());
const Value newFrom = valid_ ? Current(Position()) : newTo;
// Are we already part way through another transition?
if (time_now() < start_ + duration_) {
if (time_now() < start_ + delay_ + duration_ && valid_) {
if (newTo == to_) {
// Already on course. Don't change.
} else if (newTo == from_) {
return;
} else if (newTo == from_ && duration_ > 0.0f) {
// Reversing, adjust start_ to be smooth from the current value.
float newOffset = duration_ - DurationOffset();
if (newDuration >= 0.0f && duration_ > 0.0f) {
float newOffset = duration_ - std::max(0.0f, DurationOffset());
if (newDuration >= 0.0f) {
newOffset *= newDuration / duration_;
}
start_ = time_now() - newOffset;
} else {
// Otherwise, start over.
start_ = time_now() - newOffset - delay_;
} else if (time_now() <= start_ + delay_) {
// Start the delay over again.
start_ = time_now();
} else {
// Since we've partially animated to the other value, skip delay.
start_ = time_now() - delay_;
}
} else {
// Already finished, so restart.
@@ -79,6 +101,7 @@ public:
from_ = newFrom;
to_ = newTo;
valid_ = true;
if (newDuration >= 0.0f) {
duration_ = newDuration;
}
@@ -93,6 +116,7 @@ public:
void Reset(const Value &newFrom) {
from_ = newFrom;
to_ = newFrom;
valid_ = true;
}
const Value &FromValue() const {
+8 -2
View File
@@ -169,9 +169,15 @@ View::~View() {
}
void View::Update() {
for (Tween *tween : tweens_) {
if (!tween->Finished())
for (size_t i = 0; i < tweens_.size(); ++i) {
Tween *tween = tweens_[i];
if (!tween->Finished()) {
tween->Apply(this);
} else if (!tween->Persists()) {
tweens_.erase(tweens_.begin() + i);
i--;
delete tween;
}
}
}