UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SVectorInputBox.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
6#include "Layout/Margin.h"
11#include "Widgets/SWidget.h"
14#include "Styling/CoreStyle.h"
16
17#include <type_traits>
18
20class SHorizontalBox;
21
25template<typename NumericType, typename VectorType = UE::Math::TVector<NumericType>, int32 NumberOfComponents = 3>
27{
28public:
31
34
37
40
42 DECLARE_DELEGATE_ThreeParams(FOnConstrainVector, int32 /* Component */, VectorType /* old */ , VectorType& /* new */);
43
44 struct FArguments;
45
46private:
48
49 struct FVectorXArgumentsEmpty {};
50 template<typename ArgumentType>
51 struct FVectorXArguments : FVectorXArgumentsEmpty
52 {
53 using WidgetArgsType = ArgumentType;
54
55 FORCENOINLINE FVectorXArguments()
57 , _XDisplayName(NSLOCTEXT("SVectorInputBox", "X_DisplayName", "X"))
58 {
59 if constexpr (NumberOfComponents == 3)
60 {
62 {
64 }
65 }
67 }
68
71
72
74
75
77
78
80
81
83
84
86
87
89
90
92
93
95
97 };
98
99 struct FVectorYArgumentsEmpty {};
100 template<typename ArgumentType>
101 struct FVectorYArguments : FVectorYArgumentsEmpty
102 {
103 using WidgetArgsType = ArgumentType;
104
105 FORCENOINLINE FVectorYArguments()
107 , _YDisplayName(NSLOCTEXT("SVectorInputBox", "Y_DisplayName", "Y"))
108 {
109 if constexpr (NumberOfComponents == 3)
110 {
112 {
114 }
115 }
117 }
118
121
122
124
125
127
128
130
131
133
134
136
137
139
140
142
143
145
147 };
148
149 struct FVectorZArgumentsEmpty {};
150 template<typename ArgumentType>
151 struct FVectorZArguments : FVectorZArgumentsEmpty
152 {
153 using WidgetArgsType = ArgumentType;
154
155 FORCENOINLINE FVectorZArguments()
157 , _ZDisplayName(NSLOCTEXT("SVectorInputBox", "Z_DisplayName", "Z"))
158 {
159 if constexpr (NumberOfComponents == 3)
160 {
162 {
164 }
165 }
167 }
168
171
172
174
175
177
178
180
181
183
184
186
187
189
190
192
193
195
197 };
198
199 struct FVectorWArgumentsEmpty {};
200 template<typename ArgumentType>
201 struct FVectorWArguments : FVectorWArgumentsEmpty
202 {
203 using WidgetArgsType = ArgumentType;
204
205 FORCENOINLINE FVectorWArguments()
207 , _WDisplayName(NSLOCTEXT("SVectorInputBox", "W_DisplayName", "W"))
208 {
209 if constexpr (NumberOfComponents >= 4)
210 {
212 }
213 }
214
217
218
220
221
223
224
226
227
229
230
232
233
235
236
238
239
241
243 };
244
245public:
246 //SLATE_BEGIN_ARGS(SNumericVectorInputBox<NumericType>)
247 struct FArguments : public TSlateBaseNamedArgs<ThisClass>
248 , std::conditional<NumberOfComponents >= 1, FVectorXArguments<FArguments>, FVectorXArgumentsEmpty>::type
249 , std::conditional<NumberOfComponents >= 2, FVectorYArguments<FArguments>, FVectorYArgumentsEmpty>::type
250 , std::conditional<NumberOfComponents >= 3, FVectorZArguments<FArguments>, FVectorZArgumentsEmpty>::type
251 , std::conditional<NumberOfComponents >= 4, FVectorWArguments<FArguments>, FVectorWArgumentsEmpty>::type
252 {
253 typedef FArguments WidgetArgsType;
254 FORCENOINLINE FArguments()
255 : _EditableTextBoxStyle( &FAppStyle::Get().GetWidgetStyle<FEditableTextBoxStyle>("NormalEditableTextBox") )
256 , _SpinBoxStyle(&FAppStyle::Get().GetWidgetStyle<FSpinBoxStyle>("NumericEntrySpinBox") )
257 , _Font(FAppStyle::Get().GetFontStyle("NormalFont"))
259 , _SpinDelta(1)
262 , _Swizzle(FIntVector4(0, 1, 2, 3))
264 , _TogglePadding(FMargin(1.f,0.f,1.f,0.f) )
266 {}
267
270
271
273
274
276
277
279
280
282
283
285
286
288
289
290 SLATE_STYLE_ARGUMENT( FEditableTextBoxStyle, EditableTextBoxStyle )
291
292
293 SLATE_STYLE_ARGUMENT( FSpinBoxStyle, SpinBoxStyle )
294
295
297
298
300
301
302 SLATE_ATTRIBUTE( NumericType, SpinDelta )
303
304
305 SLATE_ATTRIBUTE( int32, LinearDeltaSensitivity )
306
307
309
310
312
313
314 SLATE_EVENT( FSimpleDelegate, OnBeginSliderMovement )
315
316
317 SLATE_EVENT( FOnNumericValueChanged, OnEndSliderMovement )
318
319
321
322
324
325
327
328
330
331
332 SLATE_ARGUMENT(bool, PreventThrottling)
333 }; // SLATE_END_ARGS()
334
335
341 void Construct(const FArguments& InArgs)
342 {
343 bUseVectorGetter = true;
344
346
348 [
349 HorizontalBox
350 ];
351
352 VectorAttribute = InArgs._Vector;
353 OnVectorValueChanged = InArgs._OnVectorChanged;
354 OnVectorValueCommitted = InArgs._OnVectorCommitted;
355
356 if(!VectorAttribute.IsBound() && !VectorAttribute.IsSet())
357 {
358 bUseVectorGetter = false;
359
361 {
362 if constexpr (NumberOfComponents == 2)
363 {
364 TOptional<NumericType> X = InArgs._X.Get();
365 TOptional<NumericType> Y = InArgs._Y.Get();
366 if(X.IsSet() && Y.IsSet())
367 {
368 return VectorType(X.GetValue(), Y.GetValue());
369 }
370 }
371 if constexpr (NumberOfComponents == 3)
372 {
373 TOptional<NumericType> X = InArgs._X.Get();
374 TOptional<NumericType> Y = InArgs._Y.Get();
375 TOptional<NumericType> Z = InArgs._Z.Get();
376 if(X.IsSet() && Y.IsSet() && Z.IsSet())
377 {
378 return VectorType(X.GetValue(), Y.GetValue(), Z.GetValue());
379 }
380 }
381 if constexpr (NumberOfComponents == 4)
382 {
383 TOptional<NumericType> X = InArgs._X.Get();
384 TOptional<NumericType> Y = InArgs._Y.Get();
385 TOptional<NumericType> Z = InArgs._Z.Get();
386 TOptional<NumericType> W = InArgs._W.Get();
387 if(X.IsSet() && Y.IsSet() && Z.IsSet() && W.IsSet())
388 {
389 return VectorType(X.GetValue(), Y.GetValue(), Z.GetValue(), W.GetValue());
390 }
391 }
392
393 return TOptional<VectorType>();
394 });
395 }
396
397 if(!OnVectorValueChanged.IsBound())
398 {
399 OnVectorValueChanged = FOnVectorValueChanged::CreateLambda([InArgs](VectorType Vector)
400 {
401 if constexpr (NumberOfComponents >= 1)
402 {
403 InArgs._OnXChanged.ExecuteIfBound(Vector.X);
404 }
405 if constexpr (NumberOfComponents >= 2)
406 {
407 InArgs._OnYChanged.ExecuteIfBound(Vector.Y);
408 }
409 if constexpr (NumberOfComponents >= 3)
410 {
411 InArgs._OnZChanged.ExecuteIfBound(Vector.Z);
412 }
413 if constexpr (NumberOfComponents >= 4)
414 {
415 InArgs._OnWChanged.ExecuteIfBound(Vector.W);
416 }
417 });
418 }
419 if(!OnVectorValueCommitted.IsBound())
420 {
421 OnVectorValueCommitted = FOnVectorValueCommitted::CreateLambda([InArgs](VectorType Vector, ETextCommit::Type CommitType)
422 {
423 if constexpr (NumberOfComponents >= 1)
424 {
425 InArgs._OnXCommitted.ExecuteIfBound(Vector.X, CommitType);
426 }
427 if constexpr (NumberOfComponents >= 2)
428 {
429 InArgs._OnYCommitted.ExecuteIfBound(Vector.Y, CommitType);
430 }
431 if constexpr (NumberOfComponents >= 3)
432 {
433 InArgs._OnZCommitted.ExecuteIfBound(Vector.Z, CommitType);
434 }
435 if constexpr (NumberOfComponents >= 4)
436 {
437 InArgs._OnWCommitted.ExecuteIfBound(Vector.W, CommitType);
438 }
439 });
440 }
441
442 using ComponentConstructorFn = void (ThisClass::*)(const FArguments&, TSharedRef<SHorizontalBox>);
444
445 if constexpr (NumberOfComponents >= 1)
446 {
447 ComponentConstructors[0] = ComponentConstructorFn(&ThisClass::ConstructX);
448 }
449 if constexpr (NumberOfComponents >= 2)
450 {
451 ComponentConstructors[1] = ComponentConstructorFn(&ThisClass::ConstructY);
452 }
453 if constexpr (NumberOfComponents >= 3)
454 {
455 ComponentConstructors[2] = ComponentConstructorFn(&ThisClass::ConstructZ);
456 }
457 if constexpr (NumberOfComponents >= 4)
458 {
459 ComponentConstructors[3] = ComponentConstructorFn(&ThisClass::ConstructW);
460 }
461
462 // Call the widget construction functions in swizzle order
463 for (int32 ComponentIndex = 0; ComponentIndex < NumberOfComponents; ++ComponentIndex)
464 {
465 int32 ConstructorIndex = InArgs._Swizzle[ComponentIndex];
466 if (ensureMsgf(ConstructorIndex < NumberOfComponents, TEXT("Invalid swizzle index (%d >= %d)"), ConstructorIndex, NumberOfComponents))
467 {
468 (this->*ComponentConstructors[ConstructorIndex])(InArgs, HorizontalBox);
469 }
470 }
471 }
472
473private:
477 void ConstructComponent(int32 ComponentIndex,
478 const FArguments& InArgs,
479 const TAttribute<FLinearColor>& LabelColor,
481 TSharedRef<SHorizontalBox>& HorizontalBox,
490 {
492 if (InArgs._bColorAxisLabels)
493 {
495 }
496
498 if (ComponentDisplayName.IsSet())
499 {
500 ToolTipTextFormatString.Append(FText::Format(NSLOCTEXT("SVectorInputBox", "ToolTipTextFormatDisplayName", "{0}: "), ComponentDisplayName.Get()).ToString());
501 }
503
505
506 // any other getter below can use the vector
508
509 HorizontalBox->AddSlot()
510 [
512 .AllowSpin(InArgs._AllowSpin)
513 .EditableTextBoxStyle(InArgs._EditableTextBoxStyle)
514 .SpinBoxStyle(InArgs._SpinBoxStyle)
515 .Font(InArgs._Font)
516 .Value(Value)
517 .OnValueChanged(CreatePerComponentChanged(ComponentIndex, OnComponentChanged, InArgs._ConstrainVector))
518 .OnValueCommitted(CreatePerComponentCommitted(ComponentIndex, OnComponentCommitted, InArgs._ConstrainVector))
520 .UndeterminedString(NSLOCTEXT("SVectorInputBox", "MultipleValues", "Multiple Values"))
521 .ContextMenuExtender(OnContextMenuExtenderComponent)
522 .TypeInterface(InArgs._TypeInterface)
523 .MinFractionalDigits(InArgs._TypeInterface ? InArgs._TypeInterface->GetMinFractionalDigits() : TOptional<int32>())
524 .MaxFractionalDigits(InArgs._TypeInterface ? InArgs._TypeInterface->GetMaxFractionalDigits() : TOptional<int32>())
525 .MinValue(CreatePerComponentGetter(ComponentIndex, TOptional<NumericType>(), InArgs._MinVector))
526 .MaxValue(CreatePerComponentGetter(ComponentIndex, TOptional<NumericType>(), InArgs._MaxVector))
527 .MinSliderValue(CreatePerComponentGetter(ComponentIndex, TOptional<NumericType>(), InArgs._MinSliderVector))
528 .MaxSliderValue(CreatePerComponentGetter(ComponentIndex, TOptional<NumericType>(), InArgs._MaxSliderVector))
530 .Delta(InArgs._SpinDelta)
531 .OnBeginSliderMovement(CreatePerComponentSliderMovementEvent(InArgs._OnBeginSliderMovement, OnComponentBeginSliderMovement))
532 .OnEndSliderMovement(CreatePerComponentSliderMovementEvent<FOnNumericValueChanged, NumericType>(InArgs._OnEndSliderMovement, OnComponentEndSliderMovement))
533 .LabelPadding(FMargin(3.f))
534 .LabelLocation(SNumericEntryBox<NumericType>::ELabelLocation::Inside)
535 .Label()
536 [
537 LabelWidget
538 ]
543 .PreventThrottling(InArgs._PreventThrottling)
544 ];
545 }
546
550 void ConstructX(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
551 {
553 InArgs,
554 InArgs._XColor,
555 InArgs._XDisplayName,
556 HorizontalBox,
557 InArgs._X,
558 InArgs._OnXChanged,
559 InArgs._OnXCommitted,
560 InArgs._ToggleXChecked,
561 InArgs._OnToggleXChanged,
562 InArgs._ContextMenuExtenderX,
563 InArgs._OnXBeginSliderMovement,
564 InArgs._OnXEndSliderMovement
565 );
566 }
567
571 void ConstructY(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
572 {
574 InArgs,
575 InArgs._YColor,
576 InArgs._YDisplayName,
577 HorizontalBox,
578 InArgs._Y,
579 InArgs._OnYChanged,
580 InArgs._OnYCommitted,
581 InArgs._ToggleYChecked,
582 InArgs._OnToggleYChanged,
583 InArgs._ContextMenuExtenderY,
584 InArgs._OnYBeginSliderMovement,
585 InArgs._OnYEndSliderMovement
586 );
587 }
588
592 void ConstructZ(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
593 {
595 InArgs,
596 InArgs._ZColor,
597 InArgs._ZDisplayName,
598 HorizontalBox,
599 InArgs._Z,
600 InArgs._OnZChanged,
601 InArgs._OnZCommitted,
602 InArgs._ToggleZChecked,
603 InArgs._OnToggleZChanged,
604 InArgs._ContextMenuExtenderZ,
605 InArgs._OnZBeginSliderMovement,
606 InArgs._OnZEndSliderMovement
607 );
608 }
609
613 void ConstructW(const FArguments& InArgs, TSharedRef<SHorizontalBox> HorizontalBox)
614 {
616 InArgs,
617 InArgs._WColor,
618 InArgs._WDisplayName,
619 HorizontalBox,
620 InArgs._W,
621 InArgs._OnWChanged,
622 InArgs._OnWCommitted,
623 InArgs._ToggleWChecked,
624 InArgs._OnToggleWChanged,
625 InArgs._ContextMenuExtenderW,
626 InArgs._OnWBeginSliderMovement,
627 InArgs._OnWEndSliderMovement
628 );
629 }
630
631 /*
632 * Creates a lambda to retrieve a component off a vector
633 */
635 int32 ComponentIndex,
638 {
639 if(bUseVectorGetter && (Vector.IsBound() || Vector.IsSet()))
640 {
641 return TAttribute<TOptional<NumericType>>::CreateLambda(
642 [ComponentIndex, Component, Vector]() -> TOptional<NumericType>
643 {
645 if(OptionalVectorValue.IsSet())
646 {
647 return OptionalVectorValue.GetValue()[ComponentIndex];
648 }
649 return Component.Get();
650 });
651 }
652 return Component;
653 }
654
655 /*
656 * Creates a lambda to react to a change event
657 */
659 int32 ComponentIndex,
662 {
663 if(ConstrainVector.IsBound() && OnVectorValueChanged.IsBound())
664 {
665 return FOnNumericValueChanged::CreateLambda(
666 [ComponentIndex, OnComponentChanged, this, ConstrainVector](NumericType InValue)
667 {
669 if(OptionalVectorValue.IsSet())
670 {
671 VectorType VectorValue = OptionalVectorValue.GetValue();
672 VectorValue[ComponentIndex] = InValue;
673
674 ConstrainVector.ExecuteIfBound(ComponentIndex, OptionalVectorValue.GetValue(), VectorValue);
675 OnVectorValueChanged.Execute(VectorValue);
676 }
677 else
678 {
679 OnComponentChanged.ExecuteIfBound(InValue);
680 }
681 });
682 }
683 return OnComponentChanged;
684 }
685
686 /*
687 * Creates a lambda to react to a commit event
688 */
690 int32 ComponentIndex,
693 {
694 if(ConstrainVector.IsBound() && OnVectorValueCommitted.IsBound())
695 {
696 return FOnNumericValueCommitted::CreateLambda(
697 [ComponentIndex, OnComponentCommitted, this, ConstrainVector](NumericType InValue, ETextCommit::Type CommitType)
698 {
700 if(OptionalVectorValue.IsSet())
701 {
702 VectorType VectorValue = OptionalVectorValue.GetValue();
703 VectorValue[ComponentIndex] = InValue;
704
705 if(ConstrainVector.IsBound())
706 {
707 ConstrainVector.Execute(ComponentIndex, OptionalVectorValue.GetValue(), VectorValue);
708 }
709
711 }
712 else
713 {
714 OnComponentCommitted.ExecuteIfBound(InValue, CommitType);
715 }
716 });
717 }
719 }
720
724 template<typename EventType, typename... ArgsType>
725 EventType CreatePerComponentSliderMovementEvent(
726 const EventType OnSliderMovement,
727 const EventType OnComponentSliderMovement)
728 {
729 if(OnSliderMovement.IsBound())
730 {
731 return EventType::CreateLambda(
733 {
734 OnSliderMovement.ExecuteIfBound(Args...);
735 OnComponentSliderMovement.ExecuteIfBound(Args...);
736 });
737 }
739 }
740
741 bool bUseVectorGetter = true;
745};
746
751
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define SLATE_STYLE_ARGUMENT(ArgType, ArgName)
Definition DeclarativeSyntaxSupport.h:280
#define SNew(WidgetType,...)
Definition DeclarativeSyntaxSupport.h:37
#define SLATE_ATTRIBUTE(AttrType, AttrName)
Definition DeclarativeSyntaxSupport.h:192
#define SLATE_EVENT(DelegateName, EventName)
Definition DeclarativeSyntaxSupport.h:458
#define SLATE_ARGUMENT(ArgType, ArgName)
Definition DeclarativeSyntaxSupport.h:208
#define X(Name, Desc)
Definition FormatStringSan.h:47
#define NSLOCTEXT(InNamespace, InKey, InTextLiteral)
Definition Internationalization.h:300
FVector MaxVector(const FVector &VectorA, const FVector &VectorB)
Definition PhysicsFieldComponent.cpp:172
FVector MinVector(const FVector &VectorA, const FVector &VectorB)
Definition PhysicsFieldComponent.cpp:167
void Construct(const FArguments &InArgs)
ECheckBoxState
Definition SlateTypes.h:65
Definition AppStyle.h:24
Definition ArrangedChildren.h:15
Definition Text.h:385
static CORE_API FText FromString(const ANSICHAR *String)
Definition Text.cpp:1081
static CORE_API FText Format(FTextFormat Fmt, const FFormatNamedArguments &InArguments)
Definition Text.cpp:469
CORE_API const FString & ToString() const
Definition Text.cpp:1263
Definition SCompoundWidget.h:22
FCompoundWidgetOneChildSlot ChildSlot
Definition SCompoundWidget.h:113
Definition SBoxPanel.h:171
static SLATECORE_API TSharedRef< class SWidget > NullWidget
Definition SNullWidget.h:22
Definition SNumericEntryBox.h:37
static TSharedRef< SWidget > BuildNarrowColorLabel(FLinearColor LabelColor)
Definition SNumericEntryBox.h:458
Definition SVectorInputBox.h:27
DECLARE_DELEGATE_TwoParams(FOnVectorValueCommitted, VectorType, ETextCommit::Type)
DECLARE_DELEGATE_ThreeParams(FOnConstrainVector, int32, VectorType, VectorType &)
DECLARE_DELEGATE_OneParam(FOnNumericValueChanged, NumericType)
DECLARE_DELEGATE_OneParam(FOnVectorValueChanged, VectorType)
DECLARE_DELEGATE_TwoParams(FOnNumericValueCommitted, NumericType, ETextCommit::Type)
Definition Attribute.h:17
const ObjectType & Get() const
Definition Attribute.h:241
Definition SharedPointer.h:692
Definition SharedPointer.h:153
Definition StaticArray.h:26
BuilderType & Append(const OtherCharType *const String, const int32 Length)
Definition StringBuilder.h:238
Definition StringBuilder.h:509
CORE_API bool UseForwardRightUpDisplayNames()
Definition AxisDisplayInfo.cpp:122
CORE_API FText GetAxisDisplayName(EAxisList::Type Axis)
Definition AxisDisplayInfo.cpp:22
CORE_API FLinearColor GetAxisColor(EAxisList::Type Axis)
Definition AxisDisplayInfo.cpp:96
@ X
Definition Axis.h:26
@ Y
Definition Axis.h:27
@ Z
Definition Axis.h:28
Type
Definition SlateEnums.h:291
constexpr int32 MaxValue
Definition LandscapeDataAccess.h:26
FORCEINLINE T * Get(const FObjectPtr &ObjectPtr)
Definition ObjectPtr.h:426
constexpr double MinValue(bool OnlyInside)
Definition Geometry.cpp:53
@ Inside
Definition GeoEnum.h:90
@ LinearDeltaSensitivity
Definition ObjectMacros.h:1422
@ false
Definition radaudio_common.h:23
Definition SlateTypes.h:1019
Definition Color.h:48
Definition Margin.h:17
Definition SlateFontInfo.h:147
Definition SlateTypes.h:1489
Definition NumericTypeInterface.h:21
Definition UnrealTemplate.h:341
Definition Optional.h:131
constexpr OptionalType & GetValue()
Definition Optional.h:443
constexpr bool IsSet() const
Definition Optional.h:69
constexpr const OptionalType & Get(const OptionalType &DefaultValue UE_LIFETIMEBOUND) const UE_LIFETIMEBOUND
Definition Optional.h:472
Definition DeclarativeSyntaxSupport.h:681