Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

210 lines
6.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GeometryCollection/ManagedArrayAccessor.h"
#include "GeometryCollection/ManagedArrayCollection.h"
// Note: Prefer namespace GeometryCollection::UV for new code
namespace GeometryCollectionUV
{
enum
{
MAX_NUM_UV_CHANNELS = 8,
};
}
namespace GeometryCollection::UV
{
// Names of each UV layer attribute. In a valid collection with UVs, the first layer must be present, and the other layers are optional
extern CHAOS_API const FName UVLayerNames[GeometryCollectionUV::MAX_NUM_UV_CHANNELS];
// The UV layers are always contained in the vertices group in a geometry collection
extern CHAOS_API const FName VerticesGroupName;
bool CHAOS_API HasValidUVs(const FManagedArrayCollection& Collection);
bool CHAOS_API SetNumUVLayers(FManagedArrayCollection& Collection, int32 NumUVs);
int32 CHAOS_API GetNumUVLayers(const FManagedArrayCollection& Collection);
void CHAOS_API DefineUVSchema(FManagedArrayCollection& Collection);
inline const TManagedArray<FVector2f>* FindUVLayer(const FManagedArrayCollection& Collection, int32 UVLayer)
{
return Collection.FindAttributeTyped<FVector2f>(UVLayerNames[UVLayer], VerticesGroupName);
}
inline TManagedArray<FVector2f>* FindUVLayer(FManagedArrayCollection& Collection, int32 UVLayer)
{
return Collection.FindAttributeTyped<FVector2f>(UVLayerNames[UVLayer], VerticesGroupName);
}
inline const TManagedArray<FVector2f>& GetUVLayer(const FManagedArrayCollection& Collection, int32 UVLayer)
{
checkSlow(UVLayer >= 0 && UVLayer < GeometryCollectionUV::MAX_NUM_UV_CHANNELS);
return Collection.GetAttribute<FVector2f>(UVLayerNames[UVLayer], VerticesGroupName);
}
inline TManagedArray<FVector2f>& ModifyUVLayer(FManagedArrayCollection& Collection, int32 UVLayer)
{
checkSlow(UVLayer >= 0 && UVLayer < GeometryCollectionUV::MAX_NUM_UV_CHANNELS);
return Collection.ModifyAttribute<FVector2f>(UVLayerNames[UVLayer], VerticesGroupName);
}
template<typename ManagedArrayType, int32 MaxArraySize>
struct TArrayOfAttributesAccessor
{
TArray<ManagedArrayType*, TFixedAllocator<MaxArraySize>> Attributes;
ManagedArrayType& operator[](int32 Idx) const
{
return *Attributes[Idx];
}
int32 Num() const
{
return Attributes.Num();
}
};
using FUVLayers = TArrayOfAttributesAccessor<TManagedArray<FVector2f>, 8>;
using FConstUVLayers = TArrayOfAttributesAccessor<const TManagedArray<FVector2f>, 8>;
/**
* Find the currently-valid UV layers for a given collection
* @return A temporary accessor for all the active UV layers. Must be recreated if the collection attributes are changed / the number of UV layers is changed.
*/
inline FUVLayers FindActiveUVLayers(FManagedArrayCollection& Collection)
{
FUVLayers Layers;
for (int32 LayerIdx = 0; LayerIdx < GeometryCollectionUV::MAX_NUM_UV_CHANNELS; ++LayerIdx)
{
TManagedArray<FVector2f>* Layer = Collection.FindAttributeTyped<FVector2f>(UVLayerNames[LayerIdx], VerticesGroupName);
if (!Layer)
{
break;
}
Layers.Attributes.Add(Layer);
}
return Layers;
}
/**
* Find the currently-valid UV layers for a given collection
* @return A temporary accessor for all the active UV layers. Must be recreated if the collection attributes are changed / the number of UV layers is changed.
*/
inline FConstUVLayers FindActiveUVLayers(const FManagedArrayCollection& Collection)
{
FConstUVLayers Layers;
for (int32 LayerIdx = 0; LayerIdx < GeometryCollectionUV::MAX_NUM_UV_CHANNELS; ++LayerIdx)
{
const TManagedArray<FVector2f>* Layer = Collection.FindAttributeTyped<FVector2f>(UVLayerNames[LayerIdx], VerticesGroupName);
if (!Layer)
{
break;
}
Layers.Attributes.Add(Layer);
}
return Layers;
}
// Set all UVs in the array for the given vertex, stopping early if there are not enough matching UV layers in the collection
inline void SetUVs(FManagedArrayCollection& Collection, int32 VertexIdx, TArrayView<const FVector2f> UVs)
{
for (int32 LayerIdx = 0; LayerIdx < UVs.Num(); ++LayerIdx)
{
TManagedArray<FVector2f>* Layer = FindUVLayer(Collection, LayerIdx);
if (!ensure(Layer != nullptr))
{
break;
}
(*Layer)[VertexIdx] = UVs[LayerIdx];
}
}
inline void MatchUVLayerCount(FManagedArrayCollection& ToCollection, const FManagedArrayCollection& FromCollection)
{
SetNumUVLayers(ToCollection, GetNumUVLayers(FromCollection));
}
}
namespace GeometryCollection::Facades
{
class FCollectionUVFacade
{
public:
FCollectionUVFacade(FManagedArrayCollection& InCollection) : Collection(&InCollection), ConstCollection(&InCollection)
{}
FCollectionUVFacade(const FManagedArrayCollection& InCollection) : Collection(nullptr), ConstCollection(&InCollection)
{}
/**
* returns true if all the necessary attributes are present
* if not then the API can be used to create
*/
inline bool IsValid() const
{
return GeometryCollection::UV::HasValidUVs(*ConstCollection);
}
/**
* Add the necessary attributes if they are missing
*/
void DefineSchema()
{
GeometryCollection::UV::DefineUVSchema(*Collection);
}
inline bool SetNumUVLayers(int32 UVLayers)
{
return GeometryCollection::UV::SetNumUVLayers(*Collection, UVLayers);
}
inline int32 GetNumUVLayers() const
{
return GeometryCollection::UV::GetNumUVLayers(*ConstCollection);
}
inline const TManagedArray<FVector2f>& GetUVLayer(int32 UVLayer) const
{
return GeometryCollection::UV::GetUVLayer(*ConstCollection, UVLayer);
}
inline TManagedArray<FVector2f>& ModifyUVLayer(int32 UVLayer)
{
return GeometryCollection::UV::ModifyUVLayer(*Collection, UVLayer);
}
inline const TManagedArray<FVector2f>* FindUVLayer(int32 UVLayer) const
{
return GeometryCollection::UV::FindUVLayer(*ConstCollection, UVLayer);
}
inline TManagedArray<FVector2f>* FindUVLayer(int32 UVLayer)
{
return GeometryCollection::UV::FindUVLayer(*Collection, UVLayer);
}
inline FVector2f& ModifyUV(int32 VertexIdx, int32 LayerIdx)
{
return ModifyUVLayer(LayerIdx)[VertexIdx];
}
inline const FVector2f& GetUV(int32 VertexIdx, int32 LayerIdx) const
{
return GetUVLayer(LayerIdx)[VertexIdx];
}
inline void SetUV(int32 VertexIdx, int32 LayerIdx, const FVector2f& UV)
{
ModifyUVLayer(LayerIdx)[VertexIdx] = UV;
}
inline GeometryCollection::UV::FUVLayers FindActiveUVLayers()
{
return GeometryCollection::UV::FindActiveUVLayers(*Collection);
}
inline GeometryCollection::UV::FConstUVLayers FindActiveUVLayers() const
{
return GeometryCollection::UV::FindActiveUVLayers(*ConstCollection);
}
// Set all UVs in the array for the given vertex, stopping early if there are not enough matching UV layers in the collection
inline void SetUVs(int32 VertexIdx, TArrayView<const FVector2f> UVs)
{
GeometryCollection::UV::SetUVs(*Collection, VertexIdx, UVs);
}
private:
FManagedArrayCollection* Collection;
const FManagedArrayCollection* ConstCollection;
};
}