Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MSKPSlide.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
14#include "include/core/SkRect.h"
18
19#include <cstddef>
20#include <utility>
21
22#include "imgui.h"
23
25 : MSKPSlide(name, SkStream::MakeFromFile(path.c_str())) {}
26
27MSKPSlide::MSKPSlide(const SkString& name, std::unique_ptr<SkStreamSeekable> stream)
28 : fStream(std::move(stream)) {
29 fName = name;
30}
31
33 return fPlayer ? fPlayer->maxDimensions() : SkISize{0, 0};
34}
35
37 if (!fPlayer) {
38 ImGui::Text("Could not read mskp file %s.\n", fName.c_str());
39 return;
40 }
41 ImGui::Begin("MSKP");
42
43 ImGui::BeginGroup();
44 // Play/Pause button
45 if (ImGui::Button(fPaused ? "Play " : "Pause")) {
46 fPaused = !fPaused;
47 if (fPaused) {
48 // This will ensure that when playback is unpaused we start on the current frame.
49 fLastFrameTime = -1;
50 }
51 }
52 // Control the frame rate of MSKP playback
53 ImGui::Text("FPS: "); ImGui::SameLine();
54 ImGui::RadioButton( "1", &fFPS, 1); ImGui::SameLine();
55 ImGui::RadioButton( "15", &fFPS, 15); ImGui::SameLine();
56 ImGui::RadioButton( "30", &fFPS, 30); ImGui::SameLine();
57 ImGui::RadioButton( "60", &fFPS, 60); ImGui::SameLine();
58 ImGui::RadioButton("120", &fFPS, 120); ImGui::SameLine();
59 ImGui::RadioButton("1:1", &fFPS, -1); // Draw one MSKP frame for each real viewer frame.
60 if (fFPS < 0) {
61 // Like above, will cause onAnimate() to resume at current frame when FPS is changed
62 // back to another frame rate.
63 fLastFrameTime = -1;
64 }
65 // Frame control. Slider and +/- buttons. Ctrl-Click slider to type frame number.
66 ImGui::Text("Frame:");
67 ImGui::SameLine();
68 ImGui::PushButtonRepeat(true); // Enable click-and-hold for frame arrows.
69 int oldFrame = fFrame;
70 if (ImGui::ArrowButton("-mksp_frame", ImGuiDir_Left)) {
71 fFrame = (fFrame + fPlayer->numFrames() - 1)%fPlayer->numFrames();
72 }
73 ImGui::SameLine();
74 if (ImGui::SliderInt("##msk_frameslider", &fFrame, 0, fPlayer->numFrames()-1, "% 3d")) {
75 fFrame = SkTPin(fFrame, 0, fPlayer->numFrames() - 1);
76 }
77 ImGui::SameLine();
78 if (ImGui::ArrowButton("+mskp_frame", ImGuiDir_Right)) {
79 fFrame = (fFrame + 1)%fPlayer->numFrames();
80 }
81 if (fFrame != oldFrame) {
82 // When manually adjusting frames force layers to redraw.
83 this->redrawLayers();
84 }
85
86 ImGui::PopButtonRepeat();
87 ImGui::EndGroup();
88
89 ImGui::BeginGroup();
90 ImGui::Checkbox("Show Frame Bounds", &fShowFrameBounds);
91 ImGui::SetNextItemWidth(200);
92 ImGui::ColorPicker4("background", fBackgroundColor, ImGuiColorEditFlags_AlphaBar);
93 // ImGui lets user enter out of range values by typing.
94 for (float& component : fBackgroundColor) {
95 component = SkTPin(component, 0.f, 1.f);
96 }
97 ImGui::EndGroup();
98
99 // UI for visualizing contents of offscreen layers.
100 ImGui::Text("Offscreen Layers "); ImGui::SameLine();
101 ImGui::Checkbox("List All Layers", &fListAllLayers);
102 ImGui::RadioButton("root", &fDrawLayerID, -1);
103 const std::vector<int>& layerIDs = fListAllLayers ? fAllLayerIDs : fFrameLayerIDs[fFrame];
104 fLayerIDStrings.resize(layerIDs.size());
105 for (size_t i = 0; i < layerIDs.size(); ++i) {
106 fLayerIDStrings[i] = SkStringPrintf("%d", layerIDs[i]);
107 ImGui::RadioButton(fLayerIDStrings[i].c_str(), &fDrawLayerID, layerIDs[i]);
108 }
109 ImGui::End();
110
111 auto bounds = SkIRect::MakeSize(fPlayer->frameDimensions(fFrame));
112
113 if (fShowFrameBounds) {
114 SkPaint boundsPaint;
115 boundsPaint.setStyle(SkPaint::kStroke_Style);
116 boundsPaint.setColor(SK_ColorRED);
117 boundsPaint.setStrokeWidth(0.f);
118 boundsPaint.setAntiAlias(true);
119 // Outset so that at default scale we draw at pixel centers of the rows/cols surrounding the
120 // bounds.
121 canvas->drawRect(SkRect::Make(bounds).makeOutset(0.5f, 0.5f), boundsPaint);
122 }
123
124 canvas->save();
125 if (fDrawLayerID >= 0) {
126 // clip out the root layer content, but still call playFrame so layer contents are updated
127 // to fFrame.
128 bounds = SkIRect::MakeEmpty();
129 }
130 canvas->clipIRect(bounds);
131 canvas->clear(SkColor4f{fBackgroundColor[0],
132 fBackgroundColor[1],
133 fBackgroundColor[2],
134 fBackgroundColor[3]});
135 fPlayer->playFrame(canvas, fFrame);
136 canvas->restore();
137
138 if (fDrawLayerID >= 0) {
139 if (sk_sp<SkImage> layerImage = fPlayer->layerSnapshot(fDrawLayerID)) {
140 canvas->save();
141 canvas->clipIRect(SkIRect::MakeSize(layerImage->dimensions()));
142 canvas->clear(SkColor4f{fBackgroundColor[0],
143 fBackgroundColor[1],
144 fBackgroundColor[2],
145 fBackgroundColor[3]});
146 canvas->drawImage(std::move(layerImage), 0, 0);
147 canvas->restore();
148 }
149 return;
150 }
151}
152
153bool MSKPSlide::animate(double nanos) {
154 if (!fPlayer || fPaused) {
155 return false;
156 }
157 if (fLastFrameTime < 0) {
158 // We're coming off being paused or switching from 1:1 mode to steady FPS. Advance 1 frame
159 // and reset the frame time to start accumulating time from now.
160 fFrame = (fFrame + 1)%fPlayer->numFrames();
161 fLastFrameTime = nanos;
162 return this->fPlayer->numFrames() > 1;
163 }
164 if (fFPS < 0) {
165 // 1:1 mode. Always draw the next frame on each animation cycle.
166 fFrame = (fFrame + 1)%fPlayer->numFrames();
167 return this->fPlayer->numFrames() > 1;
168 }
169 double elapsed = nanos - fLastFrameTime;
170 double frameTime = 1E9/fFPS;
171 int framesToAdvance = elapsed/frameTime;
172 fFrame = fFrame + framesToAdvance;
173 if (fFrame >= fPlayer->numFrames()) {
174 this->redrawLayers();
175 }
176 fFrame %= fPlayer->numFrames();
177 // Instead of just adding elapsed, note the time when this frame should have begun.
178 fLastFrameTime += framesToAdvance*frameTime;
179 return framesToAdvance > 0;
180}
181
183 if (!fStream) {
184 return;
185 }
186 fStream->rewind();
187 fPlayer = MSKPPlayer::Make(fStream.get());
188 if (!fPlayer) {
189 return;
190 }
191 fAllLayerIDs = fPlayer->layerIDs();
192 fFrameLayerIDs.clear();
193 fFrameLayerIDs.resize(fPlayer->numFrames());
194 for (int i = 0; i < fPlayer->numFrames(); ++i) {
195 fFrameLayerIDs[i] = fPlayer->layerIDs(i);
196 }
197}
198
199void MSKPSlide::unload() { fPlayer.reset(); }
200
202 if (fPlayer) {
203 fPlayer->resetLayers();
204 }
205}
206
207void MSKPSlide::redrawLayers() {
208 if (fDrawLayerID >= 0) {
209 // Completely reset the layers so that we won't see content from later frames on layers
210 // that haven't been visited from frames 0..fFrames.
211 fPlayer->resetLayers();
212 } else {
213 // Just rewind layers so that we redraw any layer from scratch on the next frame that
214 // updates it. Important for benchmarking/profiling as otherwise if a layer is only
215 // drawn once in the frame sequence then it will never be updated after the first play
216 // through. This doesn't reallocate the layer backing stores.
217 fPlayer->rewindLayers();
218 }
219}
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
SK_API SkString static SkString SkStringPrintf()
Definition SkString.h:287
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
static std::unique_ptr< MSKPPlayer > Make(SkStreamSeekable *stream)
bool animate(double nanos) override
void draw(SkCanvas *canvas) override
Definition MSKPSlide.cpp:36
void unload() override
SkISize getDimensions() const override
Definition MSKPSlide.cpp:32
void load(SkScalar winWidth, SkScalar winHeight) override
void gpuTeardown() override
MSKPSlide(const SkString &name, const SkString &path)
Definition MSKPSlide.cpp:24
void drawRect(const SkRect &rect, const SkPaint &paint)
void restore()
Definition SkCanvas.cpp:465
void clipIRect(const SkIRect &irect, SkClipOp op=SkClipOp::kIntersect)
Definition SkCanvas.h:991
void clear(SkColor color)
Definition SkCanvas.h:1199
int save()
Definition SkCanvas.cpp:451
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
void setStyle(Style style)
Definition SkPaint.cpp:105
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition SkPaint.h:170
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
const char * c_str() const
Definition SkString.h:133
SkString fName
Definition Slide.h:54
float SkScalar
Definition extension.cpp:12
const char * name
Definition fuchsia.cc:50
Definition ref_ptr.h:256
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
static constexpr SkIRect MakeEmpty()
Definition SkRect.h:45
static SkRect Make(const SkISize &size)
Definition SkRect.h:669