From f99367951abc7cb1dd0f54086cfbd767c15f4eb2 Mon Sep 17 00:00:00 2001 From: 997146918 <997146918@qq.com> Date: Sun, 31 Aug 2025 16:10:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=83=8C=E5=8C=85=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=B5=84=E6=BA=90=E7=9A=84=E7=BC=A9=E7=95=A5=E5=9B=BE?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Private/ProjectFishEditor.cpp | 10 +- .../Thumbnail/BagConfigThumbnailRenderer.cpp | 179 ++++++++++++++++++ .../BagShapeAssetThumbnailRenderer.cpp | 0 .../Thumbnail/BagConfigThumbnailRenderer.h | 32 ++++ 4 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagConfigThumbnailRenderer.cpp rename ProjectFish/Source/ProjectFishEditor/Private/{Thimbnail => Thumbnail}/BagShapeAssetThumbnailRenderer.cpp (100%) create mode 100644 ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagConfigThumbnailRenderer.h diff --git a/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp b/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp index 26fa3b0..71de39b 100644 --- a/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp +++ b/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp @@ -7,6 +7,8 @@ #include "AssetRegistry/AssetRegistryModule.h" #include "ProjectFish/DataAsset/BagShapeAsset.h" #include "../Public/Thumbnail/BagShapeAssetThumbnailRenderer.h" +#include "../Public/Thumbnail/BagConfigThumbnailRenderer.h" +#include "ProjectFish/DataAsset/BagConfigAsset.h" #define LOCTEXT_NAMESPACE "FProjectFishEditorModule" @@ -72,6 +74,7 @@ void FProjectFishEditorModule::UnregisterAssetTypeActions() void FProjectFishEditorModule::RegisterThumbnailRenderers() { UThumbnailManager::Get().RegisterCustomRenderer(UBagShapeAsset::StaticClass(), UBagShapeAssetThumbnailRenderer::StaticClass()); + UThumbnailManager::Get().RegisterCustomRenderer(UBagConfigAsset::StaticClass(), UBagConfigThumbnailRenderer::StaticClass()); RefreshExistingAssetThumbnails(); } @@ -80,6 +83,7 @@ void FProjectFishEditorModule::UnregisterThumbnailRenderers() if (UObjectInitialized()) { UThumbnailManager::Get().UnregisterCustomRenderer(UBagShapeAsset::StaticClass()); + UThumbnailManager::Get().UnregisterCustomRenderer(UBagConfigAsset::StaticClass()); } } @@ -98,13 +102,13 @@ void FProjectFishEditorModule::RefreshExistingAssetThumbnails() AssetRegistry.GetAssetsByClass(UBagShapeAsset::StaticClass()->GetClassPathName(), BagShapeAssetList); // 查找所有BagClass资产 - TArray BagClassAssetList; - //AssetRegistry.GetAssetsByClass(UBagClass::StaticClass()->GetClassPathName(), BagClassAssetList); + TArray BagConfigAssetList; + AssetRegistry.GetAssetsByClass(UBagConfigAsset::StaticClass()->GetClassPathName(), BagConfigAssetList); // 合并资产列表 TArray AllAssets; AllAssets.Append(BagShapeAssetList); - AllAssets.Append(BagClassAssetList); + AllAssets.Append(BagConfigAssetList); // 刷新每个资产的缩略图 UThumbnailManager& ThumbnailManager = UThumbnailManager::Get(); diff --git a/ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagConfigThumbnailRenderer.cpp b/ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagConfigThumbnailRenderer.cpp new file mode 100644 index 0000000..f126563 --- /dev/null +++ b/ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagConfigThumbnailRenderer.cpp @@ -0,0 +1,179 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Thumbnail/BagConfigThumbnailRenderer.h" + +#include "CanvasItem.h" +#include "CanvasTypes.h" +#include "ProjectFish/DataAsset/BagConfigAsset.h" +#include "ProjectFish/DataAsset/BagShapeAsset.h" + +bool UBagConfigThumbnailRenderer::CanVisualizeAsset(UObject* Object) +{ + return Cast(Object) != nullptr; +} + +void UBagConfigThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, + FRenderTarget* RenderTarget, FCanvas* Canvas, bool bAdditionalViewFamily) +{ + UBagConfigAsset* BagConfig= Cast(Object); + if (!BagConfig || !Canvas) + { + return; + } + + DrawBag(BagConfig, Canvas, X, Y, Width, Height); +} + +void UBagConfigThumbnailRenderer::DrawBag(UBagConfigAsset* BagConfig, FCanvas* Canvas, int32 X, int32 Y, + uint32 Width, uint32 Height) +{ + if (!BagConfig || !Canvas) + { + return; + } + + // 检查是否有背包形状资源 + if (!BagConfig->BagShapeAsset) + { + // 绘制错误状态 + FCanvasBoxItem ErrorBox(FVector2D(X, Y), FVector2D(Width, Height)); + ErrorBox.SetColor(FLinearColor(0.5f, 0.1f, 0.1f, 1.0f)); + Canvas->DrawItem(ErrorBox); + return; + } + + UBagShapeAsset* BagShapeAsset = BagConfig->BagShapeAsset; + + // Clear the background + FCanvasBoxItem BackgroundBox(FVector2D(X, Y), FVector2D(Width, Height)); + BackgroundBox.SetColor(FLinearColor(0.1f, 0.1f, 0.1f, 1.0f)); + Canvas->DrawItem(BackgroundBox); + + // Calculate the best fit scale with spacing for separators + float SeparatorWidth = 2.0f; // White separator width + float Scale = GetBestFitScale(BagShapeAsset->BagWidth, BagShapeAsset->BagHeight, Width, Height); + float CellSize = Scale - SeparatorWidth; // Reduce cell size to make room for separators + + // Calculate starting position to center the grid (including separators) + float GridWidth = BagShapeAsset->BagWidth * Scale - SeparatorWidth; + float GridHeight = BagShapeAsset->BagHeight * Scale - SeparatorWidth; + float StartX = X + (Width - GridWidth) * 0.5f; + float StartY = Y + (Height - GridHeight) * 0.5f; + + // Draw the bag slots (background) with separators + for (int32 GridY = 0; GridY < BagShapeAsset->BagHeight; GridY++) + { + for (int32 GridX = 0; GridX < BagShapeAsset->BagWidth; GridX++) + { + float CellStartX = StartX + GridX * Scale; + float CellStartY = StartY + GridY * Scale; + + bool bIsActive = BagShapeAsset->IsSlotActive(GridX, GridY); + + // Draw filled cell (smaller to leave space for separators) + FCanvasTileItem CellTile(FVector2D(CellStartX, CellStartY), FVector2D(CellSize, CellSize), + bIsActive ? FLinearColor(0.3f, 0.3f, 0.3f, 1.0f) : FLinearColor(0.15f, 0.15f, 0.15f, 1.0f)); + CellTile.BlendMode = SE_BLEND_Opaque; + Canvas->DrawItem(CellTile); + } + } + + // Draw white separators + // Vertical separators + for (int32 GridX = 1; GridX < BagShapeAsset->BagWidth; GridX++) + { + float SeparatorX = StartX + GridX * Scale - SeparatorWidth; + FCanvasTileItem VerticalSeparator(FVector2D(SeparatorX, StartY), FVector2D(SeparatorWidth, GridHeight), FLinearColor::White); + VerticalSeparator.BlendMode = SE_BLEND_Opaque; + Canvas->DrawItem(VerticalSeparator); + } + + // Horizontal separators + for (int32 GridY = 1; GridY < BagShapeAsset->BagHeight; GridY++) + { + float SeparatorY = StartY + GridY * Scale - SeparatorWidth; + FCanvasTileItem HorizontalSeparator(FVector2D(StartX, SeparatorY), FVector2D(GridWidth, SeparatorWidth), FLinearColor::White); + HorizontalSeparator.BlendMode = SE_BLEND_Opaque; + Canvas->DrawItem(HorizontalSeparator); + } + + // Draw skills on top + for (const FPlacedSkillInfo& PlacedSkill : BagConfig->PlacedSkills) + { + DrawSkill(PlacedSkill, Canvas, StartX, StartY, Scale, SeparatorWidth); + } + + // Draw outer border + FCanvasBoxItem OuterBorder(FVector2D(StartX, StartY), FVector2D(GridWidth, GridHeight)); + OuterBorder.SetColor(FLinearColor::White); + OuterBorder.LineThickness = 3.0f; + Canvas->DrawItem(OuterBorder); +} + +float UBagConfigThumbnailRenderer::GetBestFitScale(int32 BagWidth, int32 BagHeight, uint32 CanvasWidth, + uint32 CanvasHeight) const +{ + if (BagWidth == 0 || BagHeight == 0) + { + return 1.0f; + } + + // Leave some padding + float PaddedWidth = CanvasWidth * 0.85f; + float PaddedHeight = CanvasHeight * 0.85f; + + float ScaleX = PaddedWidth / BagWidth; + float ScaleY = PaddedHeight / BagHeight; + + // Use the smaller scale to ensure everything fits + float Scale = FMath::Min(ScaleX, ScaleY); + + // Ensure minimum cell size for visibility + Scale = FMath::Max(Scale, 3.0f); + + return Scale; +} + +void UBagConfigThumbnailRenderer::DrawSkill(const struct FPlacedSkillInfo& PlacedSkill, FCanvas* Canvas, float StartX, + float StartY, float Scale, float SeparatorWidth) +{ + if (!PlacedSkill.SkillAsset) + { + return; + } + + USkillAsset* SkillObject = PlacedSkill.SkillAsset; + float CellSize = Scale - SeparatorWidth; + + float SkillStartX = StartX + PlacedSkill.PositionX * Scale; + float SkillStartY = StartY + PlacedSkill.PositionY * Scale; + + float SkillWidth = GetSkillSizeValue(SkillObject->SkillSize).X * Scale - SeparatorWidth; + float SkillHeight = GetSkillSizeValue(SkillObject->SkillSize).Y * Scale - SeparatorWidth; + + // Draw skill background + FCanvasTileItem SkillTile(FVector2D(SkillStartX, SkillStartY), FVector2D(SkillWidth, SkillHeight), FLinearColor::Blue); + SkillTile.BlendMode = SE_BLEND_Opaque; + Canvas->DrawItem(SkillTile); + + // Draw skill border + FCanvasBoxItem SkillBorder(FVector2D(SkillStartX, SkillStartY), FVector2D(SkillWidth, SkillHeight)); + SkillBorder.SetColor(FLinearColor::White); + SkillBorder.LineThickness = 2.0f; + Canvas->DrawItem(SkillBorder); + + // Draw skill name (if there's enough space) + if (CellSize >= 12.0f && !SkillObject->SkillName.ToString().IsEmpty()) + { + FString DisplayName = SkillObject->SkillName.ToString(); + if (DisplayName.Len() > 8) + { + DisplayName = DisplayName.Left(6) + TEXT(".."); + } + + FCanvasTextItem TextItem(FVector2D(SkillStartX + 2, SkillStartY + 2), FText::FromString(DisplayName), GEngine->GetSmallFont(), FLinearColor::White); + TextItem.Scale = FVector2D(0.7f, 0.7f); + Canvas->DrawItem(TextItem); + } +} diff --git a/ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp b/ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagShapeAssetThumbnailRenderer.cpp similarity index 100% rename from ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp rename to ProjectFish/Source/ProjectFishEditor/Private/Thumbnail/BagShapeAssetThumbnailRenderer.cpp diff --git a/ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagConfigThumbnailRenderer.h b/ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagConfigThumbnailRenderer.h new file mode 100644 index 0000000..d0bfb53 --- /dev/null +++ b/ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagConfigThumbnailRenderer.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ThumbnailRendering/DefaultSizedThumbnailRenderer.h" +#include "BagConfigThumbnailRenderer.generated.h" + +/** + * + */ +UCLASS() +class PROJECTFISHEDITOR_API UBagConfigThumbnailRenderer : public UDefaultSizedThumbnailRenderer +{ + GENERATED_BODY() +public: + + + // UThumbnailRenderer interface + virtual bool CanVisualizeAsset(UObject* Object) override; + virtual void Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas, bool bAdditionalViewFamily) override; + +private: + /** Draw the bag class with skills on canvas */ + void DrawBag(class UBagConfigAsset* BagConfig, FCanvas* Canvas, int32 X, int32 Y, uint32 Width, uint32 Height); + + /** Get the best fit scale for the bag class */ + float GetBestFitScale(int32 BagWidth, int32 BagHeight, uint32 CanvasWidth, uint32 CanvasHeight) const; + + /** Draw a skill at the specified position */ + void DrawSkill(const struct FPlacedSkillInfo& PlacedSkill, FCanvas* Canvas, float StartX, float StartY, float Scale, float SeparatorWidth); +};