DebugLayer class new in Git master
Debug layer.
Provides a non-intrusive and extensible way to inspect node hierarchy and layer data attachments in any existing UI for debugging purposes. You can use either the DebugLayer base for inspection alone, or the DebugLayerGL subclass that provides also a way to visualize highlighted nodes directly in the inspected UI.
Setting up a debug layer instance
A debug layer, either DebugLayer or DebugLayerGL, is constructed using a fresh AbstractUserInterface::
Ui::DebugLayer& debugLayer = ui.setLayerInstance( Containers::pointer<Ui::DebugLayerGL>(ui.createLayer(), Ui::DebugLayerSource::NodeHierarchy| Ui::DebugLayerSource::NodeData, Ui::DebugLayerFlag::NodeInspect));
With this, assuming AbstractUserInterface::
Inspecting nodes
The setup shown above, in particular with DebugLayerFlag::
Ui::NodeHandle button = Ui::button(…, Ui::Icon::Yes, "Accept"); ui.eventLayer().onTapOrClick(button, []{ … });

With the DebugLayer set up, clicking on this button with Ctrl right mouse button (or Ctrl pen eraser in case of a pen input) highlights the node, showing a magenta rectangle over, and prints details about it to the console like shown below. Clicking on any other node will inspect that one instead, clicking again on the inspected node will remove the highlight.

Node {0x9, 0x2}
Nested at level 1 with 0 direct children
4 data from 3 layersWith DebugLayerSource::
Naming nodes, layers, layouters and animators
In the details we can see that the node is placed somewhere and it has four data attachments. Because the widget is simple we can assume it's the background, the icon, the text and the event handler. It would be better if the layer could tell us that, but because naming various resources isn't essential to UI functionality, and because the DebugLayer is designed to work with any custom user interface containing any custom layers, not just the builtin ones, it can't have any knowledge about layer names on its own.
We have to supply those with setLayerName(). In this case we'll name all layers exposed on the UserInterface instance, you can do the same for any custom layer as well. Similarly, setNodeName() allows to assign names to particular nodes.
debugLayer.setLayerName(ui.eventLayer(), "Event"); debugLayer.setLayerName(ui.baseLayer(), "Base"); debugLayer.setLayerName(ui.textLayer(), "Text"); debugLayer.setNodeName(button, "Accept button");
Inspecting the same node then groups the data by layer, showing them in the order they're drawn. Besides the names now being listed in the printed details, you can query them back with layerName() and nodeName().
Node {0x9, 0x2} Accept button Nested at level 1 with 0 direct children 1 data from layer {0x0, 0x1} Base 2 data from layer {0x1, 0x1} Text 1 data from layer {0x2, 0x1} Event
Similarly to layers, setLayouterName() and setAnimatorName() can name layouters and animators.
Showing details about node data, layouts and animations
Enabling DebugLayerSource::
Node {0x9, 0x2} Accept button Nested at level 1 with 0 direct children Data {0x3, 0x2} from layer {0x0, 0x1} Base Inactive out style: 1 Inactive over style: 2 Pressed out style: 3 Pressed over style: 4 Disabled style: 5 Data {0x6, 0x1} from layer {0x1, 0x1} Text Inactive style: 3 Pressed style: 7 Disabled style: 11 Data {0x7, 0x1} from layer {0x1, 0x1} Text Inactive style: 4 Pressed style: 8 Disabled style: 12 Data {0x0, 0x1} from layer {0x2, 0x1} Event reacting to tap or click
The way this works is that by passing a concrete layer type, the setLayerName(const T&, const Containers::
With DebugLayerSource::
Node inspect options
Node inspect has defaults chosen in a way that makes the highlight clearly visible on most backgrounds, and with the pointer gesture unique enough to not conflict with usual event handlers. You can change both with setNodeInspectColor() and setNodeInspectGesture().
The default set of accepted gestures does not include touch input however, as on a touch device it usually isn't possible to press any modifier keys to distinguish a "debug tap" from a regular tap. It's however possible to use addFlags() and clearFlags() to enable DebugLayerFlag::
/* Enable node inspection with just a touch */ debugLayer .addFlags(Ui::DebugLayerFlag::NodeInspect) .setNodeInspectGesture(Ui::Pointer::Finger, {}); … /* Disable it again and revert to a safe gesture when not used anymore */ debugLayer .clearFlags(Ui::DebugLayerFlag::NodeInspect) .setNodeInspectGesture(Ui::Pointer::MouseRight, Ui::Modifier::Ctrl);
Besides visual inspection using a pointer, inspectNode() allows to inspect a node programmatically.
Finally, while the inspected node details are by default printed to Debug, a console might not be always accessible. In that case you can direct the message to a callback using setNodeInspectCallback(), and populate for example a Label directly in the UI with it instead. The callback also gets called with an empty string when the highlight is removed, which can be used to hide the label again. For example:
Ui::Label details{…}; … debugLayer.setNodeInspectCallback([&details](Containers::StringView message) { details .setText(message) .setHidden(!message); });
Limitations
Currently, it's only possible to visually inspect nodes that are visible and are neither NodeFlag::
Additionally, if a top-level node covers other nodes but is otherwise invisible and doesn't react to events in any way, with DebugLayerFlag::
Highlighting nodes
Besides inspecting a single individual node to see details about what's all attached to it, it's possible to programmatically highlight nodes in the UI by passing their handle to highlightNode(). This is useful for example in case you have a node in the code and want to see where it appears in the UI. In the following snippet, the button from above would get highlighted like this, resulting in it having a cyan overlay. The function returns false in case given node handle is unknown to the debug layer, which you can use for various sanity checks:
CORRADE_INTERNAL_ASSERT(debugLayer.highlightNode(button));

The highlights are additive, meaning additional calls to highlightNode() will highlight more nodes. The set of currently highlighted node IDs can be queried with currentHighlightedNodes() and all highlights cleared with clearHighlightedNodes(). To better distinguish multiple highlighted nodes from each other, a color map can be supplied with setNodeHighlightColorMap(), where different colors get used based on node ID. The DebugTools::
debugLayer.setNodeHighlightColorMap(DebugTools::ColorMap::turbo());
The highlightNodes() overloads then allow highlighting nodes based on various conditions either on the nodes themselves or on data, layouts and animations attached to those. Each of these overloads accepts a function which if returns true, causes given node (or node given data / layout / animation is attached to) to be highlighted. For example, highlighting all top-level nodes in the UI to discover unnecessary extra draw calls:
debugLayer.highlightNodes( [](const Ui::AbstractUserInterface& ui, Ui::NodeHandle node) { return ui.isNodeTopLevel(node); });
Or highlighting all nodes that have base and text data with custom colors, to discover pieces of the UI that might have their styling hardcoded. The highlights will be combined from these two calls:
debugLayer.highlightNodes(ui.baseLayer(), [](const Ui::BaseLayer& layer, Ui::LayerDataHandle data) { return layer.color(data) != Color4{1.0f}; }); debugLayer.highlightNodes(ui.textLayer(), [](const Ui::TextLayer& layer, Ui::LayerDataHandle data) { return layer.color(data) != Color4{1.0f}; });
Node highlight is orthogonal to node inspection, so if you have DebugLayerFlag::
Making the DebugLayer opt-in
As mentioned above, having the layer always present may have unintended performance implications, and a node highlight can be confusing if triggered accidentally by an unsuspecting user. One possibility is to create it only with a certain startup option, such as is the case with --debug in magnum-ui-gallery.
Another way is to create it with no DebugLayerFlag present, and enable them temporarily only if some debug mode is activated, similarly to what was shown for touch input above. Such setup will however still make it track all enabled DebugLayerSource bits all the time. To avoid this, it's also possible to defer the layer creation and setup to the point when it's actually needed, and then destroy it again after. Note that, as certain options involve iterating the whole node tree, with very complex UIs such on-the-fly setup might cause stalls.
DebugLayer integration for custom layers, layouters and animators
To make a custom layer provide detailed info for DebugLayerSource::
class ColorLayer: public Ui::AbstractLayer { public: struct DebugIntegration; Color3 color(Ui::LayerDataHandle handle) const; … }; struct ColorLayer::DebugIntegration { void print(Debug& debug, const ColorLayer& layer, Containers::StringView layerName, Ui::LayerDataHandle data) { /* Convert to an 8-bit color for brevity */ Color3ub color8 = Math::pack<Color3ub>(layer.color(data)); debug << " Data" << Debug::packed << data << "from layer" << Debug::packed << layer.handle() << Debug::color(Debug::Color::Yellow) << layerName << Debug::resetColor << "with color"; /* If colors aren't disabled, print also a color swatch besides the actual value. All other coloring will be automatically ignored if DisableColors is set. */ if(!(debug.flags() & Debug::Flag::DisableColors)) debug << Debug::color << color8; debug << color8 << Debug::newline; } };
Assuming the concrete layer type is passed to setLayerName(), nothing else needs to be done and the integration gets used automatically. If there's multiple data attached to the same node, the print() gets called for each of them.
ColorLayer& colorLayer = ui.setLayerInstance(…); … debugLayer.setLayerName(colorLayer, "Shiny");
Node {0xc, 0x1} Data {0x4, 0x3} from layer {0x4, 0x1} Shiny with color ▓▓ #2f83cc Data {0x7, 0x1} from layer {0x4, 0x1} Shiny with color ██ #3bd267
If the integration needs additional state, a constructor can be implemented, and the instance then passed to DebugLayer::
class ColorLayer::DebugIntegration { public: /*implicit*/ DebugIntegration(DebugFlags flags = {}): _flags{flags} {} void print(Debug& debug, const ColorLayer& layer, Containers::StringView layerName, Ui::LayerDataHandle data); private: DebugFlags _flags; };
If additional details can be provided even without supplying additional state, it's recommended to have the class default-constructible as well so at least some functionality can be used even if users aren't aware of the extra options. Additionally, in the above code the constructor isn't made explicit, which allows the debug integration arguments to be passed directly to setLayerName():
/* Default integration setup */ debugLayer.setLayerName(colorLayer, "Shiny"); /* Passing extra arguments */ debugLayer.setLayerName(colorLayer, "Shiny", ColorLayer::DebugFlag::PrintColor|ColorLayer::DebugFlag::ColorSwatch);
For layouters and DebugLayerSource::
Overriding the integration in subclasses
Any layer, layouter or animator derived from a base that already has an integration, such as from AbstractVisualLayer or EventLayer, will implicitly inherit the base implementation. If the subclass wants to provide its own output, it can either provide a custom type and hide the original, or derive from it by calling the base print() in its own implementation. Here the ColorLayer from above is made to derive from AbstractVisualLayer now instead, and its DebugIntegration derives from AbstractVisualLayer::
class ColorLayer: public Ui::AbstractVisualLayer { public: struct DebugIntegration; … }; struct ColorLayer::DebugIntegration: Ui::AbstractVisualLayer::DebugIntegration { void print(Debug& debug, const ColorLayer& layer, Containers::StringView layerName, Ui::LayerDataHandle data) { Ui::AbstractVisualLayer::DebugIntegration::print(debug, layer, layerName, data); /* Print just what isn't already provided by AbstractVisualLayer */ Color3ub color8 = Math::pack<Color3ub>(layer.color(data)); debug << " Color:"; if(!(debug.flags() & Debug::Flag::DisableColors)) debug << Debug::color << color8; debug << color8 << Debug::newline; } };
Base classes
- class AbstractLayer new in Git master
- Base for data layers.
Derived classes
- class DebugLayerGL new in Git master
- OpenGL implementation of the debug layer.
Constructors, destructors, conversion operators
- DebugLayer(LayerHandle handle, DebugLayerSources sources, DebugLayerFlags flags) explicit
- Constructor.
- DebugLayer(const DebugLayer&) deleted
- Copying is not allowed.
- DebugLayer(DebugLayer&&) noexcept
- Move constructor.
Public functions
- auto operator=(const DebugLayer&) -> DebugLayer& deleted
- Copying is not allowed.
- auto operator=(DebugLayer&&) -> DebugLayer& noexcept
- Move assignment.
- auto sources() const -> DebugLayerSources
- Tracked data sources.
- auto flags() const -> DebugLayerFlags
- Behavior flags.
- auto setFlags(DebugLayerFlags flags) -> DebugLayer&
- Set behavior flags.
- auto addFlags(DebugLayerFlags flags) -> DebugLayer&
- Add behavior flags.
- auto clearFlags(DebugLayerFlags flags) -> DebugLayer&
- Clear flags.
-
auto nodeName(NodeHandle handle) const -> Containers::
StringView - Node name.
-
auto setNodeName(NodeHandle handle,
Containers::
StringView name) -> DebugLayer& - Set node name.
-
auto layerName(LayerHandle handle) const -> Containers::
StringView - Layer name.
-
auto setLayerName(const AbstractLayer& layer,
Containers::
StringView name) -> DebugLayer& - Set layer name.
-
template<class T>auto setLayerName(const T& layer, const Containers::
StringView& name) -> DebugLayer& - Set name for a layer with AbstractLayer::
DebugIntegration implemented. -
template<class T>auto setLayerName(const T& layer, const Containers::
StringView& name, const typename T::DebugIntegration& integration) -> DebugLayer& - Set name for a layer with AbstractLayer::
DebugIntegration implemented. -
template<class T>auto setLayerName(const T& layer, const Containers::
StringView& name, typename T::DebugIntegration&& integration) -> DebugLayer& -
auto layouterName(LayouterHandle handle) const -> Containers::
StringView - Layouter name.
-
auto setLayouterName(const AbstractLayouter& layouter,
Containers::
StringView name) -> DebugLayer& - Set layouter name.
-
template<class T>auto setLayouterName(const T& layouter, const Containers::
StringView& name) -> DebugLayer& - Set name for a layouter with AbstractLayouter::
DebugIntegration implemented. -
template<class T>auto setLayouterName(const T& layouter, const Containers::
StringView& name, const typename T::DebugIntegration& integration) -> DebugLayer& - Set name for a layouter with AbstractLayouter::
DebugIntegration implemented. -
template<class T>auto setLayouterName(const T& layouter, const Containers::
StringView& name, typename T::DebugIntegration&& integration) -> DebugLayer& -
auto animatorName(AnimatorHandle handle) const -> Containers::
StringView - Animator name.
-
auto setAnimatorName(const AbstractAnimator& animator,
Containers::
StringView name) -> DebugLayer& - Set animator name.
-
template<class T>auto setAnimatorName(const T& animator, const Containers::
StringView& name) -> DebugLayer& - Set name for an animator with AbstractAnimator::
DebugIntegration implemented. -
template<class T>auto setAnimatorName(const T& animator, const Containers::
StringView& name, const typename T::DebugIntegration& integration) -> DebugLayer& - Set name for an animator with AbstractAnimator::
DebugIntegration implemented. -
template<class T>auto setAnimatorName(const T& animator, const Containers::
StringView& name, typename T::DebugIntegration&& integration) -> DebugLayer& - auto nodeInspectColor() const -> Color4
- Node inspect color.
- auto setNodeInspectColor(const Color4& color) -> DebugLayer&
- Set node inspect color.
-
auto nodeInspectGesture() const -> Containers::
Pair<Pointers, Modifiers> - Node inspect gesture.
- auto setNodeInspectGesture(Pointers pointers, Modifiers modifiers) -> DebugLayer&
- Set node inspect gesture.
- auto hasNodeInspectCallback() const -> bool
- Whether a node inspect callback is set.
-
auto setNodeInspectCallback(Containers::
Function<void(Containers:: StringView message)>&& callback) -> DebugLayer& - Set node inspect callback.
- auto currentInspectedNode() const -> NodeHandle
- Node inspected by last pointer press.
- auto inspectNode(NodeHandle node) -> bool
- Inspect a node.
-
auto nodeHighlightColorMap() const -> Containers::
ArrayView<const Vector3ub> - Node highlight color map.
- auto nodeHighlightColorMapAlpha() const -> Float
- Node highlight color map alpha.
-
auto setNodeHighlightColorMap(Containers::
ArrayView<const Vector3ub> colors, Float alpha = 0.25f) -> DebugLayer& - Set node highlight color map.
-
auto currentHighlightedNodes() const -> Containers::
BitArrayView - Currently highlighted nodes.
- auto clearHighlightedNodes() -> DebugLayer&
- Clear all highlighted nodes.
- auto highlightNode(NodeHandle node) -> bool
- Highlight a node.
- auto highlightNodes(bool(*)(const AbstractUserInterface&ui, NodeHandle node) condition) -> bool
- Highlight nodes based on a condition.
-
template<class T, class U>auto highlightNodes(const T& layer, bool(*)(const U&layer, LayerDataHandle data) condition) -> bool
- Highlight nodes based on a condition queried on data attachments.
-
template<class T, class U>auto highlightNodes(const T& layouter, bool(*)(const U&layouter, LayouterDataHandle data) condition) -> bool
- Highlight nodes based on a condition queried on layout assignments.
-
template<class T, class U>auto highlightNodes(const T& animator, bool(*)(const U&animator, AnimatorDataHandle data) condition) -> bool
- Highlight nodes based on a condition queried on animation attachments.
Function documentation
Magnum:: Ui:: DebugLayer:: DebugLayer(LayerHandle handle,
DebugLayerSources sources,
DebugLayerFlags flags) explicit
Constructor.
| Parameters | |
|---|---|
| handle | Layer handle returned from AbstractUserInterface:: |
| sources | Data sources to track |
| flags | Behavior flags |
See particular DebugLayerFlag values for information about which DebugLayerSource is expected to be enabled for a particular feature. While sources have to specified upfront, the flags can be subsequently modified using setFlags(), addFlags() and clearFlags().
Note that you can also construct the DebugLayerGL subclass instead to have the layer with visual feedback.
Magnum:: Ui:: DebugLayer:: DebugLayer(DebugLayer&&) noexcept
Move constructor.
Performs a destructive move, i.e. the original object isn't usable afterwards anymore.
DebugLayer& Magnum:: Ui:: DebugLayer:: setFlags(DebugLayerFlags flags)
Set behavior flags.
| Returns | Reference to self (for method chaining) |
|---|
See particular DebugLayerFlag values for information about which DebugLayerSource is expected to be enabled for a particular feature.
If a node was inspect and DebugLayerFlag::
DebugLayer& Magnum:: Ui:: DebugLayer:: addFlags(DebugLayerFlags flags)
Add behavior flags.
| Returns | Reference to self (for method chaining) |
|---|
Calls setFlags() with the existing flags ORed with flags. Useful for preserving previously set flags.
DebugLayer& Magnum:: Ui:: DebugLayer:: clearFlags(DebugLayerFlags flags)
Clear flags.
| Returns | Reference to self (for method chaining) |
|---|
Calls setFlags() with the existing flags ANDed with the inverse of flags. Useful for removing a subset of previously set flags.
Containers:: StringView Magnum:: Ui:: DebugLayer:: nodeName(NodeHandle handle) const
Node name.
Expects that the debug layer has been already passed to AbstractUserInterface::handle isn't NodeHandle::handle doesn't have to be valid however. If DebugLayerSource::handle isn't known, returns an empty string.
If not empty, the returned string is always Containers::
DebugLayer& Magnum:: Ui:: DebugLayer:: setNodeName(NodeHandle handle,
Containers:: StringView name)
Set node name.
| Returns | Reference to self (for method chaining) |
|---|
Expects that the debug layer has been already passed to AbstractUserInterface::handle isn't NodeHandle::handle doesn't have to be valid however. If DebugLayerSource::name will be used to annotate given handle, otherwise the function does nothing.
If name is Containers::
Containers:: StringView Magnum:: Ui:: DebugLayer:: layerName(LayerHandle handle) const
Layer name.
Expects that the debug layer has been already passed to AbstractUserInterface::handle isn't LayerHandle::handle doesn't have to be valid however. If DebugLayerSource::handle isn't known, returns an empty string. For handle() returns "Debug" if a different name wasn't set.
If not empty, the returned string is always Containers::
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayerName(const AbstractLayer& layer,
Containers:: StringView name)
Set layer name.
| Returns | Reference to self (for method chaining) |
|---|
Expects that the debug layer has been already passed to AbstractUserInterface::layer is part of the same user interface. If DebugLayerSource::name will be used to annotate attachments from given layer, otherwise the function does nothing.
If name is Containers::
If a concrete layer type gets passed instead of just AbstractLayer, the setLayerName(const T&, const Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayerName(const T& layer,
const Containers:: StringView& name)
Set name for a layer with AbstractLayer::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setLayerName(const AbstractLayer&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayerName(const T& layer,
const Containers:: StringView& name,
const typename T::DebugIntegration& integration)
Set name for a layer with AbstractLayer::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setLayerName(const AbstractLayer&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayerName(const T& layer,
const Containers:: StringView& name,
typename T::DebugIntegration&& integration)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Containers:: StringView Magnum:: Ui:: DebugLayer:: layouterName(LayouterHandle handle) const
Layouter name.
Expects that the debug layer has been already passed to AbstractUserInterface::handle isn't LayouterHandle::handle doesn't have to be valid however. If DebugLayerSource::handle isn't known, returns an empty string.
If not empty, the returned string is always Containers::
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayouterName(const AbstractLayouter& layouter,
Containers:: StringView name)
Set layouter name.
| Returns | Reference to self (for method chaining) |
|---|
Expects that the debug layer has been already passed to AbstractUserInterface::layouter is part of the same user interface. If DebugLayerSource::name will be used to annotate assignments from given layouter, otherwise the function does nothing.
If name is Containers::
If a concrete layouter type gets passed instead of just AbstractLayouter, the setLayouterName(const T&, const Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayouterName(const T& layouter,
const Containers:: StringView& name)
Set name for a layouter with AbstractLayouter::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setLayouterName(const AbstractLayouter&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayouterName(const T& layouter,
const Containers:: StringView& name,
const typename T::DebugIntegration& integration)
Set name for a layouter with AbstractLayouter::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setLayouterName(const AbstractLayouter&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setLayouterName(const T& layouter,
const Containers:: StringView& name,
typename T::DebugIntegration&& integration)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Containers:: StringView Magnum:: Ui:: DebugLayer:: animatorName(AnimatorHandle handle) const
Animator name.
Expects that the debug layer has been already passed to AbstractUserInterface::handle isn't AnimatorHandle::handle doesn't have to be valid however. If DebugLayerSource::handle isn't known, returns an empty string.
If not empty, the returned string is always Containers::
DebugLayer& Magnum:: Ui:: DebugLayer:: setAnimatorName(const AbstractAnimator& animator,
Containers:: StringView name)
Set animator name.
| Returns | Reference to self (for method chaining) |
|---|
Expects that the debug layer has been already passed to AbstractUserInterface::animator is part of the same user interface. If DebugLayerSource::name will be used to annotate attachments from given animator, otherwise the function does nothing.
If name is Containers::
If a concrete animator type gets passed instead of just AbstractAnimator, the setAnimatorName(const T&, const Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setAnimatorName(const T& animator,
const Containers:: StringView& name)
Set name for an animator with AbstractAnimator::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setAnimatorName(const AbstractAnimator&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setAnimatorName(const T& animator,
const Containers:: StringView& name,
const typename T::DebugIntegration& integration)
Set name for an animator with AbstractAnimator::
| Returns | Reference to self (for method chaining) |
|---|
In addition to setAnimatorName(const AbstractAnimator&, Containers::
template<class T>
DebugLayer& Magnum:: Ui:: DebugLayer:: setAnimatorName(const T& animator,
const Containers:: StringView& name,
typename T::DebugIntegration&& integration)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
DebugLayer& Magnum:: Ui:: DebugLayer:: setNodeInspectColor(const Color4& color)
Set node inspect color.
| Returns | Reference to self (for method chaining) |
|---|
Used only if DebugLayerFlag::0xff00ffff_rgbaf*0.5f.
If the layer is instantiated as DebugLayerGL, calling this function causes LayerState::
DebugLayer& Magnum:: Ui:: DebugLayer:: setNodeInspectGesture(Pointers pointers,
Modifiers modifiers)
Set node inspect gesture.
| Returns | Reference to self (for method chaining) |
|---|
Used only if DebugLayerFlag::pointers with modifiers being exactly modifiers. Pressing on a different node moves the highlight to the other node, pressing on a node that's currently being inspected removes the highlight. Expects that pointers are non-empty. Default is a combination of Pointer::
DebugLayer& Magnum:: Ui:: DebugLayer:: setNodeInspectCallback(Containers:: Function<void(Containers:: StringView message)>&& callback)
Set node inspect callback.
| Returns | Reference to self (for method chaining) |
|---|
Used only if DebugLayerFlag::callback receives a UTF-8 message with details when a highlight happens on a pointer press, and an empty string if a highlight is removed again. If not empty, the message is guaranteed to be Containers::
If the callback is not set or if set to nullptr, details about the inspected node are printed to Debug instead.
NodeHandle Magnum:: Ui:: DebugLayer:: currentInspectedNode() const
Node inspected by last pointer press.
Expects that DebugLayerFlag::
The returned handle may be invalid if the node or any of its parents were removed and AbstractUserInterface::
bool Magnum:: Ui:: DebugLayer:: inspectNode(NodeHandle node)
Inspect a node.
Expects that DebugLayerFlag::
If node is a known handle, the function performs similarly to the node inspect gesture using a pointer press — currentInspectedNode() is set to node, details about the node are printed to Debug or passed to a callback if set, the node is visually highlighted if this is a DebugLayerGL instance, and the function returns true.
If node is NodeHandle::true if node is NodeHandle::false if the handle is unknown.
Note that, compared to the node inspect gesture, where the node details are always extracted from an up-to-date UI state, this function only operates with the state known at the last call to AbstractUserInterface::
See highlightNode() and highlightNodes() for a way to just highlight particular nodes in the UI without inspecting them.
If the layer is instantiated as DebugLayerGL and node is different from the previously inspected node, calling this function causes LayerState::
DebugLayer& Magnum:: Ui:: DebugLayer:: setNodeHighlightColorMap(Containers:: ArrayView<const Vector3ub> colors,
Float alpha = 0.25f)
Set node highlight color map.
| Returns | Reference to self (for method chaining) |
|---|
Used only if DebugLayerSource::colors are expected to have at least one element and the caller has to ensure the memory stays in scope for the whole layer lifetime or until setNodeHighlightColorMap() is called with a different color map.
The first element from colors is used to highlight a node with ID 0, the last element for a node with ID right below AbstractUserInterface::colors are made four-component and premultiplied with alpha when applied. Default is a map with a single 0x00ffff_rgb color, i.e. the same color used for all nodes.
If the layer is instantiated as DebugLayerGL, calling this function causes LayerState::
Containers:: BitArrayView Magnum:: Ui:: DebugLayer:: currentHighlightedNodes() const
Currently highlighted nodes.
Expects that DebugLayerSource::
DebugLayer& Magnum:: Ui:: DebugLayer:: clearHighlightedNodes()
Clear all highlighted nodes.
| Returns | Reference to self (for method chaining) |
|---|
Expects that DebugLayerSource::
bool Magnum:: Ui:: DebugLayer:: highlightNode(NodeHandle node)
Highlight a node.
Expects that DebugLayerSource::node isn't NodeHandle::
If node is a known handle, the node is visually highlighted if this is a DebugLayerGL instance, and the function returns true.
If node is not a known handle (for example an invalid handle of a now-removed node, or a handle of a newly created node but AbstractUserInterface::false.
The highlights are additive, meaning calling this function multiple times will make more nodes highlighted. Use clearHighlightedNodes() to clear all highlights. You can use the highlightNodes() variants to highlight nodes based on various conditions queried on the nodes themselves or on data, layouts and animations attached to those. See also inspectNode() for highlighting a node and printing its details.
If the layer is instantiated as DebugLayerGL and node wasn't already highlighted before, calling this function causes LayerState::
bool Magnum:: Ui:: DebugLayer:: highlightNodes(bool(*)(const AbstractUserInterface&ui, NodeHandle node) condition)
Highlight nodes based on a condition.
Expects that DebugLayerSource::condition isn't nullptr.
The function goes through all known and valid nodes and calls condition with the user interface instance and a NodeHandle. If condition returns true, given node is highlighted.
The passed handles are all guaranteed to be valid, however note that not yet known nodes (such as nodes that were newly created since the last call to AbstractUserInterface::false if the debug layer doesn't know any valid nodes (such as when calling this function before any AbstractUserInterface::condition was never called. The function returns true if there was at least one node to call condition on, regardless of whether any node was actually highlighted by it.
If the layer is instantiated as DebugLayerGL and nodes for which condition returned true weren't already highlighted, calling this function causes LayerState::
template<class T, class U>
bool Magnum:: Ui:: DebugLayer:: highlightNodes(const T& layer,
bool(*)(const U&layer, LayerDataHandle data) condition)
Highlight nodes based on a condition queried on data attachments.
| Returns | Reference to self (for method chaining) |
|---|
Expects that DebugLayerSource::layer is part of the same user interface and is not the debug layer itself and that condition isn't nullptr.
If layer is known to the debug layer, the function goes through all its data that are attached to known and valid nodes and calls condition with the layer instance and a LayerDataHandle. If condition returns true, the node the data is attached to is highlighted.
The passed handles are all guaranteed to be valid in given layer, however note that data attached to not yet known nodes (such as nodes that were newly created since the last call to AbstractUserInterface::false if the debug layer doesn't know layer or none of its data are attached to known and valid nodes (such as when calling this function before any AbstractUserInterface::condition was never called. The function returns true if there was at least one data to call condition on, regardless of whether any node was actually highlighted by it.
If the layer is instantiated as DebugLayerGL and nodes for which condition returned true weren't already highlighted, calling this function causes LayerState::
template<class T, class U>
bool Magnum:: Ui:: DebugLayer:: highlightNodes(const T& layouter,
bool(*)(const U&layouter, LayouterDataHandle data) condition)
Highlight nodes based on a condition queried on layout assignments.
| Returns | Reference to self (for method chaining) |
|---|
Expects that DebugLayerSource::layouter is part of the same user interface and that condition isn't nullptr.
If layouter is known to the debug layer, the function goes through all its layouts that are assigned to known and valid nodes and calls condition with the layouter instance and a LayouterDataHandle. If condition returns true, the node the layout is assigned to is highlighted.
The passed handles are all guaranteed to be valid in given layouter, however note that layouts assigned to not yet known nodes (such as nodes that were newly created since the last call to AbstractUserInterface::false if the debug layer doesn't know layouter or none of its layouts are assigned to known and valid nodes (such as when calling this function before any AbstractUserInterface::condition was never called. The function returns true if there was at least one layout to call condition on, regardless of whether any node was actually highlighted by it.
If the layer is instantiated as DebugLayerGL and nodes for which condition returned true weren't already highlighted, calling this function causes LayerState::
template<class T, class U>
bool Magnum:: Ui:: DebugLayer:: highlightNodes(const T& animator,
bool(*)(const U&animator, AnimatorDataHandle data) condition)
Highlight nodes based on a condition queried on animation attachments.
| Returns | Reference to self (for method chaining) |
|---|
Expects that DebugLayerSource::animator is part of the same user interface and supports AnimatorFeature::condition isn't nullptr.
If animator is known to the debug layer, the function goes through all its animations that are attached to known and valid nodes and calls condition with the animator instance and an AnimatorDataHandle. If condition returns true, the node the animation is attached to is highlighted.
The passed handles are all guaranteed to be valid in given animator, however note that animations attached to not yet known nodes (such as nodes that were newly created since the last call to AbstractUserInterface::false if the debug layer doesn't know animator or none of its data are attached to known and valid nodes (such as when calling this function before any AbstractUserInterface::condition was never called. The function returns true if there was at least one animation to call condition on, regardless of whether any node was actually highlighted by it.
If the layer is instantiated as DebugLayerGL and nodes for which condition returned true weren't already highlighted, calling this function causes LayerState::