BsGUIFloatDistributionField.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "GUI/BsGUIFloatDistributionField.h"
  4. #include "GUI/BsGUILayout.h"
  5. #include "GUI/BsGUILabel.h"
  6. #include "GUI/BsGUIColor.h"
  7. #include "GUI/BsGUIFloatField.h"
  8. #include "GUI/BsGUICurves.h"
  9. #include "GUI/BsGUIButton.h"
  10. #include "GUI/BsGUIContextMenu.h"
  11. #include "GUI/BsGUISpace.h"
  12. using namespace std::placeholders;
  13. namespace bs
  14. {
  15. GUIFloatDistributionField::GUIFloatDistributionField(const PrivatelyConstruct& dummy, const GUIContent& labelContent,
  16. UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
  17. : TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel)
  18. {
  19. mContextMenu = bs_shared_ptr_new<GUIContextMenu>();
  20. mContextMenu->addMenuItem("Constant", [this]()
  21. {
  22. mValue = FloatDistribution(mMinConstant);
  23. rebuild();
  24. }, 50);
  25. mContextMenu->addMenuItem("Range", [this]()
  26. {
  27. mValue = FloatDistribution(mMinConstant, mMaxConstant);
  28. rebuild();
  29. }, 40);
  30. mContextMenu->addMenuItem("Curve", [this]()
  31. {
  32. mValue = FloatDistribution(mCurves[0]);
  33. rebuild();
  34. }, 30);
  35. mContextMenu->addMenuItem("Curve range", [this]()
  36. {
  37. mValue = FloatDistribution(mCurves[0], mCurves[1]);
  38. rebuild();
  39. }, 20);
  40. rebuild();
  41. }
  42. void GUIFloatDistributionField::setValue(const FloatDistribution& value)
  43. {
  44. mValue = value;
  45. switch (mValue.getType())
  46. {
  47. default:
  48. case PDT_Constant:
  49. mMinConstant = mValue.getMinConstant();
  50. mMaxConstant = mMinConstant;
  51. mCurves[0] = TAnimationCurve<float>({
  52. { mMinConstant, 0.0f, 0.0f, 0.0f},
  53. { mMinConstant, 0.0f, 0.0f, 1.0f}});
  54. mCurves[1] = TAnimationCurve<float>({
  55. { mMinConstant, 0.0f, 0.0f, 0.0f},
  56. { mMinConstant, 0.0f, 0.0f, 1.0f}});
  57. break;
  58. case PDT_RandomRange:
  59. mMinConstant = mValue.getMinConstant();
  60. mMaxConstant = mValue.getMaxConstant();
  61. mCurves[0] = TAnimationCurve<float>({
  62. { mMinConstant, 0.0f, 0.0f, 0.0f},
  63. { mMinConstant, 0.0f, 0.0f, 1.0f}});
  64. mCurves[1] = TAnimationCurve<float>({
  65. { mMaxConstant, 0.0f, 0.0f, 0.0f},
  66. { mMaxConstant, 0.0f, 0.0f, 1.0f}});
  67. break;
  68. case PDT_Curve:
  69. mCurves[0] = mValue.getMinCurve();
  70. mCurves[1] = mValue.getMinCurve();
  71. mMinConstant = mCurves[0].evaluate(0.0f);
  72. mMaxConstant = mCurves[1].evaluate(0.0f);
  73. break;
  74. case PDT_RandomCurveRange:
  75. mCurves[0] = mValue.getMinCurve();
  76. mCurves[1] = mValue.getMaxCurve();
  77. mMinConstant = mCurves[0].evaluate(0.0f);
  78. mMaxConstant = mCurves[1].evaluate(0.0f);
  79. break;
  80. }
  81. rebuild();
  82. }
  83. bool GUIFloatDistributionField::hasInputFocus() const
  84. {
  85. if(mMinInput && mMinInput->hasInputFocus())
  86. return true;
  87. if(mMaxInput && mMaxInput->hasInputFocus())
  88. return true;
  89. return false;
  90. }
  91. void GUIFloatDistributionField::setTint(const Color& color)
  92. {
  93. mDropDownButton->setTint(color);
  94. if (mLabel)
  95. mLabel->setTint(color);
  96. if(mMinInput)
  97. mMinInput->setTint(color);
  98. if(mMaxInput)
  99. mMaxInput->setTint(color);
  100. if(mCurveDisplay)
  101. mCurveDisplay->setTint(color);
  102. }
  103. Vector2I GUIFloatDistributionField::_getOptimalSize() const
  104. {
  105. Vector2I optimalsize = mDropDownButton->_getOptimalSize();
  106. if(mLabel)
  107. {
  108. optimalsize.x += mLabel->_getOptimalSize().x;
  109. optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
  110. }
  111. if(mMinInput)
  112. {
  113. optimalsize.x += mMinInput->_getOptimalSize().x;
  114. optimalsize.y = std::max(optimalsize.y, mMinInput->_getOptimalSize().y);
  115. }
  116. if(mMaxInput)
  117. {
  118. optimalsize.x += mMaxInput->_getOptimalSize().x;
  119. optimalsize.y = std::max(optimalsize.y, mMaxInput->_getOptimalSize().y);
  120. }
  121. if(mCurveDisplay)
  122. {
  123. optimalsize.x += mCurveDisplay->_getOptimalSize().x;
  124. optimalsize.y = std::max(optimalsize.y, 50);
  125. }
  126. return optimalsize;
  127. }
  128. void GUIFloatDistributionField::styleUpdated()
  129. {
  130. mDropDownButton->setStyle(getSubStyleName(DROP_DOWN_FIELD_STYLE_TYPE));
  131. if (mLabel)
  132. mLabel->setStyle(getSubStyleName(getLabelStyleType()));
  133. if (mMinInput)
  134. mMinInput->setStyle(getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
  135. if (mMaxInput)
  136. mMaxInput->setStyle(getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
  137. if (mCurveDisplay)
  138. mCurveDisplay->setStyle(getSubStyleName(CURVES_FIELD_STYLE_TYPE));
  139. }
  140. void GUIFloatDistributionField::rebuild()
  141. {
  142. if(mLabel)
  143. mLayout->removeElement(mLabel);
  144. mLayout->clear();
  145. mLayout->addElement(mLabel);
  146. switch (mValue.getType())
  147. {
  148. default:
  149. case PDT_Constant:
  150. mMinInput = GUIFloatField::create(HString("Constant"), 50, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
  151. mMaxInput = nullptr;
  152. mCurveDisplay = nullptr;
  153. mMinInput->setValue(mMinConstant);
  154. mMinInput->onValueChanged.connect([this](float value)
  155. {
  156. mMinConstant = value;
  157. mValue = FloatDistribution(value);
  158. onConstantModified();
  159. });
  160. mMinInput->onConfirm.connect([this]() { onConstantConfirmed(); });
  161. mLayout->addElement(mMinInput);
  162. break;
  163. case PDT_RandomRange:
  164. mMinInput = GUIFloatField::create(HString("Min."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
  165. mMaxInput = GUIFloatField::create(HString("Max."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
  166. mCurveDisplay = nullptr;
  167. mMinInput->setValue(mMinConstant);
  168. mMinInput->onValueChanged.connect([this](float value)
  169. {
  170. mMinConstant = value;
  171. mValue = FloatDistribution(value, mMaxConstant);
  172. onConstantModified();
  173. });
  174. mMinInput->onConfirm.connect([this]() { onConstantConfirmed(); });
  175. mMaxInput->setValue(mMaxConstant);
  176. mMaxInput->onValueChanged.connect([this](float value)
  177. {
  178. mMaxConstant = value;
  179. mValue = FloatDistribution(mMinConstant, value);
  180. onConstantModified();
  181. });
  182. mMaxInput->onConfirm.connect([this]() { onConstantConfirmed(); });
  183. mLayout->addElement(mMinInput);
  184. mLayout->addElement(mMaxInput);
  185. break;
  186. case PDT_Curve:
  187. mMinInput = nullptr;
  188. mMaxInput = nullptr;
  189. mCurveDisplay = GUICurves::create(CurveDrawOption::DrawMarkers,
  190. getSubStyleName(CURVES_FIELD_STYLE_TYPE));
  191. mCurveDisplay->setCurves(
  192. {
  193. CurveDrawInfo(mValue.getMinCurve(), Color::BansheeOrange)
  194. });
  195. mCurveDisplay->setPadding(3);
  196. mCurveDisplay->centerAndZoom();
  197. mCurveDisplay->onClicked.connect([this](){ onClicked(); });
  198. mLayout->addElement(mCurveDisplay);
  199. break;
  200. case PDT_RandomCurveRange:
  201. mMinInput = nullptr;
  202. mMaxInput = nullptr;
  203. mCurveDisplay = GUICurves::create(CurveDrawOption::DrawMarkers | CurveDrawOption::DrawRange,
  204. getSubStyleName(CURVES_FIELD_STYLE_TYPE));
  205. mCurveDisplay->setCurves(
  206. {
  207. CurveDrawInfo(mValue.getMinCurve(), Color::BansheeOrange),
  208. CurveDrawInfo(mValue.getMaxCurve(), Color::Red)
  209. });
  210. mCurveDisplay->setPadding(3);
  211. mCurveDisplay->centerAndZoom();
  212. mCurveDisplay->onClicked.connect([this](){ onClicked(); });
  213. mLayout->addElement(mCurveDisplay);
  214. break;
  215. }
  216. mDropDownButton = GUIButton::create(HString::dummy(), getSubStyleName(DROP_DOWN_FIELD_STYLE_TYPE));
  217. mDropDownButton->onClick.connect([this]()
  218. {
  219. const Rect2I bounds = mDropDownButton->getBounds(mParentWidget->getPanel());
  220. const Vector2I center(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
  221. mContextMenu->open(center, *mParentWidget);
  222. });
  223. mLayout->addNewElement<GUIFixedSpace>(10);
  224. mLayout->addElement(mDropDownButton);
  225. }
  226. const String& GUIFloatDistributionField::getGUITypeName()
  227. {
  228. static String typeName = "GUIFloatDistributionField";
  229. return typeName;
  230. }
  231. }