Files
UnrealEngine/Engine/Source/Runtime/TextureUtilitiesCommon/Private/UDIMUtilities.cpp
2025-05-18 13:04:45 +08:00

112 lines
3.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UDIMUtilities.h"
#include "Internationalization/Regex.h"
#include "Misc/Paths.h"
#include "HAL/FileManager.h"
namespace UE
{
namespace TextureUtilitiesCommon
{
uint32 ParseUDIMName(const FString& Name, const FString& UdimRegexPattern, FString& OutPrefixName, FString& OutPostfixName)
{
FRegexPattern RegexPattern( UdimRegexPattern );
FRegexMatcher RegexMatcher( RegexPattern, Name );
int32 UdimValue = INDEX_NONE;
if ( RegexMatcher.FindNext() )
{
const int32 StartOfCaptureGroup1 = RegexMatcher.GetCaptureGroupBeginning(1);
const int32 EndOfCaptureGroup1 = RegexMatcher.GetCaptureGroupEnding(1);
const int32 StartOfCaptureGroup2 = RegexMatcher.GetCaptureGroupBeginning(2);
const int32 EndOfCaptureGroup2 = RegexMatcher.GetCaptureGroupEnding(2);
const int32 StartOfCaptureGroup3 = RegexMatcher.GetCaptureGroupBeginning(3);
const int32 EndOfCaptureGroup3 = RegexMatcher.GetCaptureGroupEnding(3);
if ( StartOfCaptureGroup1 != INDEX_NONE && StartOfCaptureGroup2 != INDEX_NONE &&
EndOfCaptureGroup1 != INDEX_NONE && EndOfCaptureGroup2 != INDEX_NONE )
{
LexFromString( UdimValue, *Name.Mid( StartOfCaptureGroup2, EndOfCaptureGroup2 - StartOfCaptureGroup2 ) );
OutPrefixName = Name.Mid( StartOfCaptureGroup1, EndOfCaptureGroup1 - StartOfCaptureGroup1 );
if ( StartOfCaptureGroup3 != INDEX_NONE && EndOfCaptureGroup3 != INDEX_NONE )
{
OutPostfixName = Name.Mid( StartOfCaptureGroup3, EndOfCaptureGroup3 - StartOfCaptureGroup3 );
}
}
}
if ( UdimValue < UDIM_Min_Index || UdimValue > UDIM_Max_Index )
{
return INDEX_NONE;
}
return UdimValue;
}
int32 GetUDIMIndex(int32 BlockX, int32 BlockY)
{
check( BlockX >= 0 && BlockX <= UDIM_Max_X );
check( BlockY >= 0 && BlockY <= UDIM_Max_Y );
int32 Ret = BlockY * 10 + BlockX + 1001;
check( Ret >= 1001 && Ret <= UDIM_Max_Index );
return Ret;
}
TMap<int32, FString> GetUDIMBlocksFromSourceFile(const FString& File, const FString& UdimRegexPattern, FString* OutFilenameWithoutUdimPatternAndExtension)
{
FString PreUDIMName;
FString PostUDIMName;
TMap<int32, FString> UDIMsAndSourcesFile;
if (ParseUDIMName(FPaths::GetBaseFilename(File), UdimRegexPattern, PreUDIMName, PostUDIMName) != INDEX_NONE)
{
const FString Path = FPaths::GetPath(File);
const FString UDIMFilter = (Path / PreUDIMName) + TEXT("*") + PostUDIMName + FPaths::GetExtension(File, true);
TArray<FString> UDIMFiles;
IFileManager::Get().FindFiles(UDIMFiles, *UDIMFilter, true, false);
UDIMFiles.Reserve(UDIMFiles.Num());
for (FString& UDIMFile : UDIMFiles)
{
const int32 UDIMIndex = ParseUDIMName(FPaths::GetBaseFilename(UDIMFile), UdimRegexPattern, PreUDIMName, PostUDIMName);
if (UDIMIndex != INDEX_NONE)
{
const FString UDIMName = PreUDIMName + PostUDIMName;
FString UDIMPath = FPaths::Combine(Path, UDIMFile);
UDIMsAndSourcesFile.Add(UDIMIndex, MoveTemp(UDIMPath));
}
}
if (!UDIMsAndSourcesFile.IsEmpty() && OutFilenameWithoutUdimPatternAndExtension)
{
*OutFilenameWithoutUdimPatternAndExtension = PreUDIMName + PostUDIMName;
}
}
return UDIMsAndSourcesFile;
}
void ExtractUDIMCoordinates(int32 UDIMIndex, int32& OutBlockX, int32& OutBlockY)
{
check( UDIMIndex != INDEX_NONE );
check( UDIMIndex >= UDIM_Min_Index && UDIMIndex <= UDIM_Max_Index );
// note 1010 is X=9, Y=0 , that is the tens column is not Y
OutBlockX = (UDIMIndex - UDIM_Min_Index) % 10;
OutBlockY = (UDIMIndex - UDIM_Min_Index) / 10;
check( OutBlockX >= 0 && OutBlockX <= UDIM_Max_X );
check( OutBlockY >= 0 && OutBlockY <= UDIM_Max_Y );
}
}
}