Merge branch 'uniform_choice' into 'master'

Add choice widget type to postprocessing uniforms

See merge request OpenMW/openmw!3969
esm4-texture
psi29a 7 months ago
commit db27543ea1

@ -168,10 +168,11 @@ namespace MWGui
if (static_cast<size_t>(index) != selected) if (static_cast<size_t>(index) != selected)
{ {
auto technique = *mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected); auto technique = *mActiveList->getItemDataAt<std::shared_ptr<fx::Technique>>(selected);
if (technique->getDynamic()) if (technique->getDynamic() || technique->getInternal())
return; return;
if (processor->enableTechnique(std::move(technique), index) != MWRender::PostProcessor::Status_Error) if (processor->enableTechnique(std::move(technique), index - mOffset)
!= MWRender::PostProcessor::Status_Error)
processor->saveChain(); processor->saveChain();
} }
} }
@ -444,10 +445,16 @@ namespace MWGui
} }
} }
mOffset = 0;
for (auto technique : processor->getTechniques()) for (auto technique : processor->getTechniques())
{ {
if (!technique->getHidden()) if (!technique->getHidden())
{
mActiveList->addItem(technique->getName(), technique); mActiveList->addItem(technique->getName(), technique);
if (technique->getInternal())
mOffset++;
}
} }
auto tryFocus = [this](ListWrapper* widget, const std::string& hint) { auto tryFocus = [this](ListWrapper* widget, const std::string& hint) {
@ -484,6 +491,7 @@ namespace MWGui
factory.registerFactory<fx::Widgets::EditNumberFloat>("Widget"); factory.registerFactory<fx::Widgets::EditNumberFloat>("Widget");
factory.registerFactory<fx::Widgets::EditNumberInt>("Widget"); factory.registerFactory<fx::Widgets::EditNumberInt>("Widget");
factory.registerFactory<fx::Widgets::EditBool>("Widget"); factory.registerFactory<fx::Widgets::EditBool>("Widget");
factory.registerFactory<fx::Widgets::EditChoice>("Widget");
factory.registerFactory<ListWrapper>("Widget"); factory.registerFactory<ListWrapper>("Widget");
} }
} }

@ -96,6 +96,8 @@ namespace MWGui
Gui::AutoSizedEditBox* mShaderInfo; Gui::AutoSizedEditBox* mShaderInfo;
std::string mOverrideHint; std::string mOverrideHint;
int mOffset = 0;
}; };
} }

@ -1,5 +1,7 @@
#include "pingpongcanvas.hpp" #include "pingpongcanvas.hpp"
#include <cassert>
#include <components/shader/shadermanager.hpp> #include <components/shader/shadermanager.hpp>
#include <components/stereo/multiview.hpp> #include <components/stereo/multiview.hpp>
#include <components/stereo/stereomanager.hpp> #include <components/stereo/stereomanager.hpp>

@ -498,6 +498,37 @@ namespace fx
mDefinedUniforms.emplace_back(std::move(uniform)); mDefinedUniforms.emplace_back(std::move(uniform));
} }
template <class SrcT, class T>
SrcT Technique::getUniformValue()
{
constexpr bool isVec
= std::is_same_v<osg::Vec2f, SrcT> || std::is_same_v<osg::Vec3f, SrcT> || std::is_same_v<osg::Vec4f, SrcT>;
constexpr bool isFloat = std::is_same_v<float, SrcT>;
constexpr bool isInt = std::is_same_v<int, SrcT>;
constexpr bool isBool = std::is_same_v<bool, SrcT>;
static_assert(isVec || isFloat || isInt || isBool, "Unsupported type");
if constexpr (isVec)
{
return parseVec<SrcT, T>();
}
else if constexpr (isFloat)
{
return parseFloat();
}
else if constexpr (isInt)
{
return parseInteger();
}
else if constexpr (isBool)
{
return parseBool();
}
error(Misc::StringUtils::format("failed setting uniform type"));
}
template <class SrcT, class T> template <class SrcT, class T>
void Technique::parseUniform() void Technique::parseUniform()
{ {
@ -515,28 +546,13 @@ namespace fx
expect<Lexer::Equal>("error parsing config for uniform block"); expect<Lexer::Equal>("error parsing config for uniform block");
constexpr bool isVec = std::is_same_v<osg::Vec2f,
SrcT> || std::is_same_v<osg::Vec3f, SrcT> || std::is_same_v<osg::Vec4f, SrcT>;
constexpr bool isFloat = std::is_same_v<float, SrcT>;
constexpr bool isInt = std::is_same_v<int, SrcT>;
constexpr bool isBool = std::is_same_v<bool, SrcT>;
static_assert(isVec || isFloat || isInt || isBool, "Unsupported type");
if (key == "default") if (key == "default")
{ {
if constexpr (isVec) data.mDefault = getUniformValue<SrcT, T>();
data.mDefault = parseVec<SrcT, T>();
else if constexpr (isFloat)
data.mDefault = parseFloat();
else if constexpr (isInt)
data.mDefault = parseInteger();
else if constexpr (isBool)
data.mDefault = parseBool();
} }
else if (key == "size") else if (key == "size")
{ {
if constexpr (isBool) if constexpr (std::is_same_v<bool, SrcT>)
error("bool arrays currently unsupported"); error("bool arrays currently unsupported");
int size = parseInteger(); int size = parseInteger();
@ -545,25 +561,11 @@ namespace fx
} }
else if (key == "min") else if (key == "min")
{ {
if constexpr (isVec) data.mMin = getUniformValue<SrcT, T>();
data.mMin = parseVec<SrcT, T>();
else if constexpr (isFloat)
data.mMin = parseFloat();
else if constexpr (isInt)
data.mMin = parseInteger();
else if constexpr (isBool)
data.mMin = parseBool();
} }
else if (key == "max") else if (key == "max")
{ {
if constexpr (isVec) data.mMax = getUniformValue<SrcT, T>();
data.mMax = parseVec<SrcT, T>();
else if constexpr (isFloat)
data.mMax = parseFloat();
else if constexpr (isInt)
data.mMax = parseInteger();
else if constexpr (isBool)
data.mMax = parseBool();
} }
else if (key == "step") else if (key == "step")
uniform->mStep = parseFloat(); uniform->mStep = parseFloat();
@ -571,18 +573,19 @@ namespace fx
uniform->mStatic = parseBool(); uniform->mStatic = parseBool();
else if (key == "description") else if (key == "description")
{ {
expect<Lexer::String>(); uniform->mDescription = parseString();
uniform->mDescription = std::get<Lexer::String>(mToken).value;
} }
else if (key == "header") else if (key == "header")
{ {
expect<Lexer::String>(); uniform->mHeader = parseString();
uniform->mHeader = std::get<Lexer::String>(mToken).value;
} }
else if (key == "display_name") else if (key == "display_name")
{ {
expect<Lexer::String>(); uniform->mDisplayName = parseString();
uniform->mDisplayName = std::get<Lexer::String>(mToken).value; }
else if (key == "widget_type")
{
parseWidgetType<SrcT, T>(data);
} }
else else
error(Misc::StringUtils::format("unexpected key '%s'", std::string{ key })); error(Misc::StringUtils::format("unexpected key '%s'", std::string{ key }));
@ -1001,6 +1004,60 @@ namespace fx
error(Misc::StringUtils::format("unrecognized blend function '%s'", std::string{ asLiteral() })); error(Misc::StringUtils::format("unrecognized blend function '%s'", std::string{ asLiteral() }));
} }
template <class SrcT, class T>
void Technique::parseWidgetType(Types::Uniform<SrcT>& uniform)
{
expect<Lexer::Literal>();
if (asLiteral() == "choice")
{
/* Example usage
widget_type = choice(
"Option A": <T>,
"Option B": <T>,
"Option C": <T>
);
*/
expect<Lexer::Open_Parenthesis>();
std::vector<fx::Types::Choice<SrcT>> choices;
while (!isNext<Lexer::Eof>())
{
fx::Types::Choice<SrcT> choice;
choice.mLabel = parseString();
expect<Lexer::Equal>();
choice.mValue = getUniformValue<SrcT, T>();
choices.push_back(choice);
if (isNext<Lexer::Comma>())
{
mToken = mLexer->next();
// Handle leading comma
if (isNext<Lexer::Close_Parenthesis>())
{
break;
}
continue;
}
break;
}
uniform.mChoices = std::move(choices);
expect<Lexer::Close_Parenthesis>();
}
else
{
error(Misc::StringUtils::format("unrecognized widget type '%s'", std::string{ asLiteral() }));
}
}
bool Technique::parseBool() bool Technique::parseBool()
{ {
mToken = mLexer->next(); mToken = mLexer->next();

@ -228,6 +228,12 @@ namespace fx
int parseSourceFormat(); int parseSourceFormat();
template <class SrcT, class T>
void parseWidgetType(Types::Uniform<SrcT>& uniform);
template <class SrcT, class T>
SrcT getUniformValue();
osg::BlendEquation::Equation parseBlendEquation(); osg::BlendEquation::Equation parseBlendEquation();
osg::BlendFunc::BlendFuncMode parseBlendFuncMode(); osg::BlendFunc::BlendFuncMode parseBlendFuncMode();

@ -4,15 +4,9 @@
#include <optional> #include <optional>
#include <variant> #include <variant>
#include <osg/BlendEquation>
#include <osg/BlendFunc>
#include <osg/Camera>
#include <osg/FrameBufferObject>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <osg/Uniform> #include <osg/Uniform>
#include <MyGUI_Widget.h>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/strings/format.hpp> #include <components/misc/strings/format.hpp>
#include <components/sceneutil/depth.hpp> #include <components/sceneutil/depth.hpp>
@ -56,6 +50,13 @@ namespace fx
osg::Vec4f mClearColor = osg::Vec4f(0.0, 0.0, 0.0, 1.0); osg::Vec4f mClearColor = osg::Vec4f(0.0, 0.0, 0.0, 1.0);
}; };
template <class T>
struct Choice
{
std::string mLabel;
T mValue;
};
template <class T> template <class T>
struct Uniform struct Uniform
{ {
@ -66,6 +67,8 @@ namespace fx
T mMin = std::numeric_limits<T>::lowest(); T mMin = std::numeric_limits<T>::lowest();
T mMax = std::numeric_limits<T>::max(); T mMax = std::numeric_limits<T>::max();
std::vector<Choice<T>> mChoices;
using value_type = T; using value_type = T;
bool isArray() const { return mArray.has_value(); } bool isArray() const { return mArray.has_value(); }

@ -28,35 +28,20 @@ namespace fx
{ {
void EditBool::setValue(bool value) void EditBool::setValue(bool value)
{ {
auto uniform = mUniform.lock();
if (!uniform)
return;
mCheckbutton->setCaptionWithReplacing(value ? "#{Interface:On}" : "#{Interface:Off}"); mCheckbutton->setCaptionWithReplacing(value ? "#{Interface:On}" : "#{Interface:Off}");
mFill->setVisible(value); mFill->setVisible(value);
uniform->setValue<bool>(value); mUniform->setValue<bool>(value);
} }
void EditBool::setValueFromUniform() void EditBool::setValueFromUniform()
{ {
auto uniform = mUniform.lock(); setValue(mUniform->template getValue<bool>());
if (!uniform)
return;
setValue(uniform->template getValue<bool>());
} }
void EditBool::toDefault() void EditBool::toDefault()
{ {
auto uniform = mUniform.lock(); setValue(mUniform->getDefault<bool>());
if (!uniform)
return;
setValue(uniform->getDefault<bool>());
} }
void EditBool::initialiseOverride() void EditBool::initialiseOverride()
@ -71,12 +56,75 @@ namespace fx
void EditBool::notifyMouseButtonClick(MyGUI::Widget* sender) void EditBool::notifyMouseButtonClick(MyGUI::Widget* sender)
{ {
auto uniform = mUniform.lock(); setValue(!mUniform->getValue<bool>());
}
template <class T>
void EditChoice::setValue(const T& value)
{
// Update the combo view
for (size_t i = 0; i < this->mChoices->getItemCount(); i++)
{
if (*this->mChoices->getItemDataAt<T>(i) == value)
{
this->mChoices->setIndexSelected(i);
break;
}
}
mUniform->template setValue<T>(value);
}
void EditChoice::notifyComboBoxChanged(MyGUI::ComboBox* sender, size_t pos)
{
std::visit(
[this, sender, pos](auto&& data) {
using T = typename std::decay_t<decltype(data)>::value_type;
setValue<T>(*sender->getItemDataAt<T>(pos));
},
mUniform->mData);
}
void EditChoice::setValueFromUniform()
{
std::visit(
[this](auto&& data) {
using T = typename std::decay_t<decltype(data)>::value_type;
size_t index = 0;
for (const auto& choice : data.mChoices)
{
this->mChoices->addItem(choice.mLabel, choice.mValue);
if (choice.mValue == mUniform->template getValue<T>())
{
this->mChoices->setIndexSelected(index);
}
index++;
}
setValue(mUniform->template getValue<T>());
},
mUniform->mData);
}
void EditChoice::toDefault()
{
std::visit(
[this](auto&& data) {
using T = typename std::decay_t<decltype(data)>::value_type;
setValue(mUniform->template getDefault<T>());
},
mUniform->mData);
}
void EditChoice::initialiseOverride()
{
Base::initialiseOverride();
if (!uniform) assignWidget(mChoices, "Choices");
return;
setValue(!uniform->getValue<bool>()); mChoices->eventComboChangePosition += MyGUI::newDelegate(this, &EditChoice::notifyComboBoxChanged);
} }
void UniformBase::init(const std::shared_ptr<fx::Types::UniformBase>& uniform) void UniformBase::init(const std::shared_ptr<fx::Types::UniformBase>& uniform)
@ -101,38 +149,48 @@ namespace fx
[this, &uniform](auto&& arg) { [this, &uniform](auto&& arg) {
using T = typename std::decay_t<decltype(arg)>::value_type; using T = typename std::decay_t<decltype(arg)>::value_type;
if constexpr (std::is_same_v<osg::Vec4f, T>) if (arg.mChoices.size() > 0)
{
createVectorWidget<T, EditNumberFloat4>(uniform, mClient, this);
}
else if constexpr (std::is_same_v<osg::Vec3f, T>)
{ {
createVectorWidget<T, EditNumberFloat3>(uniform, mClient, this); auto* widget = mClient->createWidget<EditChoice>("MW_ValueEditChoice",
}
else if constexpr (std::is_same_v<osg::Vec2f, T>)
{
createVectorWidget<T, EditNumberFloat2>(uniform, mClient, this);
}
else if constexpr (std::is_same_v<T, float>)
{
auto* widget = mClient->createWidget<EditNumberFloat>("MW_ValueEditNumber",
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch);
widget->setData(uniform);
mBases.emplace_back(widget);
}
else if constexpr (std::is_same_v<T, int>)
{
auto* widget = mClient->createWidget<EditNumberInt>("MW_ValueEditNumber",
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch); { 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch);
widget->setData(uniform); widget->setData(uniform);
mBases.emplace_back(widget); mBases.emplace_back(widget);
} }
else if constexpr (std::is_same_v<T, bool>) else
{ {
auto* widget = mClient->createWidget<EditBool>("MW_ValueEditBool", if constexpr (std::is_same_v<osg::Vec4f, T>)
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch); {
widget->setData(uniform); createVectorWidget<T, EditNumberFloat4>(uniform, mClient, this);
mBases.emplace_back(widget); }
else if constexpr (std::is_same_v<osg::Vec3f, T>)
{
createVectorWidget<T, EditNumberFloat3>(uniform, mClient, this);
}
else if constexpr (std::is_same_v<osg::Vec2f, T>)
{
createVectorWidget<T, EditNumberFloat2>(uniform, mClient, this);
}
else if constexpr (std::is_same_v<T, float>)
{
auto* widget = mClient->createWidget<EditNumberFloat>("MW_ValueEditNumber",
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch);
widget->setData(uniform);
mBases.emplace_back(widget);
}
else if constexpr (std::is_same_v<T, int>)
{
auto* widget = mClient->createWidget<EditNumberInt>("MW_ValueEditNumber",
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch);
widget->setData(uniform);
mBases.emplace_back(widget);
}
else if constexpr (std::is_same_v<T, bool>)
{
auto* widget = mClient->createWidget<EditBool>("MW_ValueEditBool",
{ 0, 0, mClient->getWidth(), mClient->getHeight() }, MyGUI::Align::Stretch);
widget->setData(uniform);
mBases.emplace_back(widget);
}
} }
mReset->eventMouseButtonClick += MyGUI::newDelegate(this, &UniformBase::notifyResetClicked); mReset->eventMouseButtonClick += MyGUI::newDelegate(this, &UniformBase::notifyResetClicked);

@ -57,7 +57,7 @@ namespace fx
virtual void toDefault() = 0; virtual void toDefault() = 0;
protected: protected:
std::weak_ptr<fx::Types::UniformBase> mUniform; std::shared_ptr<fx::Types::UniformBase> mUniform;
Index mIndex; Index mIndex;
}; };
@ -95,22 +95,19 @@ namespace fx
float range = 0.f; float range = 0.f;
float min = 0.f; float min = 0.f;
if (auto uniform = mUniform.lock()) if constexpr (std::is_fundamental_v<UType>)
{ {
if constexpr (std::is_fundamental_v<UType>) mUniform->template setValue<UType>(mValue);
{ range = mUniform->template getMax<UType>() - mUniform->template getMin<UType>();
uniform->template setValue<UType>(mValue); min = mUniform->template getMin<UType>();
range = uniform->template getMax<UType>() - uniform->template getMin<UType>(); }
min = uniform->template getMin<UType>(); else
} {
else UType uvalue = mUniform->template getValue<UType>();
{ uvalue[mIndex] = mValue;
UType uvalue = uniform->template getValue<UType>(); mUniform->template setValue<UType>(uvalue);
uvalue[mIndex] = mValue; range = mUniform->template getMax<UType>()[mIndex] - mUniform->template getMin<UType>()[mIndex];
uniform->template setValue<UType>(uvalue); min = mUniform->template getMin<UType>()[mIndex];
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; float fill = (range == 0.f) ? 1.f : (mValue - min) / range;
@ -119,28 +116,22 @@ namespace fx
void setValueFromUniform() override void setValueFromUniform() override
{ {
if (auto uniform = mUniform.lock()) T value;
{
T value;
if constexpr (std::is_fundamental_v<UType>) if constexpr (std::is_fundamental_v<UType>)
value = uniform->template getValue<UType>(); value = mUniform->template getValue<UType>();
else else
value = uniform->template getValue<UType>()[mIndex]; value = mUniform->template getValue<UType>()[mIndex];
setValue(value); setValue(value);
}
} }
void toDefault() override void toDefault() override
{ {
if (auto uniform = mUniform.lock()) if constexpr (std::is_fundamental_v<UType>)
{ setValue(mUniform->template getDefault<UType>());
if constexpr (std::is_fundamental_v<UType>) else
setValue(uniform->template getDefault<UType>()); setValue(mUniform->template getDefault<UType>()[mIndex]);
else
setValue(uniform->template getDefault<UType>()[mIndex]);
}
} }
private: private:
@ -164,15 +155,10 @@ namespace fx
void notifyMouseWheel(MyGUI::Widget* sender, int rel) void notifyMouseWheel(MyGUI::Widget* sender, int rel)
{ {
auto uniform = mUniform.lock();
if (!uniform)
return;
if (rel > 0) if (rel > 0)
increment(uniform->mStep); increment(mUniform->mStep);
else else
increment(-uniform->mStep); increment(-mUniform->mStep);
} }
void notifyMouseButtonDragged(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id) void notifyMouseButtonDragged(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
@ -180,24 +166,19 @@ namespace fx
if (id != MyGUI::MouseButton::Left) if (id != MyGUI::MouseButton::Left)
return; return;
auto uniform = mUniform.lock();
if (!uniform)
return;
int delta = left - mLastPointerX; int delta = left - mLastPointerX;
// allow finer tuning when shift is pressed // allow finer tuning when shift is pressed
constexpr double scaling = 20.0; constexpr double scaling = 20.0;
T step T step
= MyGUI::InputManager::getInstance().isShiftPressed() ? uniform->mStep / scaling : uniform->mStep; = MyGUI::InputManager::getInstance().isShiftPressed() ? mUniform->mStep / scaling : mUniform->mStep;
if (step == 0) if (step == 0)
{ {
if constexpr (std::is_integral_v<T>) if constexpr (std::is_integral_v<T>)
step = 1; step = 1;
else else
step = uniform->mStep; step = mUniform->mStep;
} }
if (delta > 0) if (delta > 0)
@ -218,30 +199,20 @@ namespace fx
void increment(T step) void increment(T step)
{ {
auto uniform = mUniform.lock();
if (!uniform)
return;
if constexpr (std::is_fundamental_v<UType>) if constexpr (std::is_fundamental_v<UType>)
setValue(std::clamp<T>(uniform->template getValue<UType>() + step, setValue(std::clamp<T>(mUniform->template getValue<UType>() + step,
uniform->template getMin<UType>(), uniform->template getMax<T>())); mUniform->template getMin<UType>(), mUniform->template getMax<T>()));
else else
setValue(std::clamp<T>(uniform->template getValue<UType>()[mIndex] + step, setValue(std::clamp<T>(mUniform->template getValue<UType>()[mIndex] + step,
uniform->template getMin<UType>()[mIndex], uniform->template getMax<UType>()[mIndex])); mUniform->template getMin<UType>()[mIndex], mUniform->template getMax<UType>()[mIndex]));
} }
void notifyButtonClicked(MyGUI::Widget* sender) void notifyButtonClicked(MyGUI::Widget* sender)
{ {
auto uniform = mUniform.lock();
if (!uniform)
return;
if (sender == mButtonDecrease) if (sender == mButtonDecrease)
increment(-uniform->mStep); increment(-mUniform->mStep);
else if (sender == mButtonIncrease) else if (sender == mButtonIncrease)
increment(uniform->mStep); increment(mUniform->mStep);
} }
MyGUI::Button* mButtonDecrease{ nullptr }; MyGUI::Button* mButtonDecrease{ nullptr };
@ -275,6 +246,23 @@ namespace fx
MYGUI_RTTI_DERIVED(EditNumberInt) MYGUI_RTTI_DERIVED(EditNumberInt)
}; };
class EditChoice : public EditBase, public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(EditChoice)
public:
template <class T>
void setValue(const T& value);
void setValueFromUniform() override;
void toDefault() override;
private:
void initialiseOverride() override;
void notifyComboBoxChanged(MyGUI::ComboBox* sender, size_t pos);
MyGUI::ComboBox* mChoices{ nullptr };
};
class UniformBase final : public MyGUI::Widget class UniformBase final : public MyGUI::Widget
{ {
MYGUI_RTTI_DERIVED(UniformBase) MYGUI_RTTI_DERIVED(UniformBase)

@ -451,21 +451,21 @@ To use the sampler, define the appropriately named `sampler2D` in any of your pa
It is possible to define settings for your shaders that can be adjusted by either users or a Lua script. It is possible to define settings for your shaders that can be adjusted by either users or a Lua script.
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
| Block | default | min | max | static | step | description | display_name | header | | Block | default | min | max | static | step | description | display_name | header | widget_type |
+=================+==========+==========+==========+=========+==========+==============+===================+=========+ +=================+==========+==========+==========+=========+==========+==============+===================+=========+==============+
|``uniform_bool`` | boolean | x | x | boolean | x | string | string | string | |``uniform_bool`` | boolean | x | x | boolean | x | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
|``uniform_float``| float | float | float | boolean | float | string | string | string | |``uniform_float``| float | float | float | boolean | float | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
|``uniform_int`` | integer | integer | integer | boolean | integer | string | string | string | |``uniform_int`` | integer | integer | integer | boolean | integer | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
|``uniform_vec2`` | vec2 | vec2 | vec2 | boolean | vec2 | string | string | string | |``uniform_vec2`` | vec2 | vec2 | vec2 | boolean | vec2 | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
|``uniform_vec3`` | vec3 | vec3 | vec3 | boolean | vec3 | string | string | string | |``uniform_vec3`` | vec3 | vec3 | vec3 | boolean | vec3 | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
|``uniform_vec4`` | vec4 | vec4 | vec4 | boolean | vec4 | string | string | string | |``uniform_vec4`` | vec4 | vec4 | vec4 | boolean | vec4 | string | string | string | choice(...) |
+-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+ +-----------------+----------+----------+----------+---------+----------+--------------+-------------------+---------+--------------+
The ``description`` field is used to display a toolip when viewed in the in-game HUD. The ``header`` field The ``description`` field is used to display a toolip when viewed in the in-game HUD. The ``header`` field
field can be used to organize uniforms into groups in the HUD. The ``display_name`` field can be used to create a field can be used to organize uniforms into groups in the HUD. The ``display_name`` field can be used to create a
@ -509,6 +509,21 @@ These uniform blocks must be defined with the new ``size`` parameter.
size = 10; size = 10;
} }
You may also define a dropdown list for users to select specific values from instead of the default sliders using the ``widget_type`` field.
Each item in the dropdown has an associated display name, which can be a localized string.
.. code-block:: none
uniform_int uStrength {
default = 2;
display_name = "Strength";
widget_type = choice(
"Low" = 1,
"Medium" = 2,
"High" = 3
);
}
``render_target`` ``render_target``
***************** *****************

@ -1,6 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1"> <MyGUI type="Resource" version="1.1">
<Resource type="ResourceLayout" name="MW_ValueEditChoice" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 100 50" align="Stretch" name="Root">
<Widget type="ComboBox" skin="MW_ComboBox" position_real="0 0 1 1" align="Stretch" name="Choices">
<Property key="Caption" value=""/>
<UserString key="HStretch" value="true"/>
<UserString key="VStretch" value="true"/>
</Widget>
</Widget>
</Resource>
<Resource type="ResourceLayout" name="MW_ValueEditNumber" version="3.2.0"> <Resource type="ResourceLayout" name="MW_ValueEditNumber" version="3.2.0">
<Widget type="Widget" skin="" position="0 0 100 50" align="Stretch" name="Root"> <Widget type="Widget" skin="" position="0 0 100 50" align="Stretch" name="Root">
<Widget type="Widget" skin="BlackBG" position="0 0 100 50" name="Fill" align="Stretch"> <Widget type="Widget" skin="BlackBG" position="0 0 100 50" name="Fill" align="Stretch">

Loading…
Cancel
Save