| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #include "BsGUIFloatField.h"
- #include "BsGUILayout.h"
- #include "BsGUILabel.h"
- #include "BsGUIInputBox.h"
- #include "BsGUISpace.h"
- #include "BsBuiltinResources.h"
- #include "BsCGUIWidget.h"
- #include "BsGUIMouseEvent.h"
- #include "BsCursor.h"
- #include "BsCGUIWidget.h"
- #include "BsViewport.h"
- #include "BsCmdInputFieldValueChange.h"
- #include <regex>
- using namespace std::placeholders;
- namespace BansheeEngine
- {
- const float GUIFloatField::DRAG_SPEED = 0.05f;
- GUIFloatField::GUIFloatField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
- const String& style, const GUIDimensions& dimensions, bool withLabel)
- :TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel), mInputBox(nullptr), mIsDragging(false),
- mLastDragPos(0), mHasInputFocus(false), mValue(0.0f), mMinValue(std::numeric_limits<float>::lowest()),
- mMaxValue(std::numeric_limits<float>::max())
- {
- mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getInputStyleType()));
- mInputBox->setFilter(&GUIFloatField::floatFilter);
- mInputBox->onValueChanged.connect(std::bind((void(GUIFloatField::*)(const WString&))&GUIFloatField::valueChanged, this, _1));
- mInputBox->onFocusChanged.connect(std::bind(&GUIFloatField::focusChanged, this, _1));
- mInputBox->onConfirm.connect(std::bind(&GUIFloatField::inputConfirmed, this));
- mLayout->addElement(mInputBox);
- setValue(0);
- mInputBox->setText(L"0");
- }
- GUIFloatField::~GUIFloatField()
- {
- }
- bool GUIFloatField::_hasCustomCursor(const Vector2I position, CursorType& type) const
- {
- if (!_isDisabled())
- {
- Rect2I draggableArea;
- if (mLabel != nullptr)
- draggableArea = mLabel->_getLayoutData().area;
- if (draggableArea.contains(position))
- {
- type = CursorType::ArrowLeftRight;
- return true;
- }
- }
- return false;
- }
- bool GUIFloatField::_mouseEvent(const GUIMouseEvent& event)
- {
- GUIElementContainer::_mouseEvent(event);
- Rect2I draggableArea;
- if(mLabel != nullptr)
- draggableArea = mLabel->_getLayoutData().area;
- if(event.getType() == GUIMouseEventType::MouseDragStart)
- {
- if (!_isDisabled())
- {
- if (draggableArea.contains(event.getDragStartPosition()))
- {
- mLastDragPos = event.getPosition().x;
- mIsDragging = true;
- }
- }
- return true;
- }
- else if(event.getType() == GUIMouseEventType::MouseDrag)
- {
- if (!_isDisabled())
- {
- if (mIsDragging)
- {
- INT32 xDiff = event.getPosition().x - mLastDragPos;
- INT32 jumpAmount = 0;
- if (event.getPosition().x < 0)
- {
- Vector2I cursorScreenPos = Cursor::instance().getScreenPosition();
- cursorScreenPos.x += _getParentWidget()->getTarget()->getWidth();
- jumpAmount = _getParentWidget()->getTarget()->getWidth();
- Cursor::instance().setScreenPosition(cursorScreenPos);
- }
- else if (event.getPosition().x >= _getParentWidget()->getTarget()->getWidth())
- {
- Vector2I cursorScreenPos = Cursor::instance().getScreenPosition();
- cursorScreenPos.x -= _getParentWidget()->getTarget()->getWidth();
- jumpAmount = -_getParentWidget()->getTarget()->getWidth();
- Cursor::instance().setScreenPosition(cursorScreenPos);
- }
- float oldValue = getValue();
- float newValue = oldValue + xDiff * DRAG_SPEED;
- mLastDragPos = event.getPosition().x + jumpAmount;
- if (oldValue != newValue)
- {
- setValue(newValue);
- valueChanged(newValue);
- }
- }
- }
- return true;
- }
- else if(event.getType() == GUIMouseEventType::MouseDragEnd)
- {
- if (!_isDisabled())
- mIsDragging = false;
- return true;
- }
- return false;
- }
- void GUIFloatField::setValue(float value)
- {
- mValue = Math::clamp(value, mMinValue, mMaxValue);
- // Only update with new value if it actually changed, otherwise
- // problems can occur when user types in "0." and the field
- // updates back to "0" effectively making "." unusable
- float curValue = parseFloat(mInputBox->getText());
- if (mValue != curValue)
- mInputBox->setText(toWString(mValue));
- }
- void GUIFloatField::setRange(float min, float max)
- {
- mMinValue = min;
- mMaxValue = max;
- }
- void GUIFloatField::setTint(const Color& color)
- {
- if (mLabel != nullptr)
- mLabel->setTint(color);
- mInputBox->setTint(color);
- }
- const String& GUIFloatField::getGUITypeName()
- {
- static String typeName = "GUIFloatField";
- return typeName;
- }
- const String& GUIFloatField::getInputStyleType()
- {
- static String LABEL_STYLE_TYPE = "EditorFieldInput";
- return LABEL_STYLE_TYPE;
- }
- void GUIFloatField::styleUpdated()
- {
- if (mLabel != nullptr)
- mLabel->setStyle(getSubStyleName(getLabelStyleType()));
- mInputBox->setStyle(getSubStyleName(getInputStyleType()));
- }
- void GUIFloatField::valueChanged(const WString& newValue)
- {
- valueChanged(parseFloat(newValue));
- }
- void GUIFloatField::valueChanged(float newValue)
- {
- CmdInputFieldValueChange<GUIFloatField, float>::execute(this, newValue);
- if (!onValueChanged.empty())
- onValueChanged(newValue);
- }
- void GUIFloatField::focusChanged(bool focus)
- {
- if (focus)
- {
- UndoRedo::instance().pushGroup("InputBox");
- mHasInputFocus = true;
- }
- else
- {
- UndoRedo::instance().popGroup("InputBox");
- mHasInputFocus = false;
- }
- }
- void GUIFloatField::inputConfirmed()
- {
- onConfirm();
- }
- bool GUIFloatField::floatFilter(const WString& str)
- {
- return std::regex_match(str, std::wregex(L"-?(\\d+(\\.\\d*)?)?"));
- }
- }
|