Files
FLESH/Source/FLESHEditor/Private/MatrixInputWidget.cpp
2025-04-17 23:59:17 +08:00

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