更新 Source/FLESHEditor/Private/MatrixInputWidget.cpp

This commit is contained in:
2025-04-21 18:22:58 +08:00
parent 36a117dab6
commit 72908595a5

View File

@@ -13,41 +13,62 @@ void SMatrixInputWidget::Construct(const FArguments& InArgs)
{
Matrix = InArgs._Matrix;
OnMatrixChanged = InArgs._OnMatrixChanged;
Rows = InArgs._Rows;
Columns = InArgs._Columns;
// Create a grid panel for the matrix elements
GridPanel = SNew(SGridPanel);
// Create numeric entry boxes for each matrix element
NumericEntryBoxes.SetNum(16); // 4x4 matrix
NumericEntryBoxes.SetNum(Rows * Columns); // Allocate numeric entry boxes based on rows and columns
// Add labels for rows and columns
for (int32 Col = 0; Col < 4; ++Col)
for (int32 Col = 0; Col < Columns; ++Col)
{
FString ColLabel;
switch (Col)
{
case 0: ColLabel = "X"; break;
case 1: ColLabel = "Y"; break;
case 2: ColLabel = "Z"; break;
default: ColLabel = FString::Printf(TEXT("Column %d"), Col);
}
GridPanel->AddSlot(Col + 1, 0)
[
SNew(STextBlock)
.Text(FText::Format(FText::FromString("Column {0}"), FText::AsNumber(Col)))
.Text(FText::FromString(ColLabel))
.Margin(FMargin(5.0f))
];
}
for (int32 Row = 0; Row < 4; ++Row)
for (int32 Row = 0; Row < Rows; ++Row)
{
FString RowLabel;
switch (Row)
{
case 0: RowLabel = "Right"; break;
case 1: RowLabel = "Forward"; break;
case 2: RowLabel = "Up"; break;
case 3: RowLabel = "Position"; break;
default: RowLabel = FString::Printf(TEXT("Row %d"), Row);
}
GridPanel->AddSlot(0, Row + 1)
[
SNew(STextBlock)
.Text(FText::Format(FText::FromString("Row {0}"), FText::AsNumber(Row)))
.Text(FText::FromString(RowLabel))
.Margin(FMargin(5.0f))
];
}
// Add numeric entry boxes for each matrix element
for (int32 Row = 0; Row < 4; ++Row)
for (int32 Row = 0; Row < Rows; ++Row)
{
for (int32 Col = 0; Col < 4; ++Col)
for (int32 Col = 0; Col < Columns; ++Col)
{
TSharedPtr<SNumericEntryBox<float>> NumericEntryBox = CreateMatrixElementWidget(Row, Col);
NumericEntryBoxes[Row * 4 + Col] = NumericEntryBox;
NumericEntryBoxes[Row * Columns + Col] = NumericEntryBox;
GridPanel->AddSlot(Col + 1, Row + 1)
[
@@ -101,37 +122,386 @@ void SMatrixInputWidget::Construct(const FArguments& InArgs)
}))
];
// Main widget layout
// Add preset cutting buttons
ButtonPanel->AddSlot(0, 1)
[
SNew(SButton)
.Text(FText::FromString("Horizontal Cut"))
.ToolTipText(FText::FromString("Set up a horizontal cutting plane"))
.OnClicked(FOnClicked::CreateLambda([this]()
{
// Set horizontal cutting plane
FMatrix HorizontalCutMatrix = FMatrix::Identity;
HorizontalCutMatrix.SetOrigin(FVector(0.0f, 0.0f, 0.0f));
SetMatrix(HorizontalCutMatrix);
return FReply::Handled();
}))
];
ButtonPanel->AddSlot(1, 1)
[
SNew(SButton)
.Text(FText::FromString("Vertical Cut"))
.ToolTipText(FText::FromString("Set up a vertical cutting plane"))
.OnClicked(FOnClicked::CreateLambda([this]()
{
// Set vertical cutting plane
FMatrix VerticalCutMatrix = FMatrix::Identity;
VerticalCutMatrix.SetOrigin(FVector(0.0f, 0.0f, 0.0f));
// Rotate 90 degrees to make it vertical
FRotator Rotator(0.0f, 0.0f, 90.0f);
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
SetMatrix(VerticalCutMatrix * RotationMatrix);
return FReply::Handled();
}))
];
ButtonPanel->AddSlot(2, 1)
[
SNew(SButton)
.Text(FText::FromString("Diagonal Cut"))
.ToolTipText(FText::FromString("Set up a diagonal cutting plane"))
.OnClicked(FOnClicked::CreateLambda([this]()
{
// Set diagonal cutting plane
FMatrix DiagonalCutMatrix = FMatrix::Identity;
DiagonalCutMatrix.SetOrigin(FVector(0.0f, 0.0f, 0.0f));
// Rotate 45 degrees
FRotator Rotator(0.0f, 0.0f, 45.0f);
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
SetMatrix(DiagonalCutMatrix * RotationMatrix);
return FReply::Handled();
}))
];
// Add apply cut button
TSharedPtr<SButton> ApplyCutButton = SNew(SButton)
.Text(FText::FromString("Apply Cut"))
.ButtonStyle(FAppStyle::Get(), "FlatButton.Success")
.ContentPadding(FMargin(8.0f, 4.0f))
.HAlign(HAlign_Center)
.ToolTipText(FText::FromString("Apply the current cutting plane to the model"))
.OnClicked(FOnClicked::CreateLambda([this]()
{
// Apply cutting
if (OnMatrixChanged.IsBound())
{
OnMatrixChanged.Execute(Matrix);
}
return FReply::Handled();
}));
// Create rotation controls
TSharedPtr<SVerticalBox> RotationControls = SNew(SVerticalBox);
// Add X-axis rotation
RotationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("X Rotation:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-180.0f)
.MaxValue(180.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply X-axis rotation
FRotator Rotator(NewValue, 0.0f, 0.0f);
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
FMatrix NewMatrix = Matrix * RotationMatrix;
SetMatrix(NewMatrix);
})
]
];
// Add Y-axis rotation
RotationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("Y Rotation:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-180.0f)
.MaxValue(180.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply Y-axis rotation
FRotator Rotator(0.0f, NewValue, 0.0f);
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
FMatrix NewMatrix = Matrix * RotationMatrix;
SetMatrix(NewMatrix);
})
]
];
// Add Z-axis rotation
RotationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("Z Rotation:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-180.0f)
.MaxValue(180.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply Z-axis rotation
FRotator Rotator(0.0f, 0.0f, NewValue);
FMatrix RotationMatrix = FRotationMatrix::Make(Rotator);
FMatrix NewMatrix = Matrix * RotationMatrix;
SetMatrix(NewMatrix);
})
]
];
// Create translation controls
TSharedPtr<SVerticalBox> TranslationControls = SNew(SVerticalBox);
// Add X-axis translation
TranslationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("X Position:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-1000.0f)
.MaxValue(1000.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply X-axis translation
FVector Translation = Matrix.GetOrigin();
Translation.X = NewValue;
FMatrix NewMatrix = Matrix;
NewMatrix.SetOrigin(Translation);
SetMatrix(NewMatrix);
})
]
];
// Add Y-axis translation
TranslationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("Y Position:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-1000.0f)
.MaxValue(1000.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply Y-axis translation
FVector Translation = Matrix.GetOrigin();
Translation.Y = NewValue;
FMatrix NewMatrix = Matrix;
NewMatrix.SetOrigin(Translation);
SetMatrix(NewMatrix);
})
]
];
// Add Z-axis translation
TranslationControls->AddSlot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
.Padding(0.0f, 0.0f, 4.0f, 0.0f)
[
SNew(STextBlock)
.Text(FText::FromString("Z Position:"))
.MinDesiredWidth(80.0f)
]
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
[
SNew(SSpinBox<float>)
.MinValue(-1000.0f)
.MaxValue(1000.0f)
.Delta(1.0f)
.Value(0.0f)
.OnValueChanged_Lambda([this](float NewValue)
{
// Apply Z-axis translation
FVector Translation = Matrix.GetOrigin();
Translation.Z = NewValue;
FMatrix NewMatrix = Matrix;
NewMatrix.SetOrigin(Translation);
SetMatrix(NewMatrix);
})
]
];
// Create main layout
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(5.0f)
.Padding(0.0f, 0.0f, 0.0f, 8.0f)
[
SNew(STextBlock)
.Text(FText::FromString("Matrix Input"))
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 14))
.Text(FText::FromString("Cutting Plane Transformation Matrix"))
.Font(FAppStyle::GetFontStyle("HeadingFont"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(5.0f)
.AutoHeight()
[
SNew(SScrollBox)
+ SScrollBox::Slot()
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
GridPanel.ToSharedRef()
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(5.0f)
.Padding(0.0f, 8.0f)
[
ButtonPanel.ToSharedRef()
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Rotation Controls"))
.Font(FAppStyle::GetFontStyle("NormalFontBold"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
RotationControls.ToSharedRef()
]
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 8.0f)
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Translation Controls"))
.Font(FAppStyle::GetFontStyle("NormalFontBold"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
TranslationControls.ToSharedRef()
]
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 8.0f)
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("ToolPanel.GroupBorder"))
.Padding(4.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Presets"))
.Font(FAppStyle::GetFontStyle("NormalFontBold"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 4.0f)
[
ButtonPanel.ToSharedRef()
]
]
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 8.0f)
.HAlign(HAlign_Center)
[
ApplyCutButton.ToSharedRef()
]
];
// Update the UI with the initial matrix value
// Initialize the UI
UpdateUI();
}
@@ -207,11 +577,11 @@ void SMatrixInputWidget::OnMatrixElementChanged(float NewValue, int32 Row, int32
void SMatrixInputWidget::UpdateUI()
{
// Update each numeric entry box with the current matrix values
for (int32 Row = 0; Row < 4; ++Row)
for (int32 Row = 0; Row < Rows; ++Row)
{
for (int32 Col = 0; Col < 4; ++Col)
for (int32 Col = 0; Col < Columns; ++Col)
{
int32 Index = Row * 4 + Col;
int32 Index = Row * Columns + Col;
if (NumericEntryBoxes.IsValidIndex(Index) && NumericEntryBoxes[Index].IsValid())
{
// In UE5.5.4, we need to rebuild the grid panel to update the value