[skottie] Add SkottieSlide frame rate UI option
Also store fTimeBase as a double/ns, since uint/ms doesn't have enough precision when setting progress manually. Change-Id: Ic01a55cea5897dd8b43d2d54f4a98e08e7406af8 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/259172 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
b692ce4c63
commit
1bb3a6dae5
@ -145,7 +145,7 @@ void SkottieSlide::draw(SkCanvas* canvas) {
|
|||||||
fAnimation->render(canvas, &dstR);
|
fAnimation->render(canvas, &dstR);
|
||||||
|
|
||||||
// TODO: this does not capture GPU flush time!
|
// TODO: this does not capture GPU flush time!
|
||||||
const auto frame_index = SkToSizeT(SkScalarRoundToInt(fCurrentFrame));
|
const auto frame_index = static_cast<size_t>(fCurrentFrame);
|
||||||
fFrameTimes[frame_index] = static_cast<float>((SkTime::GetNSecs() - t0) * 1e-6);
|
fFrameTimes[frame_index] = static_cast<float>((SkTime::GetNSecs() - t0) * 1e-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,23 +178,30 @@ void SkottieSlide::draw(SkCanvas* canvas) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SkottieSlide::animate(double nanos) {
|
bool SkottieSlide::animate(double nanos) {
|
||||||
SkMSec msec = TimeUtils::NanosToMSec(nanos);
|
if (!fTimeBase) {
|
||||||
if (fTimeBase == 0) {
|
|
||||||
// Reset the animation time.
|
// Reset the animation time.
|
||||||
fTimeBase = msec;
|
fTimeBase = nanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fAnimation) {
|
if (fAnimation) {
|
||||||
fInvalController.reset();
|
fInvalController.reset();
|
||||||
|
|
||||||
|
const auto frame_count = fAnimation->duration() * fAnimation->fps();
|
||||||
|
|
||||||
if (!fDraggingProgress) {
|
if (!fDraggingProgress) {
|
||||||
// Clock-driven progress: update current frame.
|
// Clock-driven progress: update current frame.
|
||||||
const double t_sec = (msec - fTimeBase) / 1000.0;
|
const double t_sec = (nanos - fTimeBase) * 1e-9;
|
||||||
fCurrentFrame = std::fmod(t_sec, fAnimation->duration()) * fAnimation->fps();
|
fCurrentFrame = std::fmod(t_sec * fAnimation->fps(), frame_count);
|
||||||
} else {
|
} else {
|
||||||
// Slider-driven progress: update the time origin.
|
// Slider-driven progress: update the time origin.
|
||||||
fTimeBase = TimeUtils::NanosToMSec(nanos)
|
fTimeBase = nanos - fCurrentFrame / fAnimation->fps() * 1e9;
|
||||||
- static_cast<SkMSec>(fCurrentFrame / fAnimation->fps() * 1000);
|
}
|
||||||
|
|
||||||
|
// Sanitize and rate-lock the current frame.
|
||||||
|
fCurrentFrame = SkTPin<float>(fCurrentFrame, 0.0f, frame_count - 1);
|
||||||
|
if (fFrameRate > 0) {
|
||||||
|
const auto fps_scale = fFrameRate / fAnimation->fps();
|
||||||
|
fCurrentFrame = std::trunc(fCurrentFrame * fps_scale) / fps_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
fAnimation->seekFrame(fCurrentFrame);
|
fAnimation->seekFrame(fCurrentFrame);
|
||||||
@ -230,14 +237,26 @@ bool SkottieSlide::onMouse(SkScalar x, SkScalar y, skui::InputState state, skui:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkRect SkottieSlide::UIArea() const {
|
SkRect SkottieSlide::UIArea() const {
|
||||||
static constexpr float kUIHeight = 150.0f;
|
static constexpr float kUIHeight = 120.0f;
|
||||||
|
|
||||||
return SkRect::MakeXYWH(0, fWinSize.height() - kUIHeight, fWinSize.width(), kUIHeight);
|
return SkRect::MakeXYWH(0, fWinSize.height() - kUIHeight, fWinSize.width(), kUIHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkottieSlide::renderUI() {
|
void SkottieSlide::renderUI() {
|
||||||
static constexpr auto kUI_opacity = 0.35f,
|
static constexpr auto kUI_opacity = 0.35f,
|
||||||
kUI_hist_height = 50.0f;
|
kUI_hist_height = 50.0f,
|
||||||
|
kUI_fps_width = 100.0f;
|
||||||
|
|
||||||
|
auto add_frame_rate_option = [this](const char* label, double rate) {
|
||||||
|
const auto is_selected = (fFrameRate == rate);
|
||||||
|
if (ImGui::Selectable(label, is_selected)) {
|
||||||
|
fFrameRate = rate;
|
||||||
|
fFrameRateLabel = label;
|
||||||
|
}
|
||||||
|
if (is_selected) {
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ImGui::SetNextWindowBgAlpha(kUI_opacity);
|
ImGui::SetNextWindowBgAlpha(kUI_opacity);
|
||||||
if (ImGui::Begin("Skottie Controls", nullptr, ImGuiWindowFlags_NoDecoration |
|
if (ImGui::Begin("Skottie Controls", nullptr, ImGuiWindowFlags_NoDecoration |
|
||||||
@ -251,12 +270,23 @@ void SkottieSlide::renderUI() {
|
|||||||
ImGui::SetWindowSize(ImVec2(ui_area.width(), ui_area.height()));
|
ImGui::SetWindowSize(ImVec2(ui_area.width(), ui_area.height()));
|
||||||
|
|
||||||
ImGui::PushItemWidth(-1);
|
ImGui::PushItemWidth(-1);
|
||||||
|
|
||||||
ImGui::PlotHistogram("", fFrameTimes.data(), fFrameTimes.size(),
|
ImGui::PlotHistogram("", fFrameTimes.data(), fFrameTimes.size(),
|
||||||
0, nullptr, FLT_MAX, FLT_MAX, ImVec2(0, kUI_hist_height));
|
0, nullptr, FLT_MAX, FLT_MAX, ImVec2(0, kUI_hist_height));
|
||||||
ImGui::SliderFloat("", &fCurrentFrame, 0, fAnimation->duration() * fAnimation->fps() - 1);
|
ImGui::SliderFloat("", &fCurrentFrame, 0, fAnimation->duration() * fAnimation->fps() - 1);
|
||||||
fDraggingProgress = ImGui::IsItemActive();
|
fDraggingProgress = ImGui::IsItemActive();
|
||||||
|
ImGui::PopItemWidth();
|
||||||
|
|
||||||
|
ImGui::PushItemWidth(kUI_fps_width);
|
||||||
|
if (ImGui::BeginCombo("FPS", fFrameRateLabel)) {
|
||||||
|
add_frame_rate_option("", 0.0);
|
||||||
|
add_frame_rate_option("Native", fAnimation->fps());
|
||||||
|
add_frame_rate_option( "1", 1.0);
|
||||||
|
add_frame_rate_option("15", 15.0);
|
||||||
|
add_frame_rate_option("24", 24.0);
|
||||||
|
add_frame_rate_option("30", 30.0);
|
||||||
|
add_frame_rate_option("60", 60.0);
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -46,7 +46,9 @@ private:
|
|||||||
sksg::InvalidationController fInvalController;
|
sksg::InvalidationController fInvalController;
|
||||||
std::vector<float> fFrameTimes;
|
std::vector<float> fFrameTimes;
|
||||||
SkSize fWinSize = SkSize::MakeEmpty();
|
SkSize fWinSize = SkSize::MakeEmpty();
|
||||||
SkMSec fTimeBase = 0;
|
double fTimeBase = 0,
|
||||||
|
fFrameRate = 0;
|
||||||
|
const char* fFrameRateLabel = nullptr;
|
||||||
float fCurrentFrame = 0;
|
float fCurrentFrame = 0;
|
||||||
bool fShowAnimationInval = false,
|
bool fShowAnimationInval = false,
|
||||||
fShowAnimationStats = false,
|
fShowAnimationStats = false,
|
||||||
|
Loading…
Reference in New Issue
Block a user