| Flutter Impeller |

aiks_playground_inspector.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/aiks/aiks_playground_inspector.h"
6
7 #include <initializer_list>
8
9 #include "impeller/core/capture.h"
10 #include "impeller/entity/entity_pass.h"
11 #include "impeller/renderer/context.h"
12 #include "third_party/imgui/imgui.h"
13 #include "third_party/imgui/imgui_internal.h"
14
15 namespace impeller {
16
17 static const char* kElementsWindowName = "Elements";
18 static const char* kPropertiesWindowName = "Properties";
19
20 static const std::initializer_list<std::string> kSupportedDocuments = {
21 EntityPass::kCaptureDocumentName};
22
23 AiksInspector::AiksInspector() = default;
24
25 const std::optional<Picture>& AiksInspector::RenderInspector(
26 AiksContext& aiks_context,
27 const std::function<std::optional<Picture>()>& picture_callback) {
28 //----------------------------------------------------------------------------
29 /// Configure the next frame.
30 ///
31
32 RenderCapture(aiks_context.GetContext()->capture);
33
34 //----------------------------------------------------------------------------
35 /// Configure the next frame.
36 ///
37
38 if (ImGui::IsKeyPressed(ImGuiKey_Z)) {
39 wireframe_ = !wireframe_;
40 aiks_context.GetContentContext().SetWireframe(wireframe_);
41 }
42
43 if (ImGui::IsKeyPressed(ImGuiKey_C)) {
44 capturing_ = !capturing_;
45 if (capturing_) {
46 aiks_context.GetContext()->capture =
47 CaptureContext::MakeAllowlist({kSupportedDocuments});
48 }
49 }
50 if (!capturing_) {
51 hovered_element_ = nullptr;
52 selected_element_ = nullptr;
53 aiks_context.GetContext()->capture = CaptureContext::MakeInactive();
54 std::optional<Picture> new_picture = picture_callback();
55
56 // If the new picture doesn't have a pass, that means it was already moved
57 // into the inspector. Simply re-emit the last received valid picture.
58 if (!new_picture.has_value() || new_picture->pass) {
59 last_picture_ = std::move(new_picture);
60 }
61 }
62
63 return last_picture_;
64 }
65
66 void AiksInspector::HackResetDueToTextureLeaks() {
67 last_picture_.reset();
68 }
69
70 static const auto kPropertiesProcTable = CaptureProcTable{
71 .boolean =
72 [](CaptureBooleanProperty& p) {
73 ImGui::Checkbox(p.label.c_str(), &p.value);
74 },
75 .integer =
76 [](CaptureIntegerProperty& p) {
77 if (p.options.range.has_value()) {
78 ImGui::SliderInt(p.label.c_str(), &p.value,
79 static_cast<int>(p.options.range->min),
80 static_cast<int>(p.options.range->max));
81 return;
82 }
83 ImGui::InputInt(p.label.c_str(), &p.value);
84 },
85 .scalar =
86 [](CaptureScalarProperty& p) {
87 if (p.options.range.has_value()) {
88 ImGui::SliderFloat(p.label.c_str(), &p.value, p.options.range->min,
89 p.options.range->max);
90 return;
91 }
92 ImGui::DragFloat(p.label.c_str(), &p.value, 0.01);
93 },
94 .point =
95 [](CapturePointProperty& p) {
96 if (p.options.range.has_value()) {
97 ImGui::SliderFloat2(p.label.c_str(),
98 reinterpret_cast<float*>(&p.value),
99 p.options.range->min, p.options.range->max);
100 return;
101 }
102 ImGui::DragFloat2(p.label.c_str(), reinterpret_cast<float*>(&p.value),
103 0.01);
104 },
105 .vector3 =
106 [](CaptureVector3Property& p) {
107 if (p.options.range.has_value()) {
108 ImGui::SliderFloat3(p.label.c_str(),
109 reinterpret_cast<float*>(&p.value),
110 p.options.range->min, p.options.range->max);
111 return;
112 }
113 ImGui::DragFloat3(p.label.c_str(), reinterpret_cast<float*>(&p.value),
114 0.01);
115 },
116 .rect =
117 [](CaptureRectProperty& p) {
118 ImGui::DragFloat4(p.label.c_str(), reinterpret_cast<float*>(&p.value),
119 0.01);
120 },
121 .color =
122 [](CaptureColorProperty& p) {
123 ImGui::ColorEdit4(p.label.c_str(),
124 reinterpret_cast<float*>(&p.value));
125 },
126 .matrix =
127 [](CaptureMatrixProperty& p) {
128 float* pointer = reinterpret_cast<float*>(&p.value);
129 ImGui::DragFloat4((p.label + " X basis").c_str(), pointer, 0.001);
130 ImGui::DragFloat4((p.label + " Y basis").c_str(), pointer + 4, 0.001);
131 ImGui::DragFloat4((p.label + " Z basis").c_str(), pointer + 8, 0.001);
132 ImGui::DragFloat4((p.label + " Translation").c_str(), pointer + 12,
133 0.001);
134 },
135 .string =
136 [](CaptureStringProperty& p) {
137 ImGui::InputTextEx(p.label.c_str(), "",
138 // Fine as long as it's read-only.
139 const_cast<char*>(p.value.c_str()), p.value.size(),
140 ImVec2(0, 0), ImGuiInputTextFlags_ReadOnly);
141 },
142 };
143
144 void AiksInspector::RenderCapture(CaptureContext& capture_context) {
145 if (!capturing_) {
146 return;
147 }
148
149 auto document = capture_context.GetDocument(EntityPass::kCaptureDocumentName);
150
151 //----------------------------------------------------------------------------
152 /// Setup a shared dockspace to collect the capture windows.
153 ///
154
155 ImGui::SetNextWindowBgAlpha(0.5);
156 ImGui::Begin("Capture");
157 auto dockspace_id = ImGui::GetID("CaptureDockspace");
158 if (!ImGui::DockBuilderGetNode(dockspace_id)) {
159 ImGui::SetWindowSize(ImVec2(370, 680));
160 ImGui::SetWindowPos(ImVec2(640, 55));
161
162 ImGui::DockBuilderRemoveNode(dockspace_id);
163 ImGui::DockBuilderAddNode(dockspace_id);
164
165 ImGuiID opposite_id;
166 ImGuiID up_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Up, 0.6,
167 nullptr, &opposite_id);
168 ImGuiID down_id = ImGui::DockBuilderSplitNode(opposite_id, ImGuiDir_Down,
169 0.0, nullptr, nullptr);
170 ImGui::DockBuilderDockWindow(kElementsWindowName, up_id);
171 ImGui::DockBuilderDockWindow(kPropertiesWindowName, down_id);
172
173 ImGui::DockBuilderFinish(dockspace_id);
174 }
175 ImGui::DockSpace(dockspace_id);
176 ImGui::End(); // Capture window.
177
178 //----------------------------------------------------------------------------
179 /// Element hierarchy window.
180 ///
181
182 ImGui::Begin(kElementsWindowName);
183 auto root_element = document.GetElement();
184 hovered_element_ = nullptr;
185 if (root_element) {
186 RenderCaptureElement(*root_element);
187 }
188 ImGui::End(); // Hierarchy window.
189
190 if (selected_element_) {
191 //----------------------------------------------------------------------------
192 /// Properties window.
193 ///
194
195 ImGui::Begin(kPropertiesWindowName);
196 {
197 selected_element_->properties.Iterate([&](CaptureProperty& property) {
198 property.Invoke(kPropertiesProcTable);
199 });
200 }
201 ImGui::End(); // Inspector window.
202
203 //----------------------------------------------------------------------------
204 /// Selected coverage highlighting.
205 ///
206
207 auto coverage_property =
208 selected_element_->properties.FindFirstByLabel("Coverage");
209 if (coverage_property) {
210 auto coverage = coverage_property->AsRect();
211 if (coverage.has_value()) {
212 Scalar scale = ImGui::GetWindowDpiScale();
213 ImGui::GetBackgroundDrawList()->AddRect(
214 ImVec2(coverage->GetLeft() / scale,
215 coverage->GetTop() / scale), // p_min
216 ImVec2(coverage->GetRight() / scale,
217 coverage->GetBottom() / scale), // p_max
218 0x992222FF, // col
219 0.0, // rounding
220 ImDrawFlags_None, // flags
221 8.0); // thickness
222 }
223 }
224 }
225
226 //----------------------------------------------------------------------------
227 /// Hover coverage highlight.
228 ///
229
230 if (hovered_element_) {
231 auto coverage_property =
232 hovered_element_->properties.FindFirstByLabel("Coverage");
233 if (coverage_property) {
234 auto coverage = coverage_property->AsRect();
235 if (coverage.has_value()) {
236 Scalar scale = ImGui::GetWindowDpiScale();
237 ImGui::GetBackgroundDrawList()->AddRect(
238 ImVec2(coverage->GetLeft() / scale,
239 coverage->GetTop() / scale), // p_min
240 ImVec2(coverage->GetRight() / scale,
241 coverage->GetBottom() / scale), // p_max
242 0x66FF2222, // col
243 0.0, // rounding
244 ImDrawFlags_None, // flags
245 8.0); // thickness
246 }
247 }
248 }
249 }
250
251 void AiksInspector::RenderCaptureElement(CaptureElement& element) {
252 ImGui::PushID(&element);
253
254 bool is_selected = selected_element_ == &element;
255 bool has_children = element.children.Count() > 0;
256
257 bool opened = ImGui::TreeNodeEx(
258 element.label.c_str(), (is_selected ? ImGuiTreeNodeFlags_Selected : 0) |
259 (has_children ? 0 : ImGuiTreeNodeFlags_Leaf) |
260 ImGuiTreeNodeFlags_SpanFullWidth |
261 ImGuiTreeNodeFlags_OpenOnArrow |
262 ImGuiTreeNodeFlags_DefaultOpen);
263 if (ImGui::IsItemClicked()) {
264 selected_element_ = &element;
265 }
266 if (ImGui::IsItemHovered()) {
267 hovered_element_ = &element;
268 }
269 if (opened) {
270 element.children.Iterate(
271 [&](CaptureElement& child) { RenderCaptureElement(child); });
272 ImGui::TreePop();
273 }
274 ImGui::PopID();
275 }
276
277 } // namespace impeller
impeller::kSupportedDocuments
static const std::initializer_list< std::string > kSupportedDocuments
Definition: aiks_playground_inspector.cc:20
aiks_playground_inspector.h
capture.h
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::AiksContext
Definition: aiks_context.h:20
impeller::AiksContext::GetContentContext
ContentContext & GetContentContext() const
Definition: aiks_context.cc:44
impeller::AiksInspector::RenderInspector
const std::optional< Picture > & RenderInspector(AiksContext &aiks_context, const std::function< std::optional< Picture >()> &picture_callback)
Definition: aiks_playground_inspector.cc:25
impeller::AiksInspector::HackResetDueToTextureLeaks
void HackResetDueToTextureLeaks()
Definition: aiks_playground_inspector.cc:66
impeller::kPropertiesProcTable
static const auto kPropertiesProcTable
Definition: aiks_playground_inspector.cc:70
impeller::kPropertiesWindowName
static const char * kPropertiesWindowName
Definition: aiks_playground_inspector.cc:18
impeller::kElementsWindowName
static const char * kElementsWindowName
Definition: aiks_playground_inspector.cc:17
impeller::CaptureContext::MakeAllowlist
static CaptureContext MakeAllowlist(std::initializer_list< std::string > allowlist)
Definition: capture.cc:159
impeller::CaptureElement::children
CapturePlaybackList< CaptureElement > children
Definition: capture.h:201
impeller::CaptureContext::MakeInactive
static CaptureContext MakeInactive()
Definition: capture.cc:155
impeller::AiksInspector::AiksInspector
AiksInspector()
entity_pass.h
impeller::AiksContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: aiks_context.cc:40
impeller::CaptureProcTable
Definition: capture.h:129
scale
const Scalar scale
Definition: stroke_path_geometry.cc:297
impeller::ContentContext::SetWireframe
void SetWireframe(bool wireframe)
Definition: content_context.cc:572
context.h
impeller::EntityPass::kCaptureDocumentName
static const std::string kCaptureDocumentName
Definition: entity_pass.h:56
impeller
Definition: aiks_blur_unittests.cc:20
impeller::CaptureElement::properties
CapturePlaybackList< CaptureProperty > properties
Definition: capture.h:200