112 lines
5.8 KiB
Markdown
Raw Normal View History

2024-10-12 17:19:46 +08:00
# Delta
- **功能描述:** 设定数字输入框值改变的幅度为Delta的倍数
- **使用位置:** UPROPERTY
- **引擎模块:** Numeric Property
- **元数据类型:** float/int
- **限制类型:** float,int32
- **关联项:** [LinearDeltaSensitivity](../LinearDeltaSensitivity.md)
- **常用程度:** ★★★
设定数字输入框值改变的幅度为Delta的倍数。
## 注意的事项是:
1. 在全局使得变化值成为Delta的倍数
2. Delta默认值是0这个时候代表没有设置数字会指数改变。
3. 注意和WheelStep的区别是Delta在鼠标左右拖动和按下键盘方向键的时候生效WheelStep是只在鼠标滚轮变化的时候生效。二者虽然都是用来控制变化幅度但作用范围不同。
## 测试代码:
```cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DeltaTest)
float MyFloat_DefaultDelta = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DeltaTest, meta = (Delta = 10))
float MyFloat_Delta10 = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DeltaTest, meta = (UIMin = "0", UIMax = "1000", Delta = 10))
float MyFloat_Delta10_UIMinMax = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DeltaTest, meta = (Delta = 10, LinearDeltaSensitivity = 50))
float MyFloat_Delta10_LinearDeltaSensitivity50 = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = DeltaTest, meta = (UIMin = "0", UIMax = "1000", Delta = 10, LinearDeltaSensitivity = 50))
float MyFloat_Delta10_LinearDeltaSensitivity50_UIMinMax = 100;
```
## 测试效果:
- MyFloat_DefaultDelta ,默认情况下鼠标往右拖动变化很剧烈,变化呈指数上升。
- MyFloat_Delta10鼠标往右拖动变化也很剧烈最终到达的值也很巨大但是变化始终以Delta为步幅。
- MyFloat_Delta10_UIMinMax 限定了UIMinMax导致最大值受限但是变化其实是按照比例值线性SliderExponent默认是1没有改变
- MyFloat_Delta10_LinearDeltaSensitivity50 在没有UIMinMax的情况下且同时设置了LinearDeltaSensitivity会导致鼠标往右拖动的整个过程中变化值始终是线性。LinearDeltaSensitivity越大越不敏感。因此一次一次缓慢的改变10
- MyFloat_Delta10_LinearDeltaSensitivity50_UIMinMax 如果上面一个再加上UIMinMax则发现又失去了LinearDeltaSensitivity的效果。因为LinearDeltaSensitivity不能在有滚动条的情况下生效。
![Delta](Delta.gif)
## 原理:
- 在方向键上下左右按键的时候每次变化正负Delta但是OnKeyDown没有直接绑定所以默认情况下按键只会触发焦点的转移。
- 基础step是0.1或1如果没受到CtrlMultiplier和ShiftMultiplier的影响。
- 默认情况下鼠标左右移动改变的差量中的指数部分是FMath::Pow((double)CurrentValue, (double)SliderExponent.Get())SliderExponent默认是1也就是越往左右两端改变的幅度越大。
- 在同时设置LinearDeltaSensitivity和Delta的情况下鼠标左右移动改变的差量中的指数部分是FMath::Pow((double)Delta.Get(), (double)SliderExponent.Get()),即改变的差量在左右整个数轴上是线性一致的。
- 在最后提交值的时候改变的差量值会被规范到Delta的倍数上来。
```cpp
, _Delta(0)
virtual FReply SSpinBox<NumericType>::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override
{
if (bUnlimitedSpinRange)
{
// If this control has a specified delta and sensitivity then we use that instead of the current value for determining how much to change.
const double Sign = (MouseEvent.GetCursorDelta().X > 0) ? 1.0 : -1.0;
if (LinearDeltaSensitivity.IsSet() && LinearDeltaSensitivity.Get() != 0 && Delta.IsSet() && Delta.Get() > 0)
{
const double MouseDelta = FMath::Abs(MouseEvent.GetCursorDelta().X / (float)LinearDeltaSensitivity.Get());
NewValue = InternalValue + (Sign * MouseDelta * FMath::Pow((double)Delta.Get(), (double)SliderExponent.Get())) * Step;
}
else
{
const double MouseDelta = FMath::Abs(MouseEvent.GetCursorDelta().X / SliderWidthInSlateUnits);
const double CurrentValue = FMath::Clamp<double>(FMath::Abs(InternalValue), 1.0, (double)std::numeric_limits<NumericType>::max());
NewValue = InternalValue + (Sign * MouseDelta * FMath::Pow((double)CurrentValue, (double)SliderExponent.Get())) * Step;
}
}
}
virtual FReply SSpinBox<NumericType>::OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override
{
else if (Key == EKeys::Up || Key == EKeys::Right)
{
const NumericType LocalValueAttribute = ValueAttribute.Get();
const NumericType LocalDelta = Delta.Get();
InternalValue = (double)LocalValueAttribute;
CommitValue(LocalValueAttribute + LocalDelta, InternalValue + (double)LocalDelta, CommittedViaArrowKey, ETextCommit::OnEnter);
ExitTextMode();
return FReply::Handled();
}
else if (Key == EKeys::Down || Key == EKeys::Left)
{
const NumericType LocalValueAttribute = ValueAttribute.Get();
const NumericType LocalDelta = Delta.Get();
InternalValue = (double)LocalValueAttribute;
CommitValue(LocalValueAttribute - LocalDelta, InternalValue + (double)LocalDelta, CommittedViaArrowKey, ETextCommit::OnEnter);
ExitTextMode();
return FReply::Handled();
}
}
void SSpinBox<NumericType>::CommitValue(NumericType NewValue, double NewSpinValue, ECommitMethod CommitMethod, ETextCommit::Type OriginalCommitInfo)
{
// 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
}
}
}
```