224 lines
6.0 KiB
C++
224 lines
6.0 KiB
C++
#include "MatrixInputWidget.h"
|
|
#include "SlateOptMacros.h"
|
|
#include "Widgets/Layout/SUniformGridPanel.h"
|
|
#include "Widgets/Text/STextBlock.h"
|
|
#include "Widgets/Input/SButton.h"
|
|
#include "Widgets/Layout/SBox.h"
|
|
#include "Widgets/Layout/SScrollBox.h"
|
|
#include "EditorStyleSet.h"
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
void SMatrixInputWidget::Construct(const FArguments& InArgs)
|
|
{
|
|
Matrix = InArgs._Matrix;
|
|
OnMatrixChanged = InArgs._OnMatrixChanged;
|
|
|
|
// Create a grid panel for the matrix elements
|
|
GridPanel = SNew(SGridPanel);
|
|
|
|
// Create numeric entry boxes for each matrix element
|
|
NumericEntryBoxes.SetNum(16); // 4x4 matrix
|
|
|
|
// Add labels for rows and columns
|
|
for (int32 Col = 0; Col < 4; ++Col)
|
|
{
|
|
GridPanel->AddSlot(Col + 1, 0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(FText::FromString("Column {0}"), FText::AsNumber(Col)))
|
|
.Margin(FMargin(5.0f))
|
|
];
|
|
}
|
|
|
|
for (int32 Row = 0; Row < 4; ++Row)
|
|
{
|
|
GridPanel->AddSlot(0, Row + 1)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::Format(FText::FromString("Row {0}"), FText::AsNumber(Row)))
|
|
.Margin(FMargin(5.0f))
|
|
];
|
|
}
|
|
|
|
// Add numeric entry boxes for each matrix element
|
|
for (int32 Row = 0; Row < 4; ++Row)
|
|
{
|
|
for (int32 Col = 0; Col < 4; ++Col)
|
|
{
|
|
TSharedPtr<SNumericEntryBox<float>> NumericEntryBox = CreateMatrixElementWidget(Row, Col);
|
|
NumericEntryBoxes[Row * 4 + Col] = NumericEntryBox;
|
|
|
|
GridPanel->AddSlot(Col + 1, Row + 1)
|
|
[
|
|
SNew(SBox)
|
|
.WidthOverride(80.0f)
|
|
.Padding(FMargin(2.0f))
|
|
[
|
|
NumericEntryBox.ToSharedRef()
|
|
]
|
|
];
|
|
}
|
|
}
|
|
|
|
// Create buttons for common operations
|
|
TSharedPtr<SUniformGridPanel> ButtonPanel = SNew(SUniformGridPanel)
|
|
.SlotPadding(FMargin(2.0f));
|
|
|
|
ButtonPanel->AddSlot(0, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(FText::FromString("Reset to Identity"))
|
|
.ToolTipText(FText::FromString("Reset the matrix to identity"))
|
|
.OnClicked(FOnClicked::CreateLambda([this]()
|
|
{
|
|
ResetToIdentity();
|
|
return FReply::Handled();
|
|
}))
|
|
];
|
|
|
|
ButtonPanel->AddSlot(1, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(FText::FromString("Set from Rotation"))
|
|
.ToolTipText(FText::FromString("Set the matrix from rotation values (degrees)"))
|
|
.OnClicked(FOnClicked::CreateLambda([this]()
|
|
{
|
|
SetFromEulerAngles(0.0f, 0.0f, 0.0f);
|
|
return FReply::Handled();
|
|
}))
|
|
];
|
|
|
|
ButtonPanel->AddSlot(2, 0)
|
|
[
|
|
SNew(SButton)
|
|
.Text(FText::FromString("Set from Translation"))
|
|
.ToolTipText(FText::FromString("Set the matrix from translation values"))
|
|
.OnClicked(FOnClicked::CreateLambda([this]()
|
|
{
|
|
SetFromTranslation(FVector::ZeroVector);
|
|
return FReply::Handled();
|
|
}))
|
|
];
|
|
|
|
// Main widget layout
|
|
ChildSlot
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(5.0f)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromString("Matrix Input"))
|
|
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 14))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.FillHeight(1.0f)
|
|
.Padding(5.0f)
|
|
[
|
|
SNew(SScrollBox)
|
|
+ SScrollBox::Slot()
|
|
[
|
|
GridPanel.ToSharedRef()
|
|
]
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(5.0f)
|
|
[
|
|
ButtonPanel.ToSharedRef()
|
|
]
|
|
];
|
|
|
|
// Update the UI with the initial matrix value
|
|
UpdateUI();
|
|
}
|
|
|
|
void SMatrixInputWidget::SetMatrix(const FMatrix& InMatrix)
|
|
{
|
|
Matrix = InMatrix;
|
|
UpdateUI();
|
|
|
|
// Notify listeners of the change
|
|
if (OnMatrixChanged.IsBound())
|
|
{
|
|
OnMatrixChanged.Execute(Matrix);
|
|
}
|
|
}
|
|
|
|
FMatrix SMatrixInputWidget::GetMatrix() const
|
|
{
|
|
return Matrix;
|
|
}
|
|
|
|
void SMatrixInputWidget::ResetToIdentity()
|
|
{
|
|
SetMatrix(FMatrix::Identity);
|
|
}
|
|
|
|
void SMatrixInputWidget::SetFromEulerAngles(float Roll, float Pitch, float Yaw)
|
|
{
|
|
FRotator Rotator(Pitch, Yaw, Roll);
|
|
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
|
|
SetMatrix(RotationMatrix);
|
|
}
|
|
|
|
void SMatrixInputWidget::SetFromTranslation(const FVector& Translation)
|
|
{
|
|
FMatrix TranslationMatrix = FMatrix::Identity;
|
|
TranslationMatrix.SetOrigin(Translation);
|
|
SetMatrix(TranslationMatrix);
|
|
}
|
|
|
|
void SMatrixInputWidget::SetFromTransform(const FTransform& Transform)
|
|
{
|
|
SetMatrix(Transform.ToMatrixWithScale());
|
|
}
|
|
|
|
TSharedPtr<SNumericEntryBox<float>> SMatrixInputWidget::CreateMatrixElementWidget(int32 Row, int32 Col)
|
|
{
|
|
return SNew(SNumericEntryBox<float>)
|
|
.Value_Lambda([this, Row, Col]() -> float
|
|
{
|
|
return Matrix.M[Row][Col];
|
|
})
|
|
.OnValueChanged(SNumericEntryBox<float>::FOnValueChanged::CreateSP(this, &SMatrixInputWidget::OnMatrixElementChanged, Row, Col))
|
|
.AllowSpin(true)
|
|
.Delta(0.1f)
|
|
.MinValue(-10000.0f)
|
|
.MaxValue(10000.0f)
|
|
.MinSliderValue(-10.0f)
|
|
.MaxSliderValue(10.0f);
|
|
}
|
|
|
|
void SMatrixInputWidget::OnMatrixElementChanged(float NewValue, int32 Row, int32 Col)
|
|
{
|
|
// Update the matrix element
|
|
Matrix.M[Row][Col] = NewValue;
|
|
|
|
// Notify listeners of the change
|
|
if (OnMatrixChanged.IsBound())
|
|
{
|
|
OnMatrixChanged.Execute(Matrix);
|
|
}
|
|
}
|
|
|
|
void SMatrixInputWidget::UpdateUI()
|
|
{
|
|
// Update each numeric entry box with the current matrix values
|
|
for (int32 Row = 0; Row < 4; ++Row)
|
|
{
|
|
for (int32 Col = 0; Col < 4; ++Col)
|
|
{
|
|
int32 Index = Row * 4 + Col;
|
|
if (NumericEntryBoxes.IsValidIndex(Index) && NumericEntryBoxes[Index].IsValid())
|
|
{
|
|
NumericEntryBoxes[Index]->SetValue(Matrix.M[Row][Col]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|