2025-08-30 18:03:42 +08:00
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
#include "Widgets/ShapeGridWidget.h"
|
2025-08-30 18:03:42 +08:00
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
const float SShapeGridWidget::CellSize = 32.0f;
|
|
|
|
|
const float SShapeGridWidget::SeparatorWidth = 2.0f;
|
|
|
|
|
void SShapeGridWidget::Construct(const FArguments& InArgs)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
BagShapeAsset = InArgs._BagShapeAsset;
|
|
|
|
|
OnSlotClicked = InArgs._OnSlotClicked;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
void SShapeGridWidget::UpdateBagShapeAsset(UShapeAsset* InBagShapeAsset)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
BagShapeAsset = InBagShapeAsset;
|
|
|
|
|
Invalidate(EInvalidateWidget::Paint);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
FReply SShapeGridWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
int32 SShapeGridWidget::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
|
2025-08-30 18:03:42 +08:00
|
|
|
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;
|
2025-10-15 18:25:31 +08:00
|
|
|
float GridWidth = BagShapeAsset->ShapeWidth * Scale - SeparatorWidth;
|
|
|
|
|
float GridHeight = BagShapeAsset->ShapeHeight * Scale - SeparatorWidth;
|
2025-08-30 18:03:42 +08:00
|
|
|
|
|
|
|
|
// 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
|
2025-10-15 18:25:31 +08:00
|
|
|
for (int32 Y = 0; Y < BagShapeAsset->ShapeHeight; Y++)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
2025-10-15 18:25:31 +08:00
|
|
|
for (int32 X = 0; X < BagShapeAsset->ShapeWidth; X++)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
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
|
2025-10-15 18:25:31 +08:00
|
|
|
for (int32 X = 1; X < BagShapeAsset->ShapeWidth; X++)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
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
|
2025-10-15 18:25:31 +08:00
|
|
|
for (int32 Y = 1; Y < BagShapeAsset->ShapeHeight; Y++)
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
FVector2D SShapeGridWidget::ComputeDesiredSize(float X) const
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
if (!BagShapeAsset.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return FVector2D(200, 200);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Scale = CellSize + SeparatorWidth;
|
|
|
|
|
return FVector2D(
|
2025-10-15 18:25:31 +08:00
|
|
|
BagShapeAsset->ShapeWidth * Scale - SeparatorWidth + 20.0f, // Add padding
|
|
|
|
|
BagShapeAsset->ShapeHeight * Scale - SeparatorWidth + 20.0f
|
2025-08-30 18:03:42 +08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
FVector2D SShapeGridWidget::GetGridCellFromPosition(const FVector2D& Position) const
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
if (!BagShapeAsset.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return FVector2D(-1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float Scale = CellSize + SeparatorWidth;
|
2025-10-15 18:25:31 +08:00
|
|
|
float GridWidth = BagShapeAsset->ShapeWidth * Scale - SeparatorWidth;
|
|
|
|
|
float GridHeight = BagShapeAsset->ShapeHeight * Scale - SeparatorWidth;
|
2025-08-30 18:03:42 +08:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-15 18:25:31 +08:00
|
|
|
bool SShapeGridWidget::IsValidGridPosition(int32 X, int32 Y) const
|
2025-08-30 18:03:42 +08:00
|
|
|
{
|
|
|
|
|
if (!BagShapeAsset.IsValid())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-10-15 18:25:31 +08:00
|
|
|
return X >= 0 && X < BagShapeAsset->ShapeWidth && Y >= 0 && Y < BagShapeAsset->ShapeHeight;
|
2025-08-30 18:03:42 +08:00
|
|
|
}
|