mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
UI: Add delay to tweens.
Also allow them to start out in an invalid state and accept first divert.
This commit is contained in:
1 parent
cd2dfd5c9a
commit
46ea88e096
4 files changed
+55
-14
No files matched your search
@@ -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 ¶ms) {
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user