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 
6 
7 #include <initializer_list>
8 
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 = {
22 
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 =
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 
67  last_picture_.reset();
68 }
69 
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