UE5.3 C++ 房屋管理系统(二)

news2025/5/16 21:09:47

三.当房屋生成成功,我们就需要把TMap里的数据存到数据库里。不然一点停止运行,就会所以数据都不见了。这里使用DataTable来存储。

1.DataTable是UE常用的表,虽然不是专门用来存档的,但也可以这么用。

DataTable表,实际是每一行的名字,对于每一行的内容。它可以根据你的结构体自动转换为表的每一行。

我们首先创造结构体,继承自TableRowBase。就是表行的基类,里面的数据类型,和TMap里BuildInfo保持一致,方便同步。

struct  FBuildTableStruct:public FTableRowBase
{
	
	GENERATED_USTRUCT_BODY();
	UPROPERTY(EditAnywhere)
	int ID = 0;

	//类型
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FString Type =  "";

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int Area = 100;
	//使用人数()
	//蓝图可访问通信
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int ResidentPopulation = 100;
	//价值()
//蓝图可访问通信
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int Pirce = 100;
	//位置
	//蓝图可访问通信
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector Position = FVector::Zero();
	//方位
	//蓝图可访问通信
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FRotator Rotation = FRotator::ZeroRotator;
	// 大小
	//蓝图可访问通信
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FVector Scale = FVector(1, 1, 1);

};

创建表,并选择表里的每一行的数据是上面的结构体。

表里的RowName,是系统自动添加的用于标识每一行。一开始表是空的,这是已经存入数据后的样子。

2.我们就写一个ATableManagerActor来管理存储。前面的是通用的,对表Tablet的数据进行增删查改。后面是根据不同的需求,封装了前面对表操作的功能。核心目的就是把 TMap里的数据,随时同步到Table里去。它们之间的主要是靠ID属性对应,RowName 保持和 ID相同。

 ATableManagerActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATableManagerActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	

	// Called every frame
	virtual void Tick(float DeltaTime) override;
	UFUNCTION(BlueprintCallable, DisplayName = "clearDataTable", Category = "DataTable")
	void clearDataTable(UDataTable* DataTable);
	UFUNCTION(BlueprintCallable, DisplayName = "addDataTableRow", Category = "DataTable")
	void addDataTableRow(UDataTable* DataTable, FName rowName, const FBuildTableStruct& row);
	UFUNCTION(BlueprintCallable, DisplayName = "removeDataTableRow", Category = "DataTable")
	void removeDataTableRow(UDataTable* DataTable, FName rowName);
	UFUNCTION(BlueprintCallable,DisplayName = "EditeDataTableRow",Category = "DataTable")
	void editeDataTableRow(FBuildTableStruct tmp);


	//从表里拿所有的信息
	UFUNCTION(BlueprintCallable, DisplayName = "findAllRow", Category = "DataTable")
	void findAllRow();

	//从表里拿删除所有的信息
	UFUNCTION(BlueprintCallable, DisplayName = "findAllRow", Category = "DataTable")
	void deletAllRow();

	UFUNCTION(BlueprintCallable, DisplayName = "saveToALLTable", Category = "DataTable")
	void saveToALLTable();
	UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")
	void DataTableToCSV();

	UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")
	FBuildTableStruct GetBuildInfoFromDT(int ID);

	UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")
	void CommiteBuildInfo();

	UFUNCTION(BlueprintCallable, DisplayName = "Inittial", Category = "DataTable")
	void Inittial();

	UFUNCTION(BlueprintCallable, DisplayName = "ShowClickBuild",Category = "DataTable")
	void ShowClickBuildInfo(ABuildBase* curBuid);

	UFUNCTION()
	void SetBuildEditUI(ULZJUserWidget* UI);


	UPROPERTY()
	UDataTable* BuildInfoDataTable;
	UPROPERTY()
	TMap<int,FBuildTableStruct> Rows;
	UPROPERTY()
	UBuildManagerInstance* BuildManagerIns;
	UPROPERTY()
	UBuildFactory* BuildFactory;

	//
	UPROPERTY()
	ABuildBase* ClickBuild;
	UPROPERTY()
	FBuildTableStruct ClicBuildInfo;
	UPROPERTY()
	ULZJUserWidget* BuildEditUI;

	bool isClick;
};

3.我们开始实现,每一行数据存入表中。首先拿到表的资源,再拿到上篇文章的 房屋管理者。然后实现,对表的增删查改。当房屋管理者的TMap发生改变,也对表里的数据进行同样操作。

// Called when the game starts or when spawned
void ATableManagerActor::BeginPlay()
{
	Super::BeginPlay();
	BuildInfoDataTable = LoadObject<UDataTable>(this, TEXT("/Script/Engine.DataTable'/LZJCore/DTBuildInfo.DTBuildInfo'"));
	findAllRow();
	BuildManagerIns = GetWorld()->GetGameInstance()->GetSubsystem<UBuildManagerInstance>();
	BuildFactory = GetWorld()->GetGameInstance()->GetSubsystem<UBuildFactory>();

	//TArray<AActor*> TBActors;
	//UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATableManagerActor::StaticClass(), TBActors);
	TArray<UUserWidget*> Actors;
	//TArray<UUserWidget*>& FoundWidgets, TSubclassOf<UUserWidget> WidgetClass,
	UWidgetBlueprintLibrary::GetAllWidgetsOfClass(GetWorld(), Actors, ULZJUserWidget::StaticClass());
	if (!Actors.IsEmpty())
	{
		BuildEditUI = Cast<ULZJUserWidget>(Actors[0]);
	}
}

// Called every frame
void ATableManagerActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ATableManagerActor::clearDataTable(UDataTable* DataTable)
{
	if (DataTable == nullptr)
	{
		return;
	}

	DataTable->EmptyTable();
	DataTable->GetOutermost()->MarkPackageDirty();
}

void ATableManagerActor::addDataTableRow(UDataTable* DataTable, FName rowName, const FBuildTableStruct& row)
{
	if (DataTable == nullptr)
	{
		return;
	}

	DataTable->AddRow(rowName, row);
	DataTable->GetOutermost()->MarkPackageDirty();
}

void ATableManagerActor::removeDataTableRow(UDataTable* DataTable, FName rowName)
{
	if (DataTable == nullptr)
	{
		return;
	}

	DataTable->RemoveRow(rowName);
	DataTable->GetOutermost()->MarkPackageDirty();
}

void ATableManagerActor::editeDataTableRow(FBuildTableStruct tmp)
{
	if (BuildInfoDataTable->IsValidLowLevel())
	{
		FString Str = FString::FromInt(tmp.ID);  // 行名
		FName RowName = FName(Str);
		FBuildTableStruct* RowData = BuildInfoDataTable->FindRow<FBuildTableStruct>(RowName, TEXT("Context"));
		if (RowData)
		{
			RowData->Area = tmp.Area;
			RowData->Pirce = tmp.Pirce;
			RowData->ResidentPopulation = tmp.ResidentPopulation;
			//RowData->= tmp.Area;
			BuildInfoDataTable->MarkPackageDirty(); // 标记为需要保存
		}
	}

}



void ATableManagerActor::findAllRow()
{
	if (BuildInfoDataTable->IsValidLowLevel())
	{
		//BuildInfoDataTable->GetTableData();
		if (!BuildInfoDataTable) return;
		TArray<FName>  RowNames = BuildInfoDataTable->GetRowNames();

		for (const auto& Name : RowNames)
		{
			for (auto it : BuildInfoDataTable->GetRowMap())
			{
				FString rowName = (it.Key).ToString();
				//FBuildTableStruct为你的FStruct
				FBuildTableStruct* pRow = (FBuildTableStruct*)it.Value;
				//输出需根据你的FStruct进行调整
				//UE_LOG(LogTemp, Warning, TEXT("read by traversal --- RowName:%s, Name:%s, price:%d, introduct:%s"), *rowName, *(pRow->ID), pRow->ProductPrice, *(pRow->ProductIntroduce));
				Rows.Add(pRow->ID,*pRow);
			}
		}
	}
}

void ATableManagerActor::deletAllRow()
{

}

void ATableManagerActor::saveToALLTable()
{
	if (BuildInfoDataTable->IsValidLowLevel())
	{
		//BuildInfoDataTable->GetTableData();
		if (!BuildInfoDataTable) return;
		TArray<FName>  RowNames = BuildInfoDataTable->GetRowNames();
		TMap<int, ABuildBase*> Cpoy = BuildManagerIns->m_TargetMap;   //拷贝值
		for (auto& Elem : Cpoy)
		{
			ABuildBase* curBuildBase = Elem.Value;
			FBuildTableStruct* BuildInfo = new FBuildTableStruct(); //结构体
			BuildInfo->ID = curBuildBase->m_targetID;
			FString IntString = FString::FromInt(BuildInfo->ID);
			FName RowName = FName(*IntString);
			BuildInfo->Area = curBuildBase->m_Area;
			BuildInfo->ResidentPopulation = curBuildBase->m_ResidentPopulation;
			BuildInfo->Pirce = curBuildBase->m_Price;

			//BuildInfo->ResidentPopulation = curBuildBase->m_ResidentPopulation;
			BuildInfo->Type = curBuildBase->m_Type;
			BuildInfo->Position = curBuildBase->m_Position;
			BuildInfo->Rotation = curBuildBase->m_Rotation;
			BuildInfoDataTable->AddRow(RowName, *BuildInfo);
			
		}
		 保存为资产
		/*FString PackageName = TEXT("/Game/Data/DynamicDataTable");
		UPackage* Package = CreatePackage(*PackageName);
		DynamicDataTable->Rename(*FPaths::GetBaseFilename(PackageName), Package);

		Package->MarkPackageDirty();
		FAssetRegistryModule::AssetCreated(DynamicDataTable);

		FString PackageFileName = FPackageName::LongPackageNameToFilename(
			PackageName, FPackageName::GetAssetPackageExtension());

		bool bSaved = UPackage::SavePackage(
			Package,
			DynamicDataTable,
			RF_Public | RF_Standalone,
			*PackageFileName);

		if (bSaved)
		{
			UE_LOG(LogTemp, Log, TEXT("Dynamic DataTable saved successfully!"));
		}*/

		//UPackage* Package = FindPackage(nullptr, *FPackageName::FilenameToLongPackageName(BuildInfoDataTable->GetPathName()));
		//if (Package)
		//{
		//	Package->SetDirtyFlag(true);

			//const TSoftObjectPtr<UDataTable> SourceDataTable = BuildInfoDataTable;
		//UEditorAssetLibrary::SaveAsset(SourceDataTable, false);
		//}
		
	}
	/*Tarray<UPackage*>PackageToSave;
	PackageToSave.Add(Table->GetOutermost());
	FEditorFileUtils::EPromptReturnCode RetValue = FEditorFileUtils::PromptForCheckoutAndSave(PackageToSave, false, false);*/

	TArray<UPackage*> PackagesToSave;
	PackagesToSave.Add(BuildInfoDataTable->GetOutermost());
	FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, false, /*bPromptToSave=*/ false);
}

void ATableManagerActor::DataTableToCSV()
{
	FString Path = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");
	Path = FPaths::ConvertRelativePathToFull(*Path);
	FPlatformFileManager::Get().Get().GetPlatformFile().DeleteFile(*Path);
	if (BuildInfoDataTable)
	{
		FString CSVString = BuildInfoDataTable->GetTableAsCSV();
		FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");
		FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);
	}
}

FBuildTableStruct ATableManagerActor::GetBuildInfoFromDT(int ID)
{
	FBuildTableStruct tmp;
	if (BuildInfoDataTable->IsValidLowLevel())
	{
		FString Str = FString::FromInt(ID);  // 行名
		FName RowName = FName(Str);
		FBuildTableStruct* RowData = BuildInfoDataTable->FindRow<FBuildTableStruct>(RowName, TEXT("Context"));
		if (RowData)
		{
			// 使用找到的数据
			UE_LOG(LogTemp, Warning, TEXT("Health: %d"), RowData->ID);
			tmp = *RowData;
		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Row not found!"));
		}
	}
	return tmp;
}

void ATableManagerActor::CommiteBuildInfo()
{
	FBuildTableStruct tmp;
	
}

void ATableManagerActor::Inittial()
{
	findAllRow();
	//TMap<int, FBuildTableStruct> Rows;
	// 假设MyMap已有数据...
	//BuildManagerIns->InitialBuilds(Rows);
	//for (auto It = Rows.CreateIterator(); It; ++It) {
	//	int ID = It.Key();   // 获取键
	//	FBuildTableStruct Build = It.Value(); // 获取值
	//	//UE_LOG(LogTemp, Warning, TEXT("Key: %s, Value: %d"), *Key, Value);
	//}
	BuildFactory->InitialBuilds(Rows);
}


//拿到点击的 ID,并查表拿到它的建筑的信息》
void ATableManagerActor::ShowClickBuildInfo(ABuildBase* curBuid)
{
	if (curBuid->IsValidLowLevel())
	{
		int ID = curBuid->m_targetID;
		ClicBuildInfo = GetBuildInfoFromDT(ID);
		isClick = true;
		if (BuildEditUI)
		{
			BuildEditUI->ShowEditBuildInfo(ClicBuildInfo);
		}
	}
	else
	{
		return;
	}
	isClick = false;
}

void ATableManagerActor::SetBuildEditUI(ULZJUserWidget* UI)
{
	BuildEditUI = UI;
}

这里将DataTable 导入到CSV,使用的是DataTable里的API, GetTableAsCSV();

void ATableManagerActor::DataTableToCSV()
{
	FString Path = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");
	Path = FPaths::ConvertRelativePathToFull(*Path);
	FPlatformFileManager::Get().Get().GetPlatformFile().DeleteFile(*Path);
	if (BuildInfoDataTable)
	{
		FString CSVString = BuildInfoDataTable->GetTableAsCSV();
		FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");
		FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode1.101.0便携版|中英文|编辑器|安装教程

软件介绍 Visual Studio Code是微软推出的一个强大的代码编辑器&#xff0c;功能强大&#xff0c;操作简单便捷&#xff0c;还有着良好的用户界面&#xff0c;设计得很人性化&#xff0c;旨在为所有开发者提供一款专注于代码本身的免费的编辑器。 软件安装 1、 下载安装包…

Linux系统发布.net core程序

前端 前端用的Vue3&#xff0c;发布的话需要Nginx下载安装Nginx 麒麟&#xff1a;这里我麒麟用的是桌面版&#xff0c;我直接把操作流程写在下面&#xff0c;写的比较简单&#xff0c;具体的可以具体搜这一块内容学习一下。打包vue程序&#xff0c;通过MobaXterm将打包后的程序…

极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎

在生成式AI与行业大模型的双重驱动下&#xff0c;人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策&#xff0c;AI技术渗透至产品研发、运营的全链条&#xff0c;推动效率跃升与创新模式变革。然而&#xff0c;面对AI技术迭代的爆发期&#xff0…

对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景

文章目录 对比 HTTP-REST 与 gRPC&#xff1a;各自的优缺点以及适用的场景HTTP-REST 与 gRPC 的核心区别gRPC 的优缺点HTTP-REST 的优缺点适用场景 模糊点什么是 Protobuf&#xff1f;HTTP/2 会将 HTTP 消息拆分并封装为二进制帧&#xff0c;那还能过使用 HTTP/2 构建 RESTful …

Git - 1( 14000 字详解 )

一&#xff1a; Git 初识 1.1 提出问题 在工作或学习中&#xff0c;我们常常会面临文档管理的问题&#xff0c;尤其是在编写各种文档时。为了防止文档丢失或因更改失误而无法恢复&#xff0c;我们常常会创建多个版本的副本&#xff0c;例如&#xff1a;“报告-v1”、“报告-v…

TCPIP详解 卷1协议 九 广播和本地组播(IGMP 和 MLD)

9.1——广播和本地组播&#xff08;IGMP 和 MLD&#xff09; IPv4可以使用4种IP地址&#xff1a;单播&#xff08;unicast&#xff09;、任播&#xff08;anycast&#xff09;、组播&#xff08;multicast&#xff09;和广播&#xff08;broadcast&#xff09;。 IPv6可以使用…

16.1 - VDMA视频转发实验之TPG

文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项 4 软件设计4.1 注意事项4.2 工程源码4.2.1 main.c文件 1 实验任务 基于14.1&#xff0c;使用Xilinx TPG&#xff08;Test Pattern Generator&#xff09; IP提供视频源&#xff0c;将视频数据通过VDMA写入PS…

cocos creator 3.8 下的 2D 改动

在B站找到的系统性cocos视频教程,纯2D开发入门,链接如下: zzehz黑马程序员6天实战游戏开发微信小程序&#xff08;Cocos2d的升级版 CocosCreator JavaScript&#xff09;_哔哩哔哩_bilibili黑马程序员6天实战游戏开发微信小程序&#xff08;Cocos2d的升级版 CocosCreator Ja…

Unity光照笔记

问题 在做项目中遇到了播放中切换场景后地面阴影是纯黑的问题&#xff0c;不得不研究一下光照。先放出官方文档。 Lighting 窗口 - Unity 手册 播放中切换场景后地面阴影是纯黑 只有投到地面的阴影是纯黑的。且跳转到使用相同Terrain的场景没有问题。 相关文章&#xff1a…

嵌入式学习的第二十天-数据结构-调试+链表的一般操作

一、调试 1.一般调试 2.找段错误 二、链表的一般操作 1.单链表的修改 int ModifyLinkList(LinkList*ll,char*name,DATATYPE*data) {DATATYPE * tmp FindLinkList(ll, name);if(NULL tmp){return 1;}memcpy(tmp,data,sizeof(DATATYPE));return 0; } 2.单链表的销毁 int D…

家具制造行业的现状 质检LIMS如何赋能家具制造企业质检升级

在家具制造行业&#xff0c;从原木切割到成品出厂&#xff0c;质检环节贯穿始终 —— 木材含水率是否达标、板材甲醛释放量是否合规、涂层耐磨性能否通过标准…… 这些看似琐碎的检测项目&#xff0c;实则是企业把控产品品质、规避市场风险的核心关卡。传统人工质检模式在效率、…

idea整合maven环境配置

idea整合maven 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系列文章】&#xff1a;每个知识点&#xff0c;都是写出代码…

无偿帮写毕业论文(看不懂的可以私信博主)

以下教程教你如何利用相关网站和AI免费帮你写一个毕业论文。毕竟毕业论文只要过就行&#xff0c;脱产学习这么多年&#xff0c;终于熬出头了&#xff0c;完成毕设后有空就去多看看亲人好友&#xff0c;祝好&#xff01; 一、找一个论文模板 废话不多说&#xff0c;先上干货Ov…

小白成长之路-vim编辑

文章目录 Vim一、命令模式二、插入模式3.a:进入插入模式&#xff0c;在当前光标的后一个字符插入![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/fd293c3832ed49e2974abfbb63eeb5bb.png)4.o: 在当前光标的下一行插入5.i:在当前光标所在字符插入&#xff0c;返回命令模…

【常用算法:排序篇】7.算法魔法与面试秘籍:从趣味排序到实战通关

一、趣味排序算法&#xff1a;突破常规的思维火花 1. 睡眠排序&#xff08;Sleep Sort&#xff09;—— 时间维度的魔法 核心思想&#xff1a;利用多线程休眠时间模拟数值大小&#xff0c;自然输出有序结果。Python示例&#xff1a;import threading import timedef sleep_so…

Android | IOS — Solox性能测试

文章目录 Solox性能测试1. 前置条件2. 软件图片 Solox性能测试 1. 前置条件 安装Python:3.10.0以上版本&#xff1a; Windows&#xff1a;Python官网 安装 SoloX python -m solox2. 软件图片 软件图片 报告分析&#xff1a;

Midjourney 最佳创作思路与实战技巧深度解析【附提示词与学习资料包下载】

引言 在人工智能图像生成领域&#xff0c;Midjourney 凭借其强大的艺术表现力和灵活的创作模式&#xff0c;已成为设计师、艺术家和创意工作者的核心工具。作为 CSDN 博主 “小正太浩二”&#xff0c;我将结合多年实战经验&#xff0c;系统分享 Midjourney 的创作方法论&#x…

工具篇-扣子空间MCP,一键做游戏,一键成曲

一、登陆扣子空间 地址如下&#xff1a; 扣子空间 打开&#xff0c;然后登陆扣子 登陆之后快速开始&#xff1a; 二、生成游戏 小试牛刀&#xff0c;我们让它做一个打地鼠的游戏&#xff1a; 已经开始设计制作&#xff1a; 制作完成&#xff1a; 三、制作音乐 新…

5.6 - 5.9 MySQL

数据库&#xff1a;存储和管理数据的仓库DB。 数据库管理系统&#xff1a;操纵和管理数据库的大型软件DBMS。 关系型数据库 一个数据库内可以创建多张表&#xff0c;在一个表内能存放多个数据。 SQL语句&#xff1a; DDL&#xff1a; 存储字符串用varchar。&#xff08;类似于…

C# WinForm 如何高效地将大量数据从 CSV 文件导入 DataGridView

如果你有非常多的csv文件&#xff0c;每个文件包含N多行与M多列&#xff0c;如&#xff1a;18000 行和 27 列。现在&#xff0c;想制作一个 Windows 窗体应用程序&#xff0c;导入它们并在 datagridview 中显示&#xff0c;然后进行一些数学运算。可是&#xff0c;发现数据导入…