From faddbbe33890acd4628c05d40e485f96bc92dffd Mon Sep 17 00:00:00 2001 From: 997146918 <997146918@qq.com> Date: Sun, 31 Aug 2025 15:14:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=83=8C=E5=8C=85=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=AA=97=E5=8F=A3UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AssetEditor/BagConfigAssetEditor.cpp | 16 +- .../Private/ProjectFishEditor.cpp | 2 +- .../BagShapeAssetThumbnailRenderer.cpp | 2 +- .../Private/Widgets/BagConfigEditorWidget.cpp | 291 ++++++++++++++++++ .../ProjectFishEditor.Build.cs | 3 +- .../BagShapeAssetThumbnailRenderer.h | 0 .../Public/Widgets/BagConfigEditorWidget.h | 64 ++++ 7 files changed, 368 insertions(+), 10 deletions(-) create mode 100644 ProjectFish/Source/ProjectFishEditor/Private/Widgets/BagConfigEditorWidget.cpp rename ProjectFish/Source/ProjectFishEditor/Public/{Thimbnail => Thumbnail}/BagShapeAssetThumbnailRenderer.h (100%) create mode 100644 ProjectFish/Source/ProjectFishEditor/Public/Widgets/BagConfigEditorWidget.h diff --git a/ProjectFish/Source/ProjectFishEditor/Private/AssetEditor/BagConfigAssetEditor.cpp b/ProjectFish/Source/ProjectFishEditor/Private/AssetEditor/BagConfigAssetEditor.cpp index e594649..a76df85 100644 --- a/ProjectFish/Source/ProjectFishEditor/Private/AssetEditor/BagConfigAssetEditor.cpp +++ b/ProjectFish/Source/ProjectFishEditor/Private/AssetEditor/BagConfigAssetEditor.cpp @@ -3,6 +3,7 @@ #include "AssetEditor/BagConfigAssetEditor.h" #include "ProjectFish/DataAsset/BagConfigAsset.h" +#include "Widgets/BagConfigEditorWidget.h" const FName FBagConfigAssetEditor::BagConfigEditorTabId(TEXT("BagConfigEditor")); @@ -63,11 +64,12 @@ void FBagConfigAssetEditor::UnregisterTabSpawners(const TSharedRef& TSharedRef FBagConfigAssetEditor::SpawnBagConfigEditorTab(const FSpawnTabArgs& Args) { - // return SNew(SDockTab) - // .TabRole(ETabRole::PanelTab) - // [ - // SNew(SBagShapeEditorWidget) - // .BagShapeAsset(BagShapeAsset) - // ]; - return SNew(SDockTab); + return SNew(SDockTab) + .TabRole(ETabRole::NomadTab) + .Label(FText::FromString(FString::Printf(TEXT("Bag Class Editor - %s"), *BagConfigAsset->GetName()))) + [ + SNew(SBagConfigEditorWidget) + .BagConfigAsset(BagConfigAsset) + ]; + } diff --git a/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp b/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp index 4ae8b79..26fa3b0 100644 --- a/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp +++ b/ProjectFish/Source/ProjectFishEditor/Private/ProjectFishEditor.cpp @@ -6,7 +6,7 @@ #include "AssetActions/BagShapeAssetTypeAction.h" #include "AssetRegistry/AssetRegistryModule.h" #include "ProjectFish/DataAsset/BagShapeAsset.h" -#include "Thimbnail/BagShapeAssetThumbnailRenderer.h" +#include "../Public/Thumbnail/BagShapeAssetThumbnailRenderer.h" #define LOCTEXT_NAMESPACE "FProjectFishEditorModule" diff --git a/ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp b/ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp index 7bd2dce..81d265c 100644 --- a/ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp +++ b/ProjectFish/Source/ProjectFishEditor/Private/Thimbnail/BagShapeAssetThumbnailRenderer.cpp @@ -1,7 +1,7 @@ // Fill out your copyright notice in the Description page of Project Settings. -#include "Thimbnail/BagShapeAssetThumbnailRenderer.h" +#include "ProjectFishEditor/Public/Thumbnail/BagShapeAssetThumbnailRenderer.h" #include "CanvasItem.h" #include "CanvasTypes.h" diff --git a/ProjectFish/Source/ProjectFishEditor/Private/Widgets/BagConfigEditorWidget.cpp b/ProjectFish/Source/ProjectFishEditor/Private/Widgets/BagConfigEditorWidget.cpp new file mode 100644 index 0000000..88cb0df --- /dev/null +++ b/ProjectFish/Source/ProjectFishEditor/Private/Widgets/BagConfigEditorWidget.cpp @@ -0,0 +1,291 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Widgets/BagConfigEditorWidget.h" + +#include "PropertyCustomizationHelpers.h" +#include "Framework/Notifications/NotificationManager.h" +#include "ProjectFish/DataAsset/BagShapeAsset.h" +#include "Widgets/Notifications/SNotificationList.h" + + +void SBagConfigEditorWidget::Construct(const FArguments& InArgs) +{ + BagConfig = InArgs._BagConfigAsset; + SelectedSkillAsset = nullptr; + bIsPlacingSkill = false; + SelectedSkillIndex = -1; + + ChildSlot + [ + SNew(SVerticalBox) + + // BagShapeAsset 选择器 + + SVerticalBox::Slot() + .AutoHeight() + .Padding(5.0f) + [ + SNew(SHorizontalBox) + + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + .Padding(0, 0, 10, 0) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("背包形状:"))) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 10)) + ] + + + SHorizontalBox::Slot() + .FillWidth(1.0f) + [ + SNew(SObjectPropertyEntryBox) + .ObjectPath_Lambda([this]() + { + return BagConfig.IsValid() && BagConfig->BagShapeAsset ? + BagConfig->BagShapeAsset->GetPathName() : FString(); + }) + .AllowedClass(UBagShapeAsset::StaticClass()) + .OnObjectChanged(this, &SBagConfigEditorWidget::OnBagShapeAssetChanged) + .DisplayUseSelected(true) + .DisplayBrowse(true) + .DisplayThumbnail(false) + ] + ] + + // 技能资源 选择器 + + SVerticalBox::Slot() + .AutoHeight() + .Padding(5.0f) + [ + SNew(SHorizontalBox) + + + SHorizontalBox::Slot() + .AutoWidth() + .VAlign(VAlign_Center) + .Padding(0, 0, 10, 0) + [ + SNew(STextBlock) + .Text(FText::FromString(TEXT("选择要添加的技能:"))) + .Font(FCoreStyle::GetDefaultFontStyle("Bold", 10)) + ] + + + SHorizontalBox::Slot() + .FillWidth(1.0f) + [ + SNew(SObjectPropertyEntryBox) + .ObjectPath_Lambda([this]() + { + return SelectedSkillAsset.IsValid() ? + SelectedSkillAsset->GetPathName() : FString(); + }) + .AllowedClass(USkillAsset::StaticClass()) + .OnObjectChanged(this, &SBagConfigEditorWidget::OnSkillAssetChanged) + .DisplayUseSelected(true) + .DisplayBrowse(true) + .DisplayThumbnail(false) + ] + ] + + // // 工具栏 + // + SVerticalBox::Slot() + // .AutoHeight() + // .Padding(5.0f) + // [ + // SNew(SHorizontalBox) + // + // + SHorizontalBox::Slot() + // .AutoWidth() + // .Padding(2.0f) + // [ + // SNew(SButton) + // .Text(FText::FromString(TEXT("Add Skill"))) + // .OnClicked(this, &SBagClassEditor::OnAddSkillClicked) + // .IsEnabled_Lambda([this]() { return BagClass.IsValid() && BagClass->BagShapeAsset != nullptr && SelectedSkillObject.IsValid(); }) + // ] + // + // + SHorizontalBox::Slot() + // .AutoWidth() + // .Padding(2.0f) + // [ + // SNew(SButton) + // .Text(FText::FromString(TEXT("Remove Selected"))) + // .OnClicked(this, &SBagClassEditor::OnRemoveSkillClicked) + // .IsEnabled_Lambda([this]() { return SelectedSkillObject.IsValid(); }) + // ] + // + // + SHorizontalBox::Slot() + // .AutoWidth() + // .Padding(2.0f) + // [ + // SNew(SButton) + // .Text(FText::FromString(TEXT("Clear All"))) + // .OnClicked(this, &SBagClassEditor::OnClearAllSkillsClicked) + // .IsEnabled_Lambda([this]() { return BagClass.IsValid() && BagClass->GetSkillCount() > 0; }) + // ] + // ] + // + // // 主编辑区域 + // + SVerticalBox::Slot() + // .FillHeight(1.0f) + // [ + // SNew(SSplitter) + // .Orientation(Orient_Horizontal) + // + // // 左侧:背包格子视图 + // + SSplitter::Slot() + // .Value(0.7f) + // [ + // SNew(SBox) + // .HAlign(HAlign_Center) + // .VAlign(VAlign_Center) + // .Padding(10.0f) + // [ + // SNew(SVerticalBox) + // + // + SVerticalBox::Slot() + // .AutoHeight() + // .HAlign(HAlign_Center) + // .Padding(0, 0, 0, 10) + // [ + // SNew(STextBlock) + // .Text_Lambda([this]() + // { + // if (!BagClass.IsValid()) + // { + // return FText::FromString(TEXT("No Bag Class")); + // } + // else if (!BagClass->BagShapeAsset) + // { + // return FText::FromString(TEXT("Please select a Bag Shape Asset above")); + // } + // else + // { + // return FText::FromString(FString::Printf(TEXT("Bag: %s (%dx%d)"), + // *BagClass->BagShapeAsset->GetName(), + // BagClass->BagShapeAsset->BagWidth, + // BagClass->BagShapeAsset->BagHeight)); + // } + // }) + // .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) + // .ColorAndOpacity_Lambda([this]() + // { + // return (!BagClass.IsValid() || !BagClass->BagShapeAsset) ? + // FSlateColor(FLinearColor::Red) : FSlateColor(FLinearColor::White); + // }) + // ] + // + // + SVerticalBox::Slot() + // .AutoHeight() + // .HAlign(HAlign_Center) + // [ + // SAssignNew(BagGridWidget, SBagGridWidget) + // .BagClass(BagClass.Get()) + // .OnGridCellClicked(this, &SBagClassEditor::OnGridCellClicked) + // .Visibility_Lambda([this]() + // { + // return (BagClass.IsValid() && BagClass->BagShapeAsset) ? + // EVisibility::Visible : EVisibility::Hidden; + // }) + // ] + // ] + // ] + // + // // 右侧:技能列表 + // + SSplitter::Slot() + // .Value(0.3f) + // [ + // SNew(SVerticalBox) + // + // + SVerticalBox::Slot() + // .AutoHeight() + // .Padding(5.0f) + // [ + // SNew(STextBlock) + // .Text(FText::FromString(TEXT("Placed Skills:"))) + // .Font(FCoreStyle::GetDefaultFontStyle("Bold", 12)) + // ] + // + // + SVerticalBox::Slot() + // .FillHeight(1.0f) + // .Padding(5.0f) + // [ + // SAssignNew(SkillListWidget, SSkillListWidget) + // .BagClass(BagClass.Get()) + // .OnSkillSelected(this, &SBagClassEditor::OnSkillSelected) + // ] + // ] + //] + ]; + + RefreshUI(); +} + +void SBagConfigEditorWidget::OnBagShapeAssetChanged(const FAssetData& AssetData) +{ + if (!BagConfig.IsValid()) + { + return; + } + + // 获取新选择的BagShapeAsset + UBagShapeAsset* NewBagShapeAsset = Cast(AssetData.GetAsset()); + + // 如果选择了不同的资源,清空现有技能并更新引用 + if (BagConfig->BagShapeAsset != NewBagShapeAsset) + { + // 清空现有技能(因为新的背包形状可能不兼容) + if (NewBagShapeAsset && BagConfig->GetSkillCount() > 0) + { + BagConfig->ClearAllSkills(); + ShowWarningMessage(TEXT("Existing skills cleared due to bag shape change")); + } + + // 更新BagShapeAsset引用 + BagConfig->BagShapeAsset = NewBagShapeAsset; + + // 标记资源为已修改 + BagConfig->MarkPackageDirty(); + + // 刷新UI + RefreshUI(); + + if (NewBagShapeAsset) + { + ShowWarningMessage(FString::Printf(TEXT("Bag shape set to: %s"), *NewBagShapeAsset->GetName())); + } + else + { + ShowWarningMessage(TEXT("Bag shape asset cleared")); + } + } +} + +void SBagConfigEditorWidget::OnSkillAssetChanged(const FAssetData& AssetData) +{ + SelectedSkillAsset = Cast(AssetData.GetAsset()); +} + +void SBagConfigEditorWidget::RefreshUI() +{ + // if (BagGridWidget.IsValid()) + // { + // BagGridWidget->RefreshGrid(); + // } + // + // if (SkillListWidget.IsValid()) + // { + // SkillListWidget->RefreshSkillList(); + // } +} + +void SBagConfigEditorWidget::ShowWarningMessage(const FString& Message) +{ + FNotificationInfo Info(FText::FromString(Message)); + Info.bFireAndForget = true; + Info.FadeOutDuration = 3.0f; + Info.ExpireDuration = 3.0f; + + FSlateNotificationManager::Get().AddNotification(Info); +} diff --git a/ProjectFish/Source/ProjectFishEditor/ProjectFishEditor.Build.cs b/ProjectFish/Source/ProjectFishEditor/ProjectFishEditor.Build.cs index 0abec18..3a5573a 100644 --- a/ProjectFish/Source/ProjectFishEditor/ProjectFishEditor.Build.cs +++ b/ProjectFish/Source/ProjectFishEditor/ProjectFishEditor.Build.cs @@ -24,7 +24,8 @@ public class ProjectFishEditor : ModuleRules "InputCore", "AssetTools", "UnrealEd", - "EditorStyle" + "EditorStyle", + "PropertyEditor" } ); } diff --git a/ProjectFish/Source/ProjectFishEditor/Public/Thimbnail/BagShapeAssetThumbnailRenderer.h b/ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagShapeAssetThumbnailRenderer.h similarity index 100% rename from ProjectFish/Source/ProjectFishEditor/Public/Thimbnail/BagShapeAssetThumbnailRenderer.h rename to ProjectFish/Source/ProjectFishEditor/Public/Thumbnail/BagShapeAssetThumbnailRenderer.h diff --git a/ProjectFish/Source/ProjectFishEditor/Public/Widgets/BagConfigEditorWidget.h b/ProjectFish/Source/ProjectFishEditor/Public/Widgets/BagConfigEditorWidget.h new file mode 100644 index 0000000..4673655 --- /dev/null +++ b/ProjectFish/Source/ProjectFishEditor/Public/Widgets/BagConfigEditorWidget.h @@ -0,0 +1,64 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "ProjectFish/DataAsset/BagConfigAsset.h" + +/** + * + */ +class PROJECTFISHEDITOR_API SBagConfigEditorWidget: public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SBagConfigEditorWidget) {} + SLATE_ARGUMENT(UBagConfigAsset*, BagConfigAsset) +SLATE_END_ARGS() + + void Construct(const FArguments& InArgs); + + // // 设置要编辑的背包类 + // void UpdateBagConfig(UBagConfigAsset* InBagConfig); + +private: + + TWeakObjectPtr BagConfig; + + // 当前选中的技能对象 + TWeakObjectPtr SelectedSkillAsset; + + // 是否处于放置模式 + bool bIsPlacingSkill; + + // 选中的技能索引 + int32 SelectedSkillIndex; + + // UI组件 + TSharedPtr BagGridWidget; + //TSharedPtr SkillListWidget; + + // // 回调函数 + // FReply OnAddSkillClicked(); + // FReply OnRemoveSkillClicked(); + // FReply OnClearAllSkillsClicked(); + + // BagShapeAsset选择回调 + void OnBagShapeAssetChanged(const FAssetData& AssetData); + + // 技能选择回调 + void OnSkillAssetChanged(const FAssetData& AssetData); + + // // 技能选择回调 + // void OnSkillSelected(int32 SkillIndex); + // + // // 格子点击回调 + // void OnGridCellClicked(int32 X, int32 Y); + + // 刷新UI + void RefreshUI(); + + // 显示警告消息 + void ShowWarningMessage(const FString& Message); +}; + +