更新通信协议,添加角色菜单项

This commit is contained in:
997146918 2025-07-07 09:34:28 +08:00
parent 5737e415c9
commit 9fcd390366
8 changed files with 227 additions and 112 deletions

View File

@ -0,0 +1,5 @@
[/Script/AIGC.AIGCSetting]
ServerIP=127.0.0.1

View File

@ -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<ISettingsModule>("Settings");
if (!SettingsModule)
return;
const auto Section = SettingsModule->RegisterSettings("Project", "Plugins", "AIGC",
FText::FromString(TEXT("AIGC")),
FText::FromString(TEXT("AIGC Setting")),
GetMutableDefault<UAIGCSetting>());
#endif
}
void FAIGCModule::UnregisterSettings()
{
#if WITH_EDITOR
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
if (SettingsModule)
SettingsModule->UnregisterSettings("Project", "Plugins", "AIGC");
#endif
}
TSharedRef<SDockTab> FAIGCModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
TSharedRef<SDockTab> 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<SDockTab> FAIGCModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTab
];
}
TSharedRef<SDockTab> 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<UAIGCSetting>();
WebSocketManager = NewObject<UWebSocketManager>();
WebSocketManager->InitWebSocket(Settings.ServerIP);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FAIGCModule, AIGC)

View File

@ -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>(
// FAIServerData ServerData;
// FJsonObjectConverter::JsonObjectStringToUStruct<FAIServerData>(
// 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<FString>());
// 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<FNetProtocol>(
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<FString>());
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);
}

View File

@ -106,13 +106,23 @@ void SAIGCWindow::Construct(const FArguments& InArgs)
EActiveTimerReturnType SAIGCWindow::OnPostPaint(double X, float Arg)
{
WebSocketManager = NewObject<UWebSocketManager>();
WebSocketManager->InitWebSocket(*ServerIP->GetInputText());
//init websocket
FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
if (ModulePtr)
{
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());
}
void SAIGCWindow::HandleReceiveData(TArray<FString> AiMessages)
{
UE_LOG(LogTemp, Warning, TEXT("AI当前进度 %d/%d"), GeneratedCount, RequireGenerateCount);
//添加数据到dataTable中
if (AiMessages.Num() > 0)
{
FAIGCModule* ModulePtr = FModuleManager::GetModulePtr<FAIGCModule>("AIGC");
if (ModulePtr) {
FString DataPath = FString::Printf(TEXT("/Game/Test/%s.%s"), *DataName->GetInputText(), *DataName->GetInputText());
FString Final = "";
for (auto message: AiMessages)
if (ModulePtr)
{
Final += message + TEXT("|");
}
ModulePtr->CreateOrAddData(DataPath, Final);
}
ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson());
}
//是否生成足够数量
if (GeneratedCount < RequireGenerateCount)
{
GeneratedCount++;
WebSocketManager->SendData(GeneratePromptJson());
}
else
void SAIGCWindow::HandleReceiveData(FNetProtocol protocol)
{
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<FAIGCModule>("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<FAIGCModule>("AIGC");
// if (ModulePtr)
// {
// ModulePtr->GetWebSocketManager()->SendData(FNetCommand::AiChatGenerate, GeneratePromptJson());
// }
//
// }
// else
// {
// GeneratedCount = 0;
// GenerateButton->SetEnabled(true);
// UE_LOG(LogTemp, Warning, TEXT("生成结束!"));
// }
}

View File

@ -37,13 +37,22 @@ struct FNPCChatRow : public FTableRowBase {
class FAIGCModule : public IModuleInterface
{
public:
TSharedRef<SDockTab> OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs);
TSharedRef<SDockTab> OnSpawnAIChatTab(const FSpawnTabArgs& SpawnTabArgs);
TSharedRef<SDockTab> 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<class FUICommandList> PluginCommands;
class UWebSocketManager* WebSocketManager = nullptr;
};
#undef LOCTEXT_NAMESPACE

View File

@ -46,3 +46,37 @@ struct FAIServerData
UPROPERTY()
TArray<FString> messages;
};
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;
};

View File

@ -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<FString>);
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()

View File

@ -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<FString> String);
void HandleReceiveData(FNetProtocol protocol);
private:
FString GeneratePromptJson();
@ -39,6 +40,5 @@ protected:
TSharedPtr<SConfigItem_NumberSpin<int32>> GenerateCount; //生成数目
TSharedPtr<SButton> GenerateButton; //生成按钮
UPROPERTY()
class UWebSocketManager* WebSocketManager;
};