Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
ParameterSetEditor.cpp
1 #include <Gui/ParameterSetEditor/ParameterSetEditor.hpp>
2 
3 #include <Gui/Widgets/ControlPanel.hpp>
4 
5 // include the Material Definition
6 #include <Engine/Data/Material.hpp>
7 
8 #include <QString>
9 #include <QWidget>
10 
11 #include <limits>
12 #include <memory>
13 
14 using json = nlohmann::json;
15 
16 namespace Ra {
17 using namespace Engine;
18 namespace Gui {
19 
20 namespace internal {
21 class RenderParameterUiBuilder
22 {
23  public:
25 
26  RenderParameterUiBuilder( ParameterSetEditor* pse, const json& constraints ) :
27  m_pse { pse }, m_constraints { constraints } {}
28 
29  void operator()( const std::string& name, bool& p, Data::RenderParameters&& /* params */ ) {
30  auto onBoolParameterChanged = [pse = this->m_pse, &p, nm = name]( bool val ) {
31  p = val;
32  emit pse->parameterModified( nm );
33  };
34  if ( m_constraints.contains( name ) ) {
35  if ( m_constraints[name]["editable"] ) {
36  const auto& m = m_constraints[name];
37  std::string description = m.contains( "description" ) ? m["description"] : "";
38  std::string nm = m.contains( "name" ) ? std::string { m["name"] } : name;
39  m_pse->addOption( nm, onBoolParameterChanged, p, description );
40  }
41  }
42  else if ( m_pse->m_showUnspecified ) {
43  m_pse->addOption( name, onBoolParameterChanged, p );
44  }
45  }
46 
47  template <typename TParam, std::enable_if_t<std::is_arithmetic<TParam>::value, bool> = true>
48  void operator()( const std::string& name, TParam& p, Data::RenderParameters&& params ) {
49  if ( params.getEnumConverter<TParam>( name ) ) {
50  m_pse->addEnumParameterWidget( name, p, params, m_constraints );
51  }
52  else {
53  // case number
54  m_pse->addNumberParameterWidget( name, p, params, m_constraints );
55  }
56  }
57 
58  template <typename TParam,
59  typename TAllocator,
60  std::enable_if_t<std::is_arithmetic<TParam>::value, bool> = true>
61  void operator()( const std::string& name,
62  std::vector<TParam, TAllocator>& p,
63  Data::RenderParameters&& params ) {
64  m_pse->addVectorParameterWidget( name, p, params, m_constraints );
65  }
66 
67  void operator()( const std::string& name,
69  Data::RenderParameters&& params ) {
70  auto onColorParameterChanged =
71  [pse = this->m_pse, &params, nm = name]( const Ra::Core::Utils::Color& val ) {
72  params.addParameter( nm, val );
73  emit pse->parameterModified( nm );
74  };
75  if ( m_constraints.contains( name ) ) {
76  const auto& m = m_constraints[name];
77  std::string description = m.contains( "description" ) ? m["description"] : "";
78  std::string nm = m.contains( "name" ) ? std::string { m["name"] } : name;
79  m_pse->addColorInput( nm, onColorParameterChanged, p, m["maxItems"] == 4, description );
80  }
81  else if ( m_pse->m_showUnspecified ) {
82  m_pse->addColorInput( name, onColorParameterChanged, p );
83  }
84  }
85 
86  template <template <typename, int...> typename M, typename T, int... dim>
87  void operator()( const std::string& name, M<T, dim...>& p, Data::RenderParameters&& params ) {
88  m_pse->addMatrixParameterWidget( name, p, params, m_constraints );
89  }
90 
91  void operator()( const std::string& /*name*/,
93  Data::RenderParameters&& /*params*/ ) {
94  // textures are not yet editable
95  }
96 
97  template <typename T>
98  void operator()( const std::string& /*name*/,
99  std::reference_wrapper<T>& /*p*/,
100  Data::RenderParameters&& /*params*/ ) {
101  // wrapped reference (e.g. embedded render parameter) edition not yet available
102  }
103 
104  private:
105  ParameterSetEditor* m_pse { nullptr };
106  const json& m_constraints;
107 };
108 } // namespace internal
109 
110 ParameterSetEditor::ParameterSetEditor( const std::string& name, QWidget* parent ) :
111  ControlPanel( name, !name.empty(), parent ) {}
112 
113 template <typename T>
114 void ParameterSetEditor::addEnumParameterWidget( const std::string& key,
115  T& initial,
117  const json& metadata ) {
118  auto m = metadata[key];
119 
120  std::string description = m.contains( "description" ) ? m["description"] : "";
121  std::string nm = m.contains( "name" ) ? std::string { m["name"] } : key;
122  if ( auto ec = params.getEnumConverter<T>( key ) ) {
123  auto items = ( *ec )->getEnumerators();
124  auto onEnumParameterStringChanged = [this, &params, &key]( const QString& value ) {
125  params.addParameter( key, value.toStdString() );
126  emit parameterModified( key );
127  };
128  addComboBox( nm,
129  onEnumParameterStringChanged,
130  params.getEnumString( key, initial ),
131  items,
132  description );
133  }
134  else {
135  LOG( Core::Utils::logWARNING )
136  << "ParameterSet don't have converter for enum " << key << " use index<>int instead.";
137 
138  auto items = std::vector<std::string>();
139  items.reserve( m["values"].size() );
140  for ( const auto& value : m["values"] ) {
141  items.push_back( value );
142  }
143 
144  auto onEnumParameterIntChanged = [this, &params, &key]( T value ) {
145  params.addParameter( key, value );
146  emit parameterModified( key );
147  };
148  addComboBox( nm, onEnumParameterIntChanged, initial, items, description );
149  }
150 }
151 
152 template <typename T>
153 void ParameterSetEditor::addNumberParameterWidget( const std::string& key,
154  T& initial,
156  const json& metadata ) {
157 
158  auto onNumberParameterChanged = [this, &initial, &key]( T value ) {
159  initial = value;
160  emit parameterModified( key );
161  };
162  if ( metadata.contains( key ) ) {
163  auto m = metadata[key];
164  auto min = std::numeric_limits<T>::lowest();
165  auto max = std::numeric_limits<T>::max();
166 
167  std::string description = m.contains( "description" ) ? m["description"] : "";
168  std::string nm = m.contains( "name" ) ? std::string { m["name"] } : key;
169 
170  if ( m.contains( "oneOf" ) ) {
171  // the variable has multiple valid bounds
172  std::vector<std::pair<T, T>> bounds;
173  bounds.reserve( m["oneOf"].size() );
174  for ( const auto& bound : m["oneOf"] ) {
175  auto mini = bound.contains( "minimum" ) ? T( bound["minimum"] ) : min;
176  auto maxi = bound.contains( "maximum" ) ? T( bound["maximum"] ) : max;
177  bounds.emplace_back( mini, maxi );
178  }
179  auto predicate = [bounds]( T value ) {
180  bool valid = false;
181  auto it = bounds.begin();
182  while ( !valid && it != bounds.end() ) {
183  valid = value >= ( *it ).first && value <= ( *it ).second;
184  ++it;
185  }
186  return valid;
187  };
188 
189  addConstrainedNumberInput<T>(
190  nm, onNumberParameterChanged, initial, predicate, description );
191  }
192  else if ( m.contains( "minimum" ) && m.contains( "maximum" ) ) {
193  min = T( m["minimum"] );
194  max = T( m["maximum"] );
195  if constexpr ( std::is_floating_point_v<T> ) {
196  addPowerSliderInput( nm, onNumberParameterChanged, initial, min, max, description );
197  }
198  else { addSliderInput( nm, onNumberParameterChanged, initial, min, max, description ); }
199  }
200  else {
201  min = m.contains( "minimum" ) ? T( m["minimum"] ) : min;
202  max = m.contains( "maximum" ) ? T( m["maximum"] ) : max;
203  addNumberInput<T>( nm, onNumberParameterChanged, initial, min, max, description );
204  }
205  }
206  else if ( m_showUnspecified ) { addNumberInput<T>( key, onNumberParameterChanged, initial ); }
207 }
208 
209 template <typename T>
210 void ParameterSetEditor::addVectorParameterWidget( const std::string& key,
211  std::vector<T>& initial,
213  const json& metadata ) {
214  auto onVectorParameterChanged = [this, &initial, &key]( const std::vector<T>& value ) {
215  initial = value;
216  emit parameterModified( key );
217  };
218 
219  if ( metadata.contains( key ) ) {
220  auto m = metadata[key];
221  std::string description = m.contains( "description" ) ? m["description"] : "";
222  addVectorInput<T>( m["name"], onVectorParameterChanged, initial, description );
223  }
224  else if ( m_showUnspecified ) { addVectorInput<T>( key, onVectorParameterChanged, initial ); }
225 }
226 
227 template <typename T>
228 void ParameterSetEditor::addMatrixParameterWidget( const std::string& key,
229  T& initial,
231  const json& metadata ) {
232  auto onMatrixParameterChanged = [this, &initial, &key]( const Ra::Core::MatrixN& value ) {
233  initial = T( value );
234  emit parameterModified( key );
235  };
236 
237  if ( metadata.contains( key ) ) {
238  auto m = metadata[key];
239  std::string description = m.contains( "description" ) ? m["description"] : "";
240  addMatrixInput( m["name"], onMatrixParameterChanged, initial, 3, description );
241  }
242  else if ( m_showUnspecified ) { addMatrixInput( key, onMatrixParameterChanged, initial ); }
243 }
244 
246  const nlohmann::json& constraints ) {
247 
248  internal::RenderParameterUiBuilder uiBuilder { this, constraints };
249  params.visit( uiBuilder, params );
250  addStretch( 0 );
251  setVisible( true );
252 }
253 
255  m_showUnspecified = enable;
256 }
257 } // namespace Gui
258 } // namespace Ra
void addParameter(const std::string &name, T value, typename std::enable_if<!std::is_class< T > {}, bool >::type=true)
Add a parameter by value.
std::pair< Data::Texture *, int > TextureInfo
Special type for Texture parameter.
Core::Utils::TypeList< bool, Core::Utils::Color, int, uint, Scalar, TextureInfo, std::vector< int >, std::vector< uint >, std::vector< Scalar >, Core::Vector2, Core::Vector3, Core::Vector4, Core::Matrix2, Core::Matrix3, Core::Matrix4, std::reference_wrapper< RenderParameters >, std::reference_wrapper< const RenderParameters > > BindableTypes
Aliases for bindable parameter types.
Core::Utils::optional< std::shared_ptr< Core::Utils::EnumConverter< EnumBaseType > > > getEnumConverter(const std::string &name)
Search for a converter associated with an enumeration parameter.
std::string getEnumString(const std::string &name, Enum value)
Return the string associated to the actual value of a parameter.
Simple Widget for RenderParameter edition The editor will expose a control panel containing all of th...
ParameterSetEditor(const std::string &name, QWidget *parent=nullptr)
void parameterModified(const std::string &name)
void setupFromParameters(Engine::Data::RenderParameters &params, const nlohmann::json &constraints)
Update the different UI element with the given renderParameter, using the given constraints.
void addComboBox(const std::string &name, std::function< void(int)> callback, int initial, const std::vector< std::string > &items, const std::string &tooltip="")
void addSliderInput(const std::string &name, std::function< void(int)> callback, int initial=0, int min=0, int max=100, const std::string &tooltip="")
void addPowerSliderInput(const std::string &name, std::function< void(double)> callback, double initial=0, double min=0, double max=100, const std::string &tooltip="")
void addMatrixInput(const std::string &name, std::function< void(const Ra::Core::MatrixN &)> callback, const Ra::Core::MatrixN &initial, int dec=3, const std::string &tooltip="")
void addStretch(int stretch=0)
Definition: Cage.cpp:3