添加背包形状编辑器UI
This commit is contained in:
parent
445f21fe7b
commit
bd75d739f1
@ -2,9 +2,238 @@
|
||||
|
||||
|
||||
#include "Widgets/BagShapeEditorWidget.h"
|
||||
#include "Widgets/Input/SSpinBox.h"
|
||||
#include "EditorStyleSet.h"
|
||||
|
||||
|
||||
void SBagShapeEditorWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
BagShapeAsset = InArgs._BagShapeAsset;
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
SNew(SSplitter)
|
||||
.Orientation(Orient_Vertical)
|
||||
+ SSplitter::Slot()
|
||||
.Value(0.2f)
|
||||
[
|
||||
CreateSizeControls()
|
||||
]
|
||||
+ SSplitter::Slot()
|
||||
.Value(0.1f)
|
||||
[
|
||||
CreateGridControls()
|
||||
]
|
||||
+ SSplitter::Slot()
|
||||
.Value(0.7f)
|
||||
[
|
||||
SNew(SScrollBox)
|
||||
+ SScrollBox::Slot()
|
||||
[
|
||||
SNew(SBorder)
|
||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||
.Padding(10.0f)
|
||||
[
|
||||
SNew(SBox)
|
||||
.HAlign(HAlign_Center)
|
||||
.VAlign(VAlign_Center)
|
||||
[
|
||||
SAssignNew(GridWidget, SBagShapeGridWidget)
|
||||
.BagShapeAsset(BagShapeAsset.Get())
|
||||
.OnSlotClicked(this, &SBagShapeEditorWidget::OnSlotClicked)
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
void SBagShapeEditorWidget::RefreshGrid()
|
||||
{
|
||||
if (GridWidget.IsValid())
|
||||
{
|
||||
GridWidget->UpdateBagShapeAsset(BagShapeAsset.Get());
|
||||
}
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> SBagShapeEditorWidget::CreateSizeControls()
|
||||
{
|
||||
return SNew(SBorder)
|
||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||
.Padding(10.0f)
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(0, 5)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString("Bag Size Settings"))
|
||||
.Font(FCoreStyle::GetDefaultFontStyle("Bold", 14))
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(0, 5)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(0, 0, 10, 0)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString("Width:"))
|
||||
]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SBox)
|
||||
.WidthOverride(100.0f)
|
||||
[
|
||||
SNew(SSpinBox<int32>)
|
||||
.MinValue(1)
|
||||
.MaxValue(10)
|
||||
.Value(this, &SBagShapeEditorWidget::GetBagWidth)
|
||||
.OnValueChanged(this, &SBagShapeEditorWidget::OnWidthChanged)
|
||||
]
|
||||
]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Center)
|
||||
.Padding(20, 0, 10, 0)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString("Width:"))
|
||||
]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
[
|
||||
SNew(SBox)
|
||||
.WidthOverride(100.0f)
|
||||
[
|
||||
SNew(SSpinBox<int32>)
|
||||
.MinValue(1)
|
||||
.MaxValue(10)
|
||||
.Value(this, &SBagShapeEditorWidget::GetBagHeight)
|
||||
.OnValueChanged(this, &SBagShapeEditorWidget::OnHeightChanged)
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
int32 SBagShapeEditorWidget::GetBagWidth() const
|
||||
{
|
||||
return BagShapeAsset.IsValid() ? BagShapeAsset->BagWidth : 5;
|
||||
}
|
||||
|
||||
int32 SBagShapeEditorWidget::GetBagHeight() const
|
||||
{
|
||||
return BagShapeAsset.IsValid() ? BagShapeAsset->BagHeight : 5;
|
||||
}
|
||||
|
||||
void SBagShapeEditorWidget::OnWidthChanged(int32 NewWidth)
|
||||
{
|
||||
if (BagShapeAsset.IsValid() && NewWidth != BagShapeAsset->BagWidth)
|
||||
{
|
||||
BagShapeAsset->BagWidth = NewWidth;
|
||||
BagShapeAsset->InitializeBagShape();
|
||||
BagShapeAsset->MarkPackageDirty();
|
||||
RefreshGrid();
|
||||
}
|
||||
}
|
||||
|
||||
void SBagShapeEditorWidget::OnHeightChanged(int32 NewHeight)
|
||||
{
|
||||
if (BagShapeAsset.IsValid() && NewHeight != BagShapeAsset->BagHeight)
|
||||
{
|
||||
BagShapeAsset->BagHeight = NewHeight;
|
||||
BagShapeAsset->InitializeBagShape();
|
||||
BagShapeAsset->MarkPackageDirty();
|
||||
RefreshGrid();
|
||||
}
|
||||
}
|
||||
|
||||
TSharedRef<SWidget> SBagShapeEditorWidget::CreateGridControls()
|
||||
{
|
||||
return SNew(SBorder)
|
||||
.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
|
||||
.Padding(10.0f)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(0, 0, 10, 0)
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(FText::FromString("All Enable"))
|
||||
.OnClicked(this, &SBagShapeEditorWidget::OnAllEnableClicked)
|
||||
]
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.Padding(0, 0, 10, 0)
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(FText::FromString("All Disable"))
|
||||
.OnClicked(this, &SBagShapeEditorWidget::OnAllDisableClicked)
|
||||
]
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
FReply SBagShapeEditorWidget::OnAllEnableClicked()
|
||||
{
|
||||
if (BagShapeAsset.IsValid())
|
||||
{
|
||||
BagShapeAsset->InitializeBagShape();
|
||||
BagShapeAsset->MarkPackageDirty();
|
||||
RefreshGrid();
|
||||
RefreshThumbnail();
|
||||
}
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
FReply SBagShapeEditorWidget::OnAllDisableClicked()
|
||||
{
|
||||
if (BagShapeAsset.IsValid())
|
||||
{
|
||||
for (int32 X = 0; X < BagShapeAsset->BagWidth; X++)
|
||||
{
|
||||
for (int32 Y = 0; Y < BagShapeAsset->BagHeight; Y++)
|
||||
{
|
||||
BagShapeAsset->SetSlotActive(X, Y, false);
|
||||
}
|
||||
}
|
||||
BagShapeAsset->MarkPackageDirty();
|
||||
RefreshGrid();
|
||||
RefreshThumbnail();
|
||||
}
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
void SBagShapeEditorWidget::OnSlotClicked(int32 X, int32 Y)
|
||||
{
|
||||
if (!BagShapeAsset.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool bCurrentState = BagShapeAsset->IsSlotActive(X, Y);
|
||||
BagShapeAsset->SetSlotActive(X, Y, !bCurrentState);
|
||||
|
||||
// Refresh the grid widget
|
||||
if (GridWidget.IsValid())
|
||||
{
|
||||
GridWidget->UpdateBagShapeAsset(BagShapeAsset.Get());
|
||||
}
|
||||
|
||||
// Mark the asset as modified
|
||||
BagShapeAsset->MarkPackageDirty();
|
||||
|
||||
// 强制刷新缩略图
|
||||
RefreshThumbnail();
|
||||
}
|
||||
|
||||
void SBagShapeEditorWidget::RefreshThumbnail()
|
||||
{
|
||||
}
|
||||
|
||||
@ -0,0 +1,177 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Widgets/BagShapeGridWidget.h"
|
||||
|
||||
const float SBagShapeGridWidget::CellSize = 32.0f;
|
||||
const float SBagShapeGridWidget::SeparatorWidth = 2.0f;
|
||||
void SBagShapeGridWidget::Construct(const FArguments& InArgs)
|
||||
{
|
||||
BagShapeAsset = InArgs._BagShapeAsset;
|
||||
OnSlotClicked = InArgs._OnSlotClicked;
|
||||
}
|
||||
|
||||
void SBagShapeGridWidget::UpdateBagShapeAsset(UBagShapeAsset* InBagShapeAsset)
|
||||
{
|
||||
BagShapeAsset = InBagShapeAsset;
|
||||
Invalidate(EInvalidateWidget::Paint);
|
||||
}
|
||||
|
||||
FReply SBagShapeGridWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
||||
{
|
||||
if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && BagShapeAsset.IsValid())
|
||||
{
|
||||
FVector2D LocalPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
|
||||
FVector2D GridCell = GetGridCellFromPosition(LocalPosition);
|
||||
|
||||
int32 GridX = FMath::FloorToInt(GridCell.X);
|
||||
int32 GridY = FMath::FloorToInt(GridCell.Y);
|
||||
|
||||
if (IsValidGridPosition(GridX, GridY))
|
||||
{
|
||||
OnSlotClicked.ExecuteIfBound(GridX, GridY);
|
||||
return FReply::Handled();
|
||||
}
|
||||
}
|
||||
|
||||
return FReply::Unhandled();
|
||||
}
|
||||
|
||||
int32 SBagShapeGridWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
|
||||
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
|
||||
const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
||||
{
|
||||
if (!BagShapeAsset.IsValid())
|
||||
{
|
||||
return LayerId;
|
||||
}
|
||||
|
||||
// Calculate grid dimensions with separators
|
||||
float Scale = CellSize + SeparatorWidth;
|
||||
float GridWidth = BagShapeAsset->BagWidth * Scale - SeparatorWidth;
|
||||
float GridHeight = BagShapeAsset->BagHeight * Scale - SeparatorWidth;
|
||||
|
||||
// Center the grid in the available space
|
||||
FVector2D GridStartPos = FVector2D(
|
||||
(AllottedGeometry.GetLocalSize().X - GridWidth) * 0.5f,
|
||||
(AllottedGeometry.GetLocalSize().Y - GridHeight) * 0.5f
|
||||
);
|
||||
|
||||
// Draw background
|
||||
FSlateDrawElement::MakeBox(
|
||||
OutDrawElements,
|
||||
LayerId,
|
||||
AllottedGeometry.ToPaintGeometry(AllottedGeometry.GetLocalSize(), FSlateLayoutTransform()),
|
||||
FCoreStyle::Get().GetBrush("WhiteBrush"),
|
||||
ESlateDrawEffect::None,
|
||||
FLinearColor(0.1f, 0.1f, 0.1f, 1.0f)
|
||||
);
|
||||
|
||||
// Draw cells
|
||||
for (int32 Y = 0; Y < BagShapeAsset->BagHeight; Y++)
|
||||
{
|
||||
for (int32 X = 0; X < BagShapeAsset->BagWidth; X++)
|
||||
{
|
||||
FVector2D CellPos = GridStartPos + FVector2D(X * Scale, Y * Scale);
|
||||
bool bIsActive = BagShapeAsset->IsSlotActive(X, Y);
|
||||
|
||||
// Draw cell background
|
||||
FLinearColor CellColor = bIsActive ? FLinearColor(0.2f, 0.8f, 0.2f, 1.0f) : FLinearColor(0.15f, 0.15f, 0.15f, 1.0f);
|
||||
FSlateDrawElement::MakeBox(
|
||||
OutDrawElements,
|
||||
LayerId + 1,
|
||||
AllottedGeometry.ToPaintGeometry(FVector2D(CellSize, CellSize), FSlateLayoutTransform(CellPos)),
|
||||
FCoreStyle::Get().GetBrush("WhiteBrush"),
|
||||
ESlateDrawEffect::None,
|
||||
CellColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw vertical separators
|
||||
for (int32 X = 1; X < BagShapeAsset->BagWidth; X++)
|
||||
{
|
||||
float SeparatorX = GridStartPos.X + X * Scale - SeparatorWidth;
|
||||
FSlateDrawElement::MakeBox(
|
||||
OutDrawElements,
|
||||
LayerId + 2,
|
||||
AllottedGeometry.ToPaintGeometry(FVector2D(SeparatorWidth, GridHeight), FSlateLayoutTransform(FVector2D(SeparatorX, GridStartPos.Y))),
|
||||
FCoreStyle::Get().GetBrush("WhiteBrush"),
|
||||
ESlateDrawEffect::None,
|
||||
FLinearColor::White
|
||||
);
|
||||
}
|
||||
|
||||
// Draw horizontal separators
|
||||
for (int32 Y = 1; Y < BagShapeAsset->BagHeight; Y++)
|
||||
{
|
||||
float SeparatorY = GridStartPos.Y + Y * Scale - SeparatorWidth;
|
||||
FSlateDrawElement::MakeBox(
|
||||
OutDrawElements,
|
||||
LayerId + 2,
|
||||
AllottedGeometry.ToPaintGeometry(FVector2D(GridWidth, SeparatorWidth), FSlateLayoutTransform(FVector2D(GridStartPos.X, SeparatorY))),
|
||||
FCoreStyle::Get().GetBrush("WhiteBrush"),
|
||||
ESlateDrawEffect::None,
|
||||
FLinearColor::White
|
||||
);
|
||||
}
|
||||
|
||||
// Draw outer border
|
||||
FSlateDrawElement::MakeBox(
|
||||
OutDrawElements,
|
||||
LayerId + 3,
|
||||
AllottedGeometry.ToPaintGeometry(FVector2D(GridWidth, GridHeight), FSlateLayoutTransform(GridStartPos)),
|
||||
FCoreStyle::Get().GetBrush("Border"),
|
||||
ESlateDrawEffect::None,
|
||||
FLinearColor::White
|
||||
);
|
||||
|
||||
return LayerId + 4;
|
||||
}
|
||||
|
||||
FVector2D SBagShapeGridWidget::ComputeDesiredSize(float X) const
|
||||
{
|
||||
if (!BagShapeAsset.IsValid())
|
||||
{
|
||||
return FVector2D(200, 200);
|
||||
}
|
||||
|
||||
float Scale = CellSize + SeparatorWidth;
|
||||
return FVector2D(
|
||||
BagShapeAsset->BagWidth * Scale - SeparatorWidth + 20.0f, // Add padding
|
||||
BagShapeAsset->BagHeight * Scale - SeparatorWidth + 20.0f
|
||||
);
|
||||
}
|
||||
|
||||
FVector2D SBagShapeGridWidget::GetGridCellFromPosition(const FVector2D& Position) const
|
||||
{
|
||||
if (!BagShapeAsset.IsValid())
|
||||
{
|
||||
return FVector2D(-1, -1);
|
||||
}
|
||||
|
||||
float Scale = CellSize + SeparatorWidth;
|
||||
float GridWidth = BagShapeAsset->BagWidth * Scale - SeparatorWidth;
|
||||
float GridHeight = BagShapeAsset->BagHeight * Scale - SeparatorWidth;
|
||||
|
||||
FVector2D GridStartPos = FVector2D(
|
||||
(GetCachedGeometry().GetLocalSize().X - GridWidth) * 0.5f,
|
||||
(GetCachedGeometry().GetLocalSize().Y - GridHeight) * 0.5f
|
||||
);
|
||||
|
||||
FVector2D RelativePos = Position - GridStartPos;
|
||||
|
||||
return FVector2D(
|
||||
RelativePos.X / Scale,
|
||||
RelativePos.Y / Scale
|
||||
);
|
||||
}
|
||||
|
||||
bool SBagShapeGridWidget::IsValidGridPosition(int32 X, int32 Y) const
|
||||
{
|
||||
if (!BagShapeAsset.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return X >= 0 && X < BagShapeAsset->BagWidth && Y >= 0 && Y < BagShapeAsset->BagHeight;
|
||||
}
|
||||
@ -23,7 +23,8 @@ public class ProjectFishEditor : ModuleRules
|
||||
"ProjectFish",
|
||||
"InputCore",
|
||||
"AssetTools",
|
||||
"UnrealEd"
|
||||
"UnrealEd",
|
||||
"EditorStyle"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "BagShapeGridWidget.h"
|
||||
#include "ProjectFish/DataAsset/BagShapeAsset.h"
|
||||
|
||||
/**
|
||||
@ -16,6 +17,32 @@ public:
|
||||
SLATE_END_ARGS()
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
private:
|
||||
/** Refresh the grid display */
|
||||
void RefreshGrid();
|
||||
|
||||
//背包大小UI
|
||||
TSharedRef<SWidget> CreateSizeControls();
|
||||
/** Get the current bag width */
|
||||
int32 GetBagWidth() const;
|
||||
/** Get the current bag height */
|
||||
int32 GetBagHeight() const;
|
||||
/** Handle width spin box value change */
|
||||
void OnWidthChanged(int32 NewWidth);
|
||||
/** Handle height spin box value change */
|
||||
void OnHeightChanged(int32 NewHeight);
|
||||
|
||||
|
||||
//重置背包状态
|
||||
TSharedRef<SWidget> CreateGridControls();
|
||||
FReply OnAllEnableClicked();
|
||||
FReply OnAllDisableClicked();
|
||||
|
||||
//点击背包格子
|
||||
void OnSlotClicked(int32 X, int32 Y);
|
||||
//刷新图标
|
||||
void RefreshThumbnail();
|
||||
private:
|
||||
TWeakObjectPtr<class UBagShapeAsset> BagShapeAsset;
|
||||
TSharedPtr<SBagShapeGridWidget> GridWidget;
|
||||
};
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ProjectFish/DataAsset/BagShapeAsset.h"
|
||||
|
||||
DECLARE_DELEGATE_TwoParams(FOnSlotClicked, int32, int32);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class SBagShapeGridWidget : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SBagShapeGridWidget) {}
|
||||
SLATE_ARGUMENT(UBagShapeAsset*, BagShapeAsset)
|
||||
SLATE_EVENT(FOnSlotClicked, OnSlotClicked)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
void UpdateBagShapeAsset(UBagShapeAsset* InBagShapeAsset);
|
||||
|
||||
// SWidget interface
|
||||
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect,
|
||||
FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
|
||||
virtual FVector2D ComputeDesiredSize(float) const override;
|
||||
|
||||
private:
|
||||
static const float CellSize;
|
||||
static const float SeparatorWidth;
|
||||
|
||||
TWeakObjectPtr<UBagShapeAsset> BagShapeAsset;
|
||||
FOnSlotClicked OnSlotClicked;
|
||||
|
||||
FVector2D GetGridCellFromPosition(const FVector2D& Position) const;
|
||||
bool IsValidGridPosition(int32 X, int32 Y) const;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user