更新 Source/FLESHEditor/Private/MatrixInputWidget.cpp
This commit is contained in:
@@ -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
|
||||
|
Reference in New Issue
Block a user