MeshLib
 
Loading...
Searching...
No Matches
MRUITestEngine.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRViewer/exports.h"
4
5#include <cstdint>
6#include <limits>
7#include <map>
8#include <optional>
9#include <string_view>
10#include <string>
11#include <variant>
12#include <vector>
13
14// This is a low-level header for implementing GUIs that can be interacted with programmatically.
15// Most likely you don't need to touch this, just use widgets from `MRUIStyle.h`.
16
18{
19
20namespace detail
21{
22 template <typename T>
24 {
25 T value{};
26 T min{};
27 T max{};
28 };
29 template <>
30 struct BoundedValue<std::string>
31 {
32 std::string value;
33
34 std::optional<std::vector<std::string>> allowedValues;
35 };
36
37 template <typename T>
38 [[nodiscard]] MRVIEWER_API std::optional<T> createValueLow( std::string_view name, std::optional<BoundedValue<T>> value );
39
40 extern template MRVIEWER_API std::optional<std::int64_t> createValueLow( std::string_view name, std::optional<BoundedValue<std::int64_t>> value );
41 extern template MRVIEWER_API std::optional<std::uint64_t> createValueLow( std::string_view name, std::optional<BoundedValue<std::uint64_t>> value );
42 extern template MRVIEWER_API std::optional<double> createValueLow( std::string_view name, std::optional<BoundedValue<double>> value );
43 extern template MRVIEWER_API std::optional<std::string> createValueLow( std::string_view name, std::optional<BoundedValue<std::string>> value );
44
45 template <typename T>
46 using UnderlyingValueType = std::conditional_t<std::is_floating_point_v<T>, double, std::conditional_t<std::is_signed_v<T>, std::int64_t, std::uint64_t>>;
47}
48
49// Call this every frame when drawing a button you want to track (regardless of whether it returns true of false).
50// If this returns true, simulate a button click.
51[[nodiscard]] MRVIEWER_API bool createButton( std::string_view name );
52
53template <typename T>
54concept AllowedValueType = std::is_arithmetic_v<T> || std::is_same_v<T, std::string>;
55
56// Create a "value" (slider/drag/...).
57// `T` must be a scalar; vector support must be implemented manually.
58// Pass `min >= max` to disable the range checks.
59// If this returns true, use the new value in place of the current one.
60template <AllowedValueType T>
61requires std::is_arithmetic_v<T>
62[[nodiscard]] std::optional<T> createValue( std::string_view name, T value, T min, T max )
63{
64 if ( !( min < max ) )
65 {
66 min = std::numeric_limits<T>::lowest();
67 max = std::numeric_limits<T>::max();
68 }
69
71 static_assert(sizeof(T) <= sizeof(U), "The used type is too large.");
72
73 auto ret = detail::createValueLow<U>( name, detail::BoundedValue<U>{ .value = U( value ), .min = U( min ), .max = U( max ) } );
74 return ret ? std::optional<T>( T( *ret ) ) : std::nullopt;
75}
76// This overload is for strings.
77[[nodiscard]] MRVIEWER_API std::optional<std::string> createValue( std::string_view name, std::string value, std::optional<std::vector<std::string>> allowedValues = std::nullopt );
78
79// Usually you don't need this function.
80// This is for widgets that require you to specify the value override before drawing it, such as `ImGui::CollapsingHeader()`.
81// For those, call this version first to read the value override, then draw the widget, then call the normal `CreateValue()` with the same name
82// and with the new value, and discard its return value.
83template <AllowedValueType T>
84[[nodiscard]] std::optional<T> createValueTentative( std::string_view name )
85{
86 auto ret = detail::createValueLow<detail::UnderlyingValueType<T>>( name, std::nullopt );
87 return ret ? std::optional<T>( T( *ret ) ) : std::nullopt;
88}
89
90// Use those to group buttons into named groups.
91MRVIEWER_API void pushTree( std::string_view name );
92MRVIEWER_API void popTree();
93
94struct Entry;
95
97{
98 // Set this to true to simulate a button click.
99 mutable bool simulateClick = false;
100};
101
102// For sliders, drags, etc.
104{
105 template <typename T>
106 struct Value
107 {
108 // The current value.
109 T value = 0;
110
111 // Min/max bounds, INCLUSIVE. If none, those are set to the min/max values representable in this type.
112 T min = 0;
113 T max = 0;
114
115 // Set to override the value.
116 mutable std::optional<T> simulatedValue;
117
118 Value() {} // Make `std::variant` below happy.
119 };
120 template <std::same_as<std::string> T> // GCC chokes on full specializations at class scope, hence this.
121 struct Value<T>
122 {
123 // The current value.
124 std::string value;
125
126 std::optional<std::vector<std::string>> allowedValues;
127
128 // Set to override the value.
129 mutable std::optional<std::string> simulatedValue;
130
131 Value() {} // Make `std::variant` below happy.
132 };
133 using ValueVar = std::variant<Value<std::int64_t>, Value<std::uint64_t>, Value<double>, Value<std::string>>;
135};
136
138{
139 // Using `std::map` over `std::unordered_map` to be able to search by `std::string_view` keys directly.
140 std::map<std::string, Entry, std::less<>> elems;
141};
142
143struct Entry
144{
145 std::variant<ButtonEntry, ValueEntry, GroupEntry> value;
146
147 // Mostly for internal use.
148 // If this is false, the entry will be removed on the next frame.
149 bool visitedOnThisFrame = false;
150};
151
152// Returns the current entry tree.
153[[nodiscard]] MRVIEWER_API const GroupEntry& getRootEntry();
154
155}
Definition MRUITestEngine.h:54
MRVIEWER_API std::optional< T > createValueLow(std::string_view name, std::optional< BoundedValue< T > > value)
std::conditional_t< std::is_floating_point_v< T >, double, std::conditional_t< std::is_signed_v< T >, std::int64_t, std::uint64_t > > UnderlyingValueType
Definition MRUITestEngine.h:46
Definition MRUITestEngine.h:18
std::optional< T > createValue(std::string_view name, T value, T min, T max)
Definition MRUITestEngine.h:62
MRVIEWER_API bool createButton(std::string_view name)
std::optional< T > createValueTentative(std::string_view name)
Definition MRUITestEngine.h:84
MRVIEWER_API const GroupEntry & getRootEntry()
MRVIEWER_API void popTree()
MRVIEWER_API void pushTree(std::string_view name)
Definition MRUITestEngine.h:97
bool simulateClick
Definition MRUITestEngine.h:99
Definition MRUITestEngine.h:144
std::variant< ButtonEntry, ValueEntry, GroupEntry > value
Definition MRUITestEngine.h:145
bool visitedOnThisFrame
Definition MRUITestEngine.h:149
Definition MRUITestEngine.h:138
std::map< std::string, Entry, std::less<> > elems
Definition MRUITestEngine.h:140
Value()
Definition MRUITestEngine.h:131
std::optional< std::string > simulatedValue
Definition MRUITestEngine.h:129
std::string value
Definition MRUITestEngine.h:124
std::optional< std::vector< std::string > > allowedValues
Definition MRUITestEngine.h:126
Definition MRUITestEngine.h:107
Value()
Definition MRUITestEngine.h:118
T max
Definition MRUITestEngine.h:113
T value
Definition MRUITestEngine.h:109
T min
Definition MRUITestEngine.h:112
std::optional< T > simulatedValue
Definition MRUITestEngine.h:116
Definition MRUITestEngine.h:104
std::variant< Value< std::int64_t >, Value< std::uint64_t >, Value< double >, Value< std::string > > ValueVar
Definition MRUITestEngine.h:133
ValueVar value
Definition MRUITestEngine.h:134
Definition MRUITestEngine.h:24
T min
Definition MRUITestEngine.h:26
T max
Definition MRUITestEngine.h:27
T value
Definition MRUITestEngine.h:25