vault backup: 2024-10-12 17:19:45
This commit is contained in:
Binary file not shown.
After Width: | Height: | Size: 323 KiB |
@@ -0,0 +1,146 @@
|
||||
# UIMin
|
||||
|
||||
- **功能描述:** 指定数字输入框上滚动条拖动的最小范围值
|
||||
- **使用位置:** UPROPERTY
|
||||
- **引擎模块:** Numeric Property
|
||||
- **元数据类型:** float/int
|
||||
- **限制类型:** float,int32
|
||||
- **关联项:** [UIMax](../UIMax.md), [ClampMin](../ClampMin.md), [ClampMax](../ClampMax.md)
|
||||
- **常用程度:** ★★★★★
|
||||
|
||||
UIMin-UIMax和ClampMin-ClampMax的区别是,UI系列阻止用户在拖动鼠标的时候把值超过某个范围,但是用户依然可以手动输入超过这个范围的值。而Clamp系列是实际的值的范围限制,用户拖动或者手动输入值都不允许超过这个范围。
|
||||
|
||||
这两个限制都无法限制蓝图下直接修改值。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MinMaxTest)
|
||||
float MyFloat_NoMinMax = 100;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MinMaxTest, meta = (UIMin = "0", UIMax = "100"))
|
||||
float MyFloat_HasMinMax_UI = 100;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MinMaxTest, meta = (ClampMin = "0", ClampMax = "100"))
|
||||
float MyFloat_HasMinMax_Clamp = 100;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MinMaxTest, meta = (ClampMin = "0", ClampMax = "100",UIMin = "20", UIMax = "50"))
|
||||
float MyFloat_HasMinMax_ClampAndUI = 100;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MinMaxTest, meta = (ClampMin = "20", ClampMax = "50",UIMin = "0", UIMax = "100"))
|
||||
float MyFloat_HasMinMax_ClampAndUI2= 100;
|
||||
```
|
||||
|
||||
## 测试效果:
|
||||
|
||||
- 从MyFloat_HasMinMax_UI发现,UIMin, UIMax限制数字输入框滚动条的范围,但依然可以手动输入超过的值999
|
||||
- 从MyFloat_HasMinMax_Clamp 发现,ClampMin,ClampMax 会同时限制UI和手动输入的范围。
|
||||
- 从MyFloat_HasMinMax_ClampAndUI和MyFloat_HasMinMax_ClampAndUI2发现,UI的滚动条会取UI的限制和Clamp限制的更窄范围,而实际输入值也是会被限制在更窄的范围内。
|
||||
|
||||

|
||||
|
||||
## 原理:
|
||||
|
||||
TNumericPropertyParams在构造的时候就会取得一些meta来初始化这些变量。否则就会成为默认值。
|
||||
|
||||
数值类型有实际的最小最大值(MinValue-MaxValue),是由ClampMin和ClampMax提供的。也有UI上的最小最大值(MinSliderValue-MaxSliderValue),是由Max(UImin,ClampMin)和Min(UIMax,ClampMax)提供的,即取最小的范围来保障合法输入。
|
||||
|
||||
```cpp
|
||||
template<typename NumericType>
|
||||
struct TNumericPropertyParams
|
||||
{
|
||||
if (MetaDataGetter.IsBound())
|
||||
{
|
||||
UIMinString = MetaDataGetter.Execute("UIMin");
|
||||
UIMaxString = MetaDataGetter.Execute("UIMax");
|
||||
SliderExponentString = MetaDataGetter.Execute("SliderExponent");
|
||||
LinearDeltaSensitivityString = MetaDataGetter.Execute("LinearDeltaSensitivity");
|
||||
DeltaString = MetaDataGetter.Execute("Delta");
|
||||
ClampMinString = MetaDataGetter.Execute("ClampMin");
|
||||
ClampMaxString = MetaDataGetter.Execute("ClampMax");
|
||||
ForcedUnits = MetaDataGetter.Execute("ForceUnits");
|
||||
WheelStepString = MetaDataGetter.Execute("WheelStep");
|
||||
}
|
||||
|
||||
TOptional<NumericType> MinValue;
|
||||
TOptional<NumericType> MaxValue;
|
||||
TOptional<NumericType> MinSliderValue;
|
||||
TOptional<NumericType> MaxSliderValue;
|
||||
NumericType SliderExponent;
|
||||
NumericType Delta;
|
||||
int32 LinearDeltaSensitivity;
|
||||
TOptional<NumericType> WheelStep;
|
||||
}
|
||||
//最终这些值会传输给
|
||||
SAssignNew(SpinBox, SSpinBox<NumericType>)
|
||||
.Style(InArgs._SpinBoxStyle)
|
||||
.Font(InArgs._Font.IsSet() ? InArgs._Font : InArgs._EditableTextBoxStyle->TextStyle.Font)
|
||||
.Value(this, &SNumericEntryBox<NumericType>::OnGetValueForSpinBox)
|
||||
.Delta(InArgs._Delta)
|
||||
.ShiftMultiplier(InArgs._ShiftMultiplier)
|
||||
.CtrlMultiplier(InArgs._CtrlMultiplier)
|
||||
.LinearDeltaSensitivity(InArgs._LinearDeltaSensitivity)
|
||||
.SupportDynamicSliderMaxValue(InArgs._SupportDynamicSliderMaxValue)
|
||||
.SupportDynamicSliderMinValue(InArgs._SupportDynamicSliderMinValue)
|
||||
.OnDynamicSliderMaxValueChanged(InArgs._OnDynamicSliderMaxValueChanged)
|
||||
.OnDynamicSliderMinValueChanged(InArgs._OnDynamicSliderMinValueChanged)
|
||||
.OnValueChanged(OnValueChanged)
|
||||
.OnValueCommitted(OnValueCommitted)
|
||||
.MinFractionalDigits(MinFractionalDigits)
|
||||
.MaxFractionalDigits(MaxFractionalDigits)
|
||||
.MinSliderValue(InArgs._MinSliderValue)
|
||||
.MaxSliderValue(InArgs._MaxSliderValue)
|
||||
.MaxValue(InArgs._MaxValue)
|
||||
.MinValue(InArgs._MinValue)
|
||||
.SliderExponent(InArgs._SliderExponent)
|
||||
.SliderExponentNeutralValue(InArgs._SliderExponentNeutralValue)
|
||||
.EnableWheel(InArgs._AllowWheel)
|
||||
.BroadcastValueChangesPerKey(InArgs._BroadcastValueChangesPerKey)
|
||||
.WheelStep(InArgs._WheelStep)
|
||||
.OnBeginSliderMovement(InArgs._OnBeginSliderMovement)
|
||||
.OnEndSliderMovement(InArgs._OnEndSliderMovement)
|
||||
.MinDesiredWidth(InArgs._MinDesiredValueWidth)
|
||||
.TypeInterface(Interface)
|
||||
.ToolTipText(this, &SNumericEntryBox<NumericType>::GetValueAsText);
|
||||
|
||||
|
||||
//最后
|
||||
void SSpinBox<NumericType>::CommitValue(NumericType NewValue, double NewSpinValue, ECommitMethod CommitMethod, ETextCommit::Type OriginalCommitInfo)
|
||||
{
|
||||
if (CommitMethod == CommittedViaSpin || CommitMethod == CommittedViaArrowKey)
|
||||
{
|
||||
const NumericType LocalMinSliderValue = GetMinSliderValue();
|
||||
const NumericType LocalMaxSliderValue = GetMaxSliderValue();
|
||||
NewValue = FMath::Clamp<NumericType>(NewValue, LocalMinSliderValue, LocalMaxSliderValue);
|
||||
NewSpinValue = FMath::Clamp<double>(NewSpinValue, (double)LocalMinSliderValue, (double)LocalMaxSliderValue);
|
||||
}
|
||||
|
||||
{
|
||||
const NumericType LocalMinValue = GetMinValue();
|
||||
const NumericType LocalMaxValue = GetMaxValue();
|
||||
NewValue = FMath::Clamp<NumericType>(NewValue, LocalMinValue, LocalMaxValue);
|
||||
NewSpinValue = FMath::Clamp<double>(NewSpinValue, (double)LocalMinValue, (double)LocalMaxValue);
|
||||
}
|
||||
|
||||
// Update the internal value, this needs to be done before rounding.
|
||||
InternalValue = NewSpinValue;
|
||||
|
||||
const bool bAlwaysUsesDeltaSnap = GetAlwaysUsesDeltaSnap();
|
||||
// If needed, round this value to the delta. Internally the value is not held to the Delta but externally it appears to be.
|
||||
if (CommitMethod == CommittedViaSpin || CommitMethod == CommittedViaArrowKey || bAlwaysUsesDeltaSnap)
|
||||
{
|
||||
NumericType CurrentDelta = Delta.Get();
|
||||
if (CurrentDelta != NumericType())
|
||||
{
|
||||
NewValue = FMath::GridSnap<NumericType>(NewValue, CurrentDelta); // snap numeric point value to nearest Delta
|
||||
}
|
||||
}
|
||||
|
||||
// Update the max slider value based on the current value if we're in dynamic mode
|
||||
if (SupportDynamicSliderMaxValue.Get() && ValueAttribute.Get() > GetMaxSliderValue())
|
||||
{
|
||||
ApplySliderMaxValueChanged(float(ValueAttribute.Get() - GetMaxSliderValue()), true);
|
||||
}
|
||||
else if (SupportDynamicSliderMinValue.Get() && ValueAttribute.Get() < GetMinSliderValue())
|
||||
{
|
||||
ApplySliderMinValueChanged(float(ValueAttribute.Get() - GetMinSliderValue()), true);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
Reference in New Issue
Block a user