mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 07:56:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			304 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef OPENMW_COMPONENTS_FX_WIDGETS_H
 | |
| #define OPENMW_COMPONENTS_FX_WIDGETS_H
 | |
| 
 | |
| #include <MyGUI_Button.h>
 | |
| #include <MyGUI_Delegate.h>
 | |
| #include <MyGUI_InputManager.h>
 | |
| #include <MyGUI_MouseButton.h>
 | |
| #include <MyGUI_RTTI.h>
 | |
| #include <MyGUI_TextBox.h>
 | |
| #include <MyGUI_Widget.h>
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <memory>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include <osg/Vec2f>
 | |
| #include <osg/Vec3f>
 | |
| #include <osg/Vec4f>
 | |
| 
 | |
| #include <components/misc/strings/format.hpp>
 | |
| 
 | |
| #include "types.hpp"
 | |
| 
 | |
| namespace Gui
 | |
| {
 | |
|     class AutoSizedTextBox;
 | |
|     class AutoSizedButton;
 | |
| }
 | |
| 
 | |
| namespace fx
 | |
| {
 | |
|     namespace Widgets
 | |
|     {
 | |
|         enum Index
 | |
|         {
 | |
|             None = -1,
 | |
|             Zero = 0,
 | |
|             One = 1,
 | |
|             Two = 2,
 | |
|             Three = 3
 | |
|         };
 | |
| 
 | |
|         class EditBase
 | |
|         {
 | |
|         public:
 | |
|             virtual ~EditBase() = default;
 | |
| 
 | |
|             void setData(const std::shared_ptr<fx::Types::UniformBase>& uniform, Index index = None)
 | |
|             {
 | |
|                 mUniform = uniform;
 | |
|                 mIndex = index;
 | |
|             }
 | |
| 
 | |
|             virtual void setValueFromUniform() = 0;
 | |
| 
 | |
|             virtual void toDefault() = 0;
 | |
| 
 | |
|         protected:
 | |
|             std::weak_ptr<fx::Types::UniformBase> mUniform;
 | |
|             Index mIndex;
 | |
|         };
 | |
| 
 | |
|         class EditBool : public EditBase, public MyGUI::Widget
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditBool)
 | |
| 
 | |
|         public:
 | |
|             void setValue(bool value);
 | |
|             void setValueFromUniform() override;
 | |
|             void toDefault() override;
 | |
| 
 | |
|         private:
 | |
|             void initialiseOverride() override;
 | |
|             void notifyMouseButtonClick(MyGUI::Widget* sender);
 | |
| 
 | |
|             MyGUI::Button* mCheckbutton{ nullptr };
 | |
|             MyGUI::Widget* mFill{ nullptr };
 | |
|         };
 | |
| 
 | |
|         template <class T, class UType>
 | |
|         class EditNumber : public EditBase, public MyGUI::Widget
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumber)
 | |
| 
 | |
|         public:
 | |
|             void setValue(T value)
 | |
|             {
 | |
|                 mValue = value;
 | |
|                 if constexpr (std::is_floating_point_v<T>)
 | |
|                     mValueLabel->setCaption(Misc::StringUtils::format("%.3f", mValue));
 | |
|                 else
 | |
|                     mValueLabel->setCaption(std::to_string(mValue));
 | |
| 
 | |
|                 float range = 0.f;
 | |
|                 float min = 0.f;
 | |
| 
 | |
|                 if (auto uniform = mUniform.lock())
 | |
|                 {
 | |
|                     if constexpr (std::is_fundamental_v<UType>)
 | |
|                     {
 | |
|                         uniform->template setValue<UType>(mValue);
 | |
|                         range = uniform->template getMax<UType>() - uniform->template getMin<UType>();
 | |
|                         min = uniform->template getMin<UType>();
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         UType uvalue = uniform->template getValue<UType>();
 | |
|                         uvalue[mIndex] = mValue;
 | |
|                         uniform->template setValue<UType>(uvalue);
 | |
|                         range = uniform->template getMax<UType>()[mIndex] - uniform->template getMin<UType>()[mIndex];
 | |
|                         min = uniform->template getMin<UType>()[mIndex];
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 float fill = (range == 0.f) ? 1.f : (mValue - min) / range;
 | |
|                 mFill->setRealSize(fill, 1.0);
 | |
|             }
 | |
| 
 | |
|             void setValueFromUniform() override
 | |
|             {
 | |
|                 if (auto uniform = mUniform.lock())
 | |
|                 {
 | |
|                     T value;
 | |
| 
 | |
|                     if constexpr (std::is_fundamental_v<UType>)
 | |
|                         value = uniform->template getValue<UType>();
 | |
|                     else
 | |
|                         value = uniform->template getValue<UType>()[mIndex];
 | |
| 
 | |
|                     setValue(value);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             void toDefault() override
 | |
|             {
 | |
|                 if (auto uniform = mUniform.lock())
 | |
|                 {
 | |
|                     if constexpr (std::is_fundamental_v<UType>)
 | |
|                         setValue(uniform->template getDefault<UType>());
 | |
|                     else
 | |
|                         setValue(uniform->template getDefault<UType>()[mIndex]);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         private:
 | |
|             void initialiseOverride() override
 | |
|             {
 | |
|                 Base::initialiseOverride();
 | |
| 
 | |
|                 assignWidget(mDragger, "Dragger");
 | |
|                 assignWidget(mValueLabel, "Value");
 | |
|                 assignWidget(mButtonIncrease, "ButtonIncrease");
 | |
|                 assignWidget(mButtonDecrease, "ButtonDecrease");
 | |
|                 assignWidget(mFill, "Fill");
 | |
| 
 | |
|                 mButtonIncrease->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNumber::notifyButtonClicked);
 | |
|                 mButtonDecrease->eventMouseButtonClick += MyGUI::newDelegate(this, &EditNumber::notifyButtonClicked);
 | |
| 
 | |
|                 mDragger->eventMouseButtonPressed += MyGUI::newDelegate(this, &EditNumber::notifyMouseButtonPressed);
 | |
|                 mDragger->eventMouseDrag += MyGUI::newDelegate(this, &EditNumber::notifyMouseButtonDragged);
 | |
|                 mDragger->eventMouseWheel += MyGUI::newDelegate(this, &EditNumber::notifyMouseWheel);
 | |
|             }
 | |
| 
 | |
|             void notifyMouseWheel(MyGUI::Widget* sender, int rel)
 | |
|             {
 | |
|                 auto uniform = mUniform.lock();
 | |
| 
 | |
|                 if (!uniform)
 | |
|                     return;
 | |
| 
 | |
|                 if (rel > 0)
 | |
|                     increment(uniform->mStep);
 | |
|                 else
 | |
|                     increment(-uniform->mStep);
 | |
|             }
 | |
| 
 | |
|             void notifyMouseButtonDragged(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
 | |
|             {
 | |
|                 if (id != MyGUI::MouseButton::Left)
 | |
|                     return;
 | |
| 
 | |
|                 auto uniform = mUniform.lock();
 | |
| 
 | |
|                 if (!uniform)
 | |
|                     return;
 | |
| 
 | |
|                 int delta = left - mLastPointerX;
 | |
| 
 | |
|                 // allow finer tuning when shift is pressed
 | |
|                 constexpr double scaling = 20.0;
 | |
|                 T step
 | |
|                     = MyGUI::InputManager::getInstance().isShiftPressed() ? uniform->mStep / scaling : uniform->mStep;
 | |
| 
 | |
|                 if (step == 0)
 | |
|                 {
 | |
|                     if constexpr (std::is_integral_v<T>)
 | |
|                         step = 1;
 | |
|                     else
 | |
|                         step = uniform->mStep;
 | |
|                 }
 | |
| 
 | |
|                 if (delta > 0)
 | |
|                     increment(step);
 | |
|                 else if (delta < 0)
 | |
|                     increment(-step);
 | |
| 
 | |
|                 mLastPointerX = left;
 | |
|             }
 | |
| 
 | |
|             void notifyMouseButtonPressed(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
 | |
|             {
 | |
|                 if (id != MyGUI::MouseButton::Left)
 | |
|                     return;
 | |
| 
 | |
|                 mLastPointerX = left;
 | |
|             }
 | |
| 
 | |
|             void increment(T step)
 | |
|             {
 | |
|                 auto uniform = mUniform.lock();
 | |
| 
 | |
|                 if (!uniform)
 | |
|                     return;
 | |
| 
 | |
|                 if constexpr (std::is_fundamental_v<UType>)
 | |
|                     setValue(std::clamp<T>(uniform->template getValue<UType>() + step,
 | |
|                         uniform->template getMin<UType>(), uniform->template getMax<T>()));
 | |
|                 else
 | |
|                     setValue(std::clamp<T>(uniform->template getValue<UType>()[mIndex] + step,
 | |
|                         uniform->template getMin<UType>()[mIndex], uniform->template getMax<UType>()[mIndex]));
 | |
|             }
 | |
| 
 | |
|             void notifyButtonClicked(MyGUI::Widget* sender)
 | |
|             {
 | |
|                 auto uniform = mUniform.lock();
 | |
| 
 | |
|                 if (!uniform)
 | |
|                     return;
 | |
| 
 | |
|                 if (sender == mButtonDecrease)
 | |
|                     increment(-uniform->mStep);
 | |
|                 else if (sender == mButtonIncrease)
 | |
|                     increment(uniform->mStep);
 | |
|             }
 | |
| 
 | |
|             MyGUI::Button* mButtonDecrease{ nullptr };
 | |
|             MyGUI::Button* mButtonIncrease{ nullptr };
 | |
|             MyGUI::Widget* mDragger{ nullptr };
 | |
|             MyGUI::Widget* mFill{ nullptr };
 | |
|             MyGUI::TextBox* mValueLabel{ nullptr };
 | |
|             T mValue{};
 | |
| 
 | |
|             int mLastPointerX{ 0 };
 | |
|         };
 | |
| 
 | |
|         class EditNumberFloat4 : public EditNumber<float, osg::Vec4f>
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumberFloat4)
 | |
|         };
 | |
|         class EditNumberFloat3 : public EditNumber<float, osg::Vec3f>
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumberFloat3)
 | |
|         };
 | |
|         class EditNumberFloat2 : public EditNumber<float, osg::Vec2f>
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumberFloat2)
 | |
|         };
 | |
|         class EditNumberFloat : public EditNumber<float, float>
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumberFloat)
 | |
|         };
 | |
|         class EditNumberInt : public EditNumber<int, int>
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(EditNumberInt)
 | |
|         };
 | |
| 
 | |
|         class UniformBase final : public MyGUI::Widget
 | |
|         {
 | |
|             MYGUI_RTTI_DERIVED(UniformBase)
 | |
| 
 | |
|         public:
 | |
|             void init(const std::shared_ptr<fx::Types::UniformBase>& uniform);
 | |
| 
 | |
|             void toDefault();
 | |
| 
 | |
|             void addItem(EditBase* item);
 | |
| 
 | |
|             Gui::AutoSizedTextBox* getLabel() { return mLabel; }
 | |
| 
 | |
|         private:
 | |
|             void notifyResetClicked(MyGUI::Widget* sender);
 | |
| 
 | |
|             void initialiseOverride() override;
 | |
| 
 | |
|             Gui::AutoSizedButton* mReset{ nullptr };
 | |
|             Gui::AutoSizedTextBox* mLabel{ nullptr };
 | |
|             MyGUI::Widget* mClient{ nullptr };
 | |
|             std::vector<EditBase*> mBases;
 | |
|         };
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 |