From 9fcd39036641c37fdb57ae6a4c95bde81ff8fe51 Mon Sep 17 00:00:00 2001 From: 997146918 <997146918@qq.com> Date: Mon, 7 Jul 2025 09:34:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=80=9A=E4=BF=A1=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=A7=92=E8=89=B2=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TestForAIGC/Config/DefaultAIGCSetting.ini | 5 + .../Plugins/AIGC/Source/AIGC/Private/AIGC.cpp | 122 +++++++++++------- .../Source/AIGC/Private/WebSocketManager.cpp | 62 +++++---- .../Source/AIGC/Private/Widget/AIGCWindow.cpp | 92 +++++++------ .../Plugins/AIGC/Source/AIGC/Public/AIGC.h | 11 +- .../AIGC/Source/AIGC/Public/Definations.h | 36 +++++- .../Source/AIGC/Public/WebSocketManager.h | 5 +- .../Source/AIGC/Public/Widget/AIGCWindow.h | 6 +- 8 files changed, 227 insertions(+), 112 deletions(-) create mode 100644 TestForAIGC/Config/DefaultAIGCSetting.ini diff --git a/TestForAIGC/Config/DefaultAIGCSetting.ini b/TestForAIGC/Config/DefaultAIGCSetting.ini new file mode 100644 index 0000000..6c25c0d --- /dev/null +++ b/TestForAIGC/Config/DefaultAIGCSetting.ini @@ -0,0 +1,5 @@ + + +[/Script/AIGC.AIGCSetting] +ServerIP=127.0.0.1 + diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/AIGC.cpp b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/AIGC.cpp index 31be888..acd5819 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/AIGC.cpp +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/AIGC.cpp @@ -2,42 +2,34 @@ #include "AIGC.h" +#include "AIGCSetting.h" #include "AIGCStyle.h" #include "AssetToolsModule.h" #include "FileHelpers.h" +#include "ISettingsModule.h" #include "LevelEditor.h" #include "ToolMenu.h" #include "ToolMenus.h" +#include "WebSocketManager.h" #include "AssetRegistry/AssetRegistryModule.h" #include "Misc/MessageDialog.h" #include "UObject/SavePackage.h" #include "Widget/AIGCWindow.h" +#include "Widget/CharacterWindow.h" #define LOCTEXT_NAMESPACE "FAIGCModule" #define AIGCWindowName FName("AIGC") +#define CharacterWindowName FName("Character") void FAIGCModule::StartupModule() { // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module - + RegeisterSettings(); //添加style FAIGCStyle::Initialize(); FAIGCStyle::ReloadTextures(); - // //注册Command - // FAIGCCommands::Register(); - // PluginCommands = MakeShareable(new FUICommandList); - // //绑定动作 - // PluginCommands->MapAction( - // FAIGCCommands::Get().MenuAction, - // FExecuteAction::CreateRaw(this, &FAIGCModule::MenuClicked), - // FCanExecuteAction()); - // - // PluginCommands->MapAction( - // FAIGCCommands::Get().SubMenuAction, - // FExecuteAction::CreateRaw(this, &FAIGCModule::SubMenuClicked), - // FCanExecuteAction()); //添加菜单 UToolMenu* menu = UToolMenus::Get()->FindMenu(FName("LevelEditor.MainMenu.AIGC")); if (!menu) @@ -62,16 +54,17 @@ void FAIGCModule::StartupModule() FGlobalTabmanager::Get()->TryInvokeTab(AIGCWindowName); }))); - // // 填充第二个子菜单项 - // FToolMenuSection& SubSection2 = SubMenu->AddSection( - // "SubSection2"); - // SubSection.AddMenuEntry( - // "Submenu2", - // LOCTEXT("Action1Label", "生成模型2"), - // LOCTEXT("Action1Tooltip", "触发模型生成2"), - // FSlateIcon(FAIGCStyle::GetStyleSetName(), "AIGCStyle.AIChat"), - // FToolUIActionChoice( - // FAIGCCommands::Get().SubMenuAction, *PluginCommands)); + //添加人员配置菜单 + FToolMenuSection& CharacterSection = SubMenu->AddSection("Character"); + SubSection.AddMenuEntry( + "Character", + LOCTEXT("Character", "角色配置"), + LOCTEXT("CharacterToolTip", ""), + FSlateIcon(FAIGCStyle::GetStyleSetName(), "AIGCStyle.AIChat"), + FUIAction(FExecuteAction::CreateLambda([this]() + { + FGlobalTabmanager::Get()->TryInvokeTab(CharacterWindowName); + }))); }), false, // 是否动态生成 FSlateIcon()); @@ -81,42 +74,54 @@ void FAIGCModule::StartupModule() } - //注册窗口 - FGlobalTabmanager::Get()->RegisterNomadTabSpawner(AIGCWindowName, FOnSpawnTab::CreateRaw(this, &FAIGCModule::OnSpawnPluginTab)) + //注册Chat窗口 + FGlobalTabmanager::Get()->RegisterNomadTabSpawner(AIGCWindowName, FOnSpawnTab::CreateRaw(this, &FAIGCModule::OnSpawnAIChatTab)) .SetDisplayName(LOCTEXT("AIGCWindow", "AIGCWindow")) .SetMenuType(ETabSpawnerMenuType::Hidden); + //注册角色窗口 + FGlobalTabmanager::Get()->RegisterNomadTabSpawner(CharacterWindowName, FOnSpawnTab::CreateRaw(this, &FAIGCModule::OnSpawnCharacterTab)) + .SetDisplayName(LOCTEXT("CharacterWindow", "CharacterWindow")) + .SetMenuType(ETabSpawnerMenuType::Hidden); } - -// void FAIGCModule::SubMenuClicked() -// { -// UE_LOG(LogTemp, Warning, TEXT("Generate Model")); -// FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("4444555")); -// } - - - - void FAIGCModule::ShutdownModule() { // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, // we call this function before unloading the module. + UnregisterSettings(); UToolMenus::UnregisterOwner(this); FAIGCStyle::Shutdown(); - //FAIGCCommands::Unregister(); + FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(AIGCWindowName); + FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(CharacterWindowName); +} + +void FAIGCModule::RegeisterSettings() +{ +#if WITH_EDITOR + ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings"); + if (!SettingsModule) + return; + + const auto Section = SettingsModule->RegisterSettings("Project", "Plugins", "AIGC", + FText::FromString(TEXT("AIGC")), + FText::FromString(TEXT("AIGC Setting")), + GetMutableDefault()); +#endif +} + +void FAIGCModule::UnregisterSettings() +{ +#if WITH_EDITOR + ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings"); + if (SettingsModule) + SettingsModule->UnregisterSettings("Project", "Plugins", "AIGC"); +#endif } - -TSharedRef FAIGCModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs) +TSharedRef FAIGCModule::OnSpawnAIChatTab(const FSpawnTabArgs& SpawnTabArgs) { - FText WidgetText = FText::Format( - LOCTEXT("WindowWidgetText", "Add code to {0} in {1} to override this window's contents"), - FText::FromString(TEXT("FTestModule::OnSpawnPluginTab")), - FText::FromString(TEXT("Test.cpp")) - ); - return SNew(SDockTab) .TabRole(ETabRole::NomadTab) [ @@ -130,6 +135,21 @@ TSharedRef FAIGCModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTab ]; } +TSharedRef FAIGCModule::OnSpawnCharacterTab(const FSpawnTabArgs& SpawnTabArgs) +{ + return SNew(SDockTab) + .TabRole(ETabRole::NomadTab) + [ + // Put your tab content here! + SNew(SBox) + .HAlign(HAlign_Center) + .VAlign(VAlign_Center) + [ + SNew(SCharacterWindow) + ] + ]; +} + void FAIGCModule::CreateOrAddData(const FString& DataTablePath, const FString& RowValue) { FString PackagePath, AssetName; @@ -158,6 +178,18 @@ void FAIGCModule::CreateOrAddData(const FString& DataTablePath, const FString& R UPackage::SavePackage(DataTable->GetPackage(), DataTable, *FilePath, SaveArgs); } + UWebSocketManager* FAIGCModule::GetWebSocketManager() +{ + return WebSocketManager; +} + +void FAIGCModule::InitWebSocketManager() +{ + auto& Settings = *GetDefault(); + WebSocketManager = NewObject(); + WebSocketManager->InitWebSocket(Settings.ServerIP); +} + #undef LOCTEXT_NAMESPACE IMPLEMENT_MODULE(FAIGCModule, AIGC) \ No newline at end of file diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/WebSocketManager.cpp b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/WebSocketManager.cpp index f2bd74d..6923321 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/WebSocketManager.cpp +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/WebSocketManager.cpp @@ -19,10 +19,16 @@ void UWebSocketManager::InitWebSocket(const FString& ServerIP) ,*ServerIP, *(FGuid::NewGuid().ToString()) ))); } -void UWebSocketManager::SendData(const FString& Data) +void UWebSocketManager::SendData(const FString& cmd, const FString& Data) { + //定义客户端协议 + FNetProtocol protocol; + protocol.cmd = cmd; + protocol.data = Data; + FString JsonString; + FJsonObjectConverter::UStructToJsonObjectString(protocol, JsonString); - WebSocketHandler->SendText(Data); + WebSocketHandler->SendText(JsonString); } void UWebSocketManager::HandleConnected() @@ -52,30 +58,38 @@ void UWebSocketManager::HandleOnMessageSend(const FString& Message) void UWebSocketManager::HandleOnReceiveText(const FString& Message) { - FAIServerData ServerData; - FJsonObjectConverter::JsonObjectStringToUStruct( + // FAIServerData ServerData; + // FJsonObjectConverter::JsonObjectStringToUStruct( + // Message, + // &ServerData, + // 0, // 检查标志位 + // 0 // 转换标志位 + // ); + // switch (ServerData.statusCode) + // { + // case -1: + // UE_LOG(LogTemp, Error, TEXT("ai server error reason = %s "), *ServerData.messages[0]); + // OnDataReceiveDelaget.Broadcast(TArray()); + // break; + // case 0: + // //normal heart tick + // break; + // case 1: + // UE_LOG(LogTemp, Warning, TEXT("Receive Text %s from WebSocket Server "), *Message); + // OnDataReceiveDelaget.Broadcast(ServerData.messages); + // break; + // case 2: + // UE_LOG(LogTemp, Error, TEXT("ai content generate format error,server is regerating..... ")); + // break; + // default: + // break; + // } + FNetProtocol serverProtocol; + FJsonObjectConverter::JsonObjectStringToUStruct( Message, - &ServerData, + &serverProtocol, 0, // 检查标志位 0 // 转换标志位 ); - switch (ServerData.statusCode) - { - case -1: - UE_LOG(LogTemp, Error, TEXT("ai server error reason = %s "), *ServerData.messages[0]); - OnDataReceiveDelaget.Broadcast(TArray()); - break; - case 0: - //normal heart tick - break; - case 1: - UE_LOG(LogTemp, Warning, TEXT("Receive Text %s from WebSocket Server "), *Message); - OnDataReceiveDelaget.Broadcast(ServerData.messages); - break; - case 2: - UE_LOG(LogTemp, Error, TEXT("ai content generate format error,server is regerating..... ")); - break; - default: - break; - } + OnDataReceiveDelaget.Broadcast(serverProtocol); } diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/Widget/AIGCWindow.cpp b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/Widget/AIGCWindow.cpp index 919784a..4435ac2 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/Widget/AIGCWindow.cpp +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Private/Widget/AIGCWindow.cpp @@ -106,13 +106,23 @@ void SAIGCWindow::Construct(const FArguments& InArgs) EActiveTimerReturnType SAIGCWindow::OnPostPaint(double X, float Arg) { - WebSocketManager = NewObject(); - WebSocketManager->InitWebSocket(*ServerIP->GetInputText()); - WebSocketManager->OnConnectDelegate.AddLambda([this](bool bSuccess) + //init websocket + FAIGCModule* ModulePtr = FModuleManager::GetModulePtr("AIGC"); + if (ModulePtr) { - GenerateButton->SetEnabled(bSuccess); - }); - WebSocketManager->OnDataReceiveDelaget.AddRaw(this, &SAIGCWindow::HandleReceiveData); + UWebSocketManager* WebSocketManager = ModulePtr->GetWebSocketManager(); + if (!WebSocketManager) + { + ModulePtr->InitWebSocketManager(); + WebSocketManager = ModulePtr->GetWebSocketManager(); + } + WebSocketManager->OnConnectDelegate.AddLambda([this](bool bSuccess) + { + GenerateButton->SetEnabled(bSuccess); + }); + WebSocketManager->OnDataReceiveDelaget.AddRaw(this, &SAIGCWindow::HandleReceiveData); + + } return EActiveTimerReturnType::Stop; } @@ -122,40 +132,50 @@ void SAIGCWindow::OnAIGenerateClicked() GenerateButton->SetEnabled(false); RequireGenerateCount = GenerateCount->GetNumber(); UE_LOG(LogTemp, Warning, TEXT("生成次数 %d prompt:%s"), RequireGenerateCount, *GeneratePromptJson()); - WebSocketManager->SendData(GeneratePromptJson()); + FAIGCModule* ModulePtr = FModuleManager::GetModulePtr("AIGC"); + if (ModulePtr) + { + ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson()); + } + } -void SAIGCWindow::HandleReceiveData(TArray AiMessages) +void SAIGCWindow::HandleReceiveData(FNetProtocol protocol) { - UE_LOG(LogTemp, Warning, TEXT("AI当前进度 %d/%d"), GeneratedCount, RequireGenerateCount); - //添加数据到dataTable中 - if (AiMessages.Num() > 0) - { - FAIGCModule* ModulePtr = FModuleManager::GetModulePtr("AIGC"); - if (ModulePtr) { - FString DataPath = FString::Printf(TEXT("/Game/Test/%s.%s"), *DataName->GetInputText(), *DataName->GetInputText()); - FString Final = ""; - for (auto message: AiMessages) - { - Final += message + TEXT("|"); - } - ModulePtr->CreateOrAddData(DataPath, Final); - } - } - - //是否生成足够数量 - if (GeneratedCount < RequireGenerateCount) - { - GeneratedCount++; - WebSocketManager->SendData(GeneratePromptJson()); - } - else - { - GeneratedCount = 0; - GenerateButton->SetEnabled(true); - UE_LOG(LogTemp, Warning, TEXT("生成结束!")); - } + // UE_LOG(LogTemp, Warning, TEXT("AI当前进度 %d/%d"), GeneratedCount, RequireGenerateCount); + // //添加数据到dataTable中 + // if (AiMessages.Num() > 0) + // { + // FAIGCModule* ModulePtr = FModuleManager::GetModulePtr("AIGC"); + // if (ModulePtr) { + // FString DataPath = FString::Printf(TEXT("/Game/Test/%s.%s"), *DataName->GetInputText(), *DataName->GetInputText()); + // FString Final = ""; + // for (auto message: AiMessages) + // { + // Final += message + TEXT("|"); + // } + // ModulePtr->CreateOrAddData(DataPath, Final); + // } + // } + // + // //是否生成足够数量 + // if (GeneratedCount < RequireGenerateCount) + // { + // GeneratedCount++; + // FAIGCModule* ModulePtr = FModuleManager::GetModulePtr("AIGC"); + // if (ModulePtr) + // { + // ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson()); + // } + // + // } + // else + // { + // GeneratedCount = 0; + // GenerateButton->SetEnabled(true); + // UE_LOG(LogTemp, Warning, TEXT("生成结束!")); + // } } diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/AIGC.h b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/AIGC.h index a4c83d8..ccd446b 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/AIGC.h +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/AIGC.h @@ -37,13 +37,22 @@ struct FNPCChatRow : public FTableRowBase { class FAIGCModule : public IModuleInterface { public: - TSharedRef OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs); + TSharedRef OnSpawnAIChatTab(const FSpawnTabArgs& SpawnTabArgs); + TSharedRef OnSpawnCharacterTab(const FSpawnTabArgs& SpawnTabArgs); //void SubMenuClicked(); /** IModuleInterface implementation */ virtual void StartupModule() override; virtual void ShutdownModule() override; + + void RegeisterSettings(); + void UnregisterSettings(); + void CreateOrAddData(const FString& DataTablePath, const FString& RowValue); + class UWebSocketManager* GetWebSocketManager(); + void InitWebSocketManager(); + private: TSharedPtr PluginCommands; + class UWebSocketManager* WebSocketManager = nullptr; }; #undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Definations.h b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Definations.h index c9a23a4..2c2163c 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Definations.h +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Definations.h @@ -45,4 +45,38 @@ struct FAIServerData int32 statusCode; UPROPERTY() TArray messages; -}; \ No newline at end of file +}; + +USTRUCT() +struct FCharacterInfo +{ + GENERATED_BODY() + FString name; + int32 age; + FString personality; + FString characterBackground; + FString chat_style; +}; + +USTRUCT() +struct FNetProtocol +{ + GENERATED_BODY() + UPROPERTY() + FString cmd; //命令名称 + UPROPERTY() + int32 status; //状态 + UPROPERTY() + FString message; //响应消息 + UPROPERTY() + FString data; //json数据 +}; + +USTRUCT() +struct FNetCommand +{ + GENERATED_BODY() + static FString CharacterList; + static FString AddCharacter; + static FString AiChatGenerate; +}; diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/WebSocketManager.h b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/WebSocketManager.h index 41aeeb3..ca251bf 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/WebSocketManager.h +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/WebSocketManager.h @@ -3,11 +3,12 @@ #pragma once #include "CoreMinimal.h" +#include "Definations.h" #include "UObject/Object.h" #include "WebSocketManager.generated.h" DECLARE_MULTICAST_DELEGATE_OneParam(FOnConnectDelegate, bool); -DECLARE_MULTICAST_DELEGATE_OneParam(FOnDataReceiveDelaget, TArray); +DECLARE_MULTICAST_DELEGATE_OneParam(FOnDataReceiveDelaget, FNetProtocol); /** * */ @@ -17,7 +18,7 @@ class AIGC_API UWebSocketManager : public UObject GENERATED_BODY() public: void InitWebSocket(const FString& ServerIP); - void SendData(const FString& Data); + void SendData(const FString& cmd, const FString& Data); UFUNCTION() void HandleConnected(); UFUNCTION() diff --git a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Widget/AIGCWindow.h b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Widget/AIGCWindow.h index 337b0cd..3d207f0 100644 --- a/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Widget/AIGCWindow.h +++ b/TestForAIGC/Plugins/AIGC/Source/AIGC/Public/Widget/AIGCWindow.h @@ -5,6 +5,7 @@ #include "CoreMinimal.h" #include "ConfigItem_NumberSpin.h" #include "ConfigItem_Text.h" +#include "Definations.h" /** * @@ -22,7 +23,7 @@ public: void OnAIGenerateClicked(); void InitWebClient(); - void HandleReceiveData(TArray String); + void HandleReceiveData(FNetProtocol protocol); private: FString GeneratePromptJson(); @@ -39,6 +40,5 @@ protected: TSharedPtr> GenerateCount; //生成数目 TSharedPtr GenerateButton; //生成按钮 - UPROPERTY() - class UWebSocketManager* WebSocketManager; + }; \ No newline at end of file