Files
UnrealEngine/Engine/Source/Programs/Enterprise/Datasmith/DatasmithARCHICADExporter/Private/SyncDatabase.h
2025-05-18 13:04:45 +08:00

297 lines
7.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Utils/AddonTools.h"
#include "Utils/LibPartInfo.h"
#include "Lock.hpp"
#include "ModelElement.hpp"
#include "Map.h"
#include "List.h"
BEGIN_NAMESPACE_UE_AC
class FSyncContext;
class FSyncData;
class FMaterialsDatabase;
class FTexturesCache;
class FElementID;
class FLibPartInfo;
class FMeshClass;
class FSyncDatabase;
class FMeshDimensions
{
public:
FMeshDimensions()
: Area(0.0f)
, Width(0.0f)
, Height(0.0f)
, Depth(0.0f)
{
}
FMeshDimensions(const IDatasmithMeshElement& InMesh)
: Area(InMesh.GetArea())
, Width(InMesh.GetWidth())
, Height(InMesh.GetHeight())
, Depth(InMesh.GetDepth())
{
}
float Area;
float Width;
float Height;
float Depth;
};
class FMeshClass
{
public:
// ARCHICAD 3D Element hash value
GS::ULong Hash = 0;
// Datasmith mesh element created for this class
TSharedPtr< IDatasmithMeshElement > MeshElement;
// Number of actor elements that are implementations of this class.
GS::UInt32 InstancesCount = 1;
// Next fields are for invariants tests
// Type of first ARCHICAD 3D Element collected for this hash
ModelerAPI::Element::Type ElementType;
// Number of elements that define transformation.
GS::UInt32 TransformCount = 0;
// Return the mesh element created for first converted element.
const TSharedPtr< IDatasmithMeshElement >& GetMeshElement() const { return MeshElement; }
bool bMeshElementInitialized = false;
// Define the mesh element for this hash value
void SetMeshElement(const TSharedPtr< IDatasmithMeshElement >& InMeshElement);
// Add an instance, waiting for the resulting mesh
enum EBuildMesh
{
kDontBuild,
kBuild
};
EBuildMesh AddInstance(FSyncData* InInstance, FSyncDatabase* IOSyncDatabase);
// Pop an instance waiting for the resulting mesh
FSyncData* PopInstance();
// Set Mesh Element to the sync data
void SetInstanceMesh(FSyncData* InInstance, FSyncDatabase* IOSyncDatabase) const;
// Set Mesh Element to the sync data
void SetWaitingInstanceMesh(FSyncDatabase* IOSyncDatabase);
FVector Translation;
FQuat Rotation;
private:
typedef TList< FSyncData* > FSyncDataList;
FSyncDataList* HeadInstances;
// Control access on this object (for queue operations)
static GS::Lock AccessControl;
// Condition variable
static GS::Condition CV;
};
class FMeshCacheIndexor
{
public:
// Constructor
FMeshCacheIndexor(const TCHAR* InIndexFilePath);
// Destructor
~FMeshCacheIndexor();
// Return the mesh dimension if mesh is already created.
const FMeshDimensions* FindMesh(const TCHAR* InMeshName) const;
// Add this mesh to the indexor
void AddMesh(const IDatasmithMeshElement& InMesh);
// If changed, save the indexor to the specified file.
void SaveToFile();
// Read the indexor from the specified file
void ReadFromFile();
private:
// We index with mesh name (aka. Hash of the mesh), and we save it's dimensions
typedef TMap< FString, TUniquePtr< FMeshDimensions > > MapName2Dimensions;
FString IndexFilePath;
// Indexor
MapName2Dimensions Name2Dimensions;
// Flag to know if we must save
bool bChanged = false;
// Control access on this object
mutable GS::Lock AccessControl;
// Condition variable
GS::Condition AccessCondition;
};
// Class that maintain synchronization datas (SyncData, Material, Texture)
class FSyncDatabase
{
public:
// Constructor
FSyncDatabase(const TCHAR* InSceneName, const TCHAR* InSceneLabel, const TCHAR* InAssetsPath,
const GS::UniString& InAssetsCache);
// Destructor
~FSyncDatabase();
// SetSceneInfo
void SetSceneInfo();
// Synchronize
void Synchronize(const FSyncContext& InSyncContext);
// Get scene
const TSharedRef< IDatasmithScene >& GetScene() const { return Scene; }
// Return the asset file path
const TCHAR* GetAssetsFolderPath() const;
// Get access to material database
FMaterialsDatabase& GetMaterialsDatabase() const { return *MaterialsDatabase; }
// Get access to textures cache
FTexturesCache& GetTexturesCache() const { return *TexturesCache; }
// Before a scan we reset our sync data, so we can detect when an element has been modified or destroyed
void ResetBeforeScan();
// After a scan, but before syncing, we delete obsolete syncdata (and it's Datasmith Element)
void CleanAfterScan();
// Get existing sync data for the specified guid
// If null, you must create it.
FSyncData*& GetSyncData(const GS::Guid& InGuid);
// Return scene sync data (Create it if not present)
FSyncData& GetSceneSyncData();
// Return layer sync data (Create it if not present)
FSyncData& GetLayerSyncData(short InLayer);
#if AC_VERSION > 26
FSyncData& GetLayerSyncData(const API_AttributeIndex& InLayer)
{
return GetLayerSyncData(short(InLayer.ToInt32_Deprecated()));
}
#endif
// Delete obsolete syncdata (and it's Datasmith Element)
void DeleteSyncData(const GS::Guid& InGuid);
// Return the name of the specified layer
const FString& GetLayerName(short InLayerIndex);
// Set the mesh in the handle and take care of mesh life cycle.
bool SetMesh(TSharedPtr< IDatasmithMeshElement >* Handle, const TSharedPtr< IDatasmithMeshElement >& InMesh);
// Return the libpart from it's index
FLibPartInfo* GetLibPartInfo(GS::Int32 InIndex);
// Return the libpart from it's unique id
FLibPartInfo* GetLibPartInfo(const char* InUnID);
FMeshClass* GetMeshClass(GS::ULong InHash) const;
void AddInstance(GS::ULong InHash, TUniquePtr< FMeshClass >&& InInstance);
// Return the cache path
static GS::UniString GetCachePath();
#if PLATFORM_MAC
// Change the cache path
static void SetCachePath(GS::UniString& InCacheDirectory);
#endif
FMeshCacheIndexor& GetMeshIndexor() { return MeshIndexor; }
private:
typedef TMap< FGuid, FSyncData* > FMapGuid2SyncData;
typedef TMap< short, FString > FMapLayerIndex2Name;
typedef TMap< GS::Int32, TUniquePtr< FLibPartInfo > > MapIndex2LibPart;
typedef TMap< FGSUnID, FLibPartInfo* > MapUnId2LibPart;
typedef GS::HashTable< GS::ULong, TUniquePtr< FMeshClass > > HashTableMeshClasses;
// To take care of mesh life cycle.
class FMeshInfo
{
public:
TSharedPtr< IDatasmithMeshElement > Mesh; // The mesh
uint32 Count = 0; // Number of actors using this mesh
FMeshInfo() {}
};
// Map mesh by their hash name.
typedef TMap< FString, FMeshInfo > FMapHashToMeshInfo;
void ResetMeshClasses();
void CleanMeshClasses(const FSyncContext& InSyncContext);
void ReportMeshClasses() const;
// Scan all elements, to determine if they need to be synchronized
UInt32 ScanElements(const FSyncContext& InSyncContext);
// Scan all lights
void ScanLights(FElementID& InElementID);
// Scan all cameras
void ScanCameras(const FSyncContext& InSyncContext);
// The scene
TSharedRef< IDatasmithScene > Scene;
// Path where to save assets
FString AssetsFolderPath;
// Fast access to material
FMaterialsDatabase* MaterialsDatabase;
// Cache to have fast access to textures
FTexturesCache* TexturesCache;
// Map guid to sync data
FMapGuid2SyncData ElementsSyncDataMap;
// Map layer index to it's name
FMapLayerIndex2Name LayerIndex2Name;
// Map mesh name (hash) to mesh info
FMapHashToMeshInfo HashToMeshInfo;
GS::Lock HashToMeshInfoAccesControl;
// Map lib part by index
MapIndex2LibPart IndexToLibPart;
// Map lib part by UnId
MapUnId2LibPart UnIdToLibPart;
HashTableMeshClasses MeshClasses;
FMeshCacheIndexor MeshIndexor;
};
END_NAMESPACE_UE_AC