2021-11-07 23:43:01 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# ifdef NEW_DIRECTLINK_PLUGIN
# include "DatasmithMaxDirectLink.h"
# include "DatasmithMaxHelper.h"
# include "DatasmithMaxWriter.h"
# include "DatasmithMaxClassIDs.h"
2022-03-24 10:41:30 -04:00
# include "MaxMaterialsToUEPbr/DatasmithMaxMaterialsToUEPbr.h"
2021-11-07 23:43:01 -05:00
# include "DatasmithSceneFactory.h"
# include "Logging/LogMacros.h"
# include "Windows/AllowWindowsPlatformTypes.h"
MAX_INCLUDES_START
# include "impexp.h"
# include "max.h"
MAX_INCLUDES_END
namespace DatasmithMaxDirectLink
{
// Copied from
// FDatasmithMaxSceneParser::MaterialEnum
// FDatasmithMaxSceneParser::TexEnum
// Collects actual materials that are used by the top-level material(assigned to node)
class FMaterialEnum
{
public :
FMaterialsCollectionTracker & MaterialsCollectionTracker ;
FMaterialTracker & MaterialTracker ;
FMaterialEnum ( FMaterialsCollectionTracker & InMaterialsCollectionTracker , FMaterialTracker & InMaterialTracker ) : MaterialsCollectionTracker ( InMaterialsCollectionTracker ) , MaterialTracker ( InMaterialTracker ) { }
void MaterialEnum ( Mtl * Material , bool bAddMaterial )
{
if ( Material = = NULL )
{
return ;
}
if ( FDatasmithMaxMatHelper : : GetMaterialClass ( Material ) = = EDSMaterialType : : XRefMat )
{
MaterialEnum ( FDatasmithMaxMatHelper : : GetRenderedXRefMaterial ( Material ) , true ) ;
}
else if ( FDatasmithMaxMatHelper : : GetMaterialClass ( Material ) = = EDSMaterialType : : MultiMat )
{
for ( int i = 0 ; i < Material - > NumSubMtls ( ) ; i + + )
{
MaterialEnum ( Material - > GetSubMtl ( i ) , true ) ;
}
}
else
{
if ( bAddMaterial )
{
if ( ! MaterialsCollectionTracker . EncounteredMaterials . Contains ( Material ) )
{
int DuplicateCount = 0 ;
FString ProposedName = Material - > GetName ( ) . data ( ) ;
// todo: fix this without changing max material name? Btw - this requires changing all material export functions for all types of materials(those functions tied to Mtl->GetName())
// todo: revert material names after export
MaterialsCollectionTracker . MaterialNames . Add ( * ProposedName ) ;
// Make unique material name
FDatasmithUtils : : SanitizeNameInplace ( ProposedName ) ;
for ( Mtl * OtherMaterial : MaterialsCollectionTracker . EncounteredMaterials )
{
if ( ProposedName = = FDatasmithUtils : : SanitizeName ( OtherMaterial - > GetName ( ) . data ( ) ) )
{
DuplicateCount + + ;
ProposedName = FDatasmithUtils : : SanitizeName ( Material - > GetName ( ) . data ( ) ) + TEXT ( " _( " ) + FString : : FromInt ( DuplicateCount ) + TEXT ( " ) " ) ;
}
}
Material - > SetName ( * ProposedName ) ;
MaterialsCollectionTracker . EncounteredMaterials . Add ( Material ) ;
}
MaterialTracker . AddActualMaterial ( Material ) ;
}
bool bAddRecursively = Material - > ClassID ( ) = = THEARANDOMCLASS | | Material - > ClassID ( ) = = VRAYBLENDMATCLASS | | Material - > ClassID ( ) = = CORONALAYERMATCLASS ;
for ( int i = 0 ; i < Material - > NumSubMtls ( ) ; i + + )
{
MaterialEnum ( Material - > GetSubMtl ( i ) , bAddRecursively ) ;
}
}
}
} ;
void FMaterialsCollectionTracker : : Reset ( )
{
MaterialTrackers . Reset ( ) ;
InvalidatedMaterialTrackers . Reset ( ) ;
EncounteredMaterials . Reset ( ) ;
EncounteredTextures . Reset ( ) ;
MaterialNames . Reset ( ) ;
UsedMaterialToMaterialTracker . Reset ( ) ;
UsedMaterialToDatasmithMaterial . Reset ( ) ;
2022-03-24 10:41:30 -04:00
UsedTextureToMaterialTracker . Reset ( ) ;
UsedTextureToDatasmithElement . Reset ( ) ;
2021-11-07 23:43:01 -05:00
}
void FMaterialsCollectionTracker : : UpdateMaterial ( FMaterialTracker * MaterialTracker )
{
RemoveConvertedMaterial ( * MaterialTracker ) ;
FMaterialEnum ( * this , * MaterialTracker ) . MaterialEnum ( MaterialTracker - > Material , true ) ;
for ( Mtl * Material : MaterialTracker - > GetActualMaterials ( ) )
{
UsedMaterialToMaterialTracker . FindOrAdd ( Material ) . Add ( MaterialTracker ) ;
}
}
2022-03-24 10:41:30 -04:00
void FMaterialsCollectionTracker : : ConvertMaterial ( Mtl * Material , TSharedRef < IDatasmithScene > DatasmithScene , const TCHAR * AssetsPath , TSet < Texmap * > & TexmapsConverted )
{
2022-04-01 06:56:55 -04:00
SCENE_UPDATE_STAT_INC ( UpdateMaterials , Total ) ;
2022-03-24 10:41:30 -04:00
// todo: reworking material export - composite materials(like VRayBlend) export submaterials too
// check below is needed to make sure that no material is exported twice.
// This is how it was handled before bu needs to be handled without going through the list of all materials.
// Names should be unique prior to this
FString MaterialName ( FDatasmithUtils : : SanitizeObjectName ( Material - > GetName ( ) . data ( ) ) ) ;
for ( int i = 0 ; i < DatasmithScene - > GetMaterialsCount ( ) ; i + + )
{
if ( FString ( DatasmithScene - > GetMaterial ( i ) - > GetName ( ) ) = = MaterialName )
{
2022-04-01 06:56:55 -04:00
SCENE_UPDATE_STAT_INC ( UpdateMaterials , SkippedAsAlreadyConverted ) ;
2022-03-24 10:41:30 -04:00
return ;
}
}
TArray < Texmap * > TexmapsUsedByMaterial ;
TSharedPtr < IDatasmithBaseMaterialElement > DatasmithMaterial ;
if ( FDatasmithMaxMaterialsToUEPbr * MaterialConverter = FDatasmithMaxMaterialsToUEPbrManager : : GetMaterialConverter ( Material ) )
{
TGuardValue < TArray < Texmap * > * > TexmapsConvertedGuard ( MaterialConverter - > TexmapsConverted , & TexmapsUsedByMaterial ) ;
MaterialConverter - > Convert ( DatasmithScene , DatasmithMaterial , Material , AssetsPath ) ;
if ( DatasmithMaterial )
{
2022-04-01 06:56:55 -04:00
SCENE_UPDATE_STAT_INC ( UpdateMaterials , Converted ) ;
2022-03-24 10:41:30 -04:00
DatasmithScene - > AddMaterial ( DatasmithMaterial ) ;
UsedMaterialToDatasmithMaterial . Add ( Material , DatasmithMaterial ) ;
2022-05-30 11:00:50 -04:00
SceneTracker . RemapConvertedMaterialUVChannels ( Material , DatasmithMaterial ) ;
2022-03-24 10:41:30 -04:00
}
}
// Tie texture used by an actual material to tracked material
for ( Texmap * Texture : TexmapsUsedByMaterial )
{
for ( FMaterialTracker * MaterialTracker : UsedMaterialToMaterialTracker [ Material ] )
{
MaterialTracker - > AddActualTexture ( Texture ) ;
UsedTextureToMaterialTracker . FindOrAdd ( Texture ) . Add ( MaterialTracker ) ;
}
}
TexmapsConverted . Append ( TexmapsUsedByMaterial ) ;
}
2021-11-07 23:43:01 -05:00
void FMaterialsCollectionTracker : : ReleaseMaterial ( FMaterialTracker & MaterialTracker )
{
RemoveConvertedMaterial ( MaterialTracker ) ;
MaterialTrackers . Remove ( MaterialTracker . Material ) ;
2022-03-10 01:41:48 -05:00
InvalidatedMaterialTrackers . Remove ( & MaterialTracker ) ;
2021-11-07 23:43:01 -05:00
}
2022-03-24 10:41:30 -04:00
2021-11-07 23:43:01 -05:00
void FMaterialsCollectionTracker : : RemoveConvertedMaterial ( FMaterialTracker & MaterialTracker )
{
for ( Mtl * Material : MaterialTracker . GetActualMaterials ( ) )
{
TSet < FMaterialTracker * > & MaterialTrackersForMaterial = UsedMaterialToMaterialTracker [ Material ] ;
MaterialTrackersForMaterial . Remove ( & MaterialTracker ) ;
if ( ! MaterialTrackersForMaterial . Num ( ) )
{
UsedMaterialToMaterialTracker . Remove ( Material ) ;
TSharedPtr < IDatasmithBaseMaterialElement > DatasmithMaterial ;
if ( UsedMaterialToDatasmithMaterial . RemoveAndCopyValue ( Material , DatasmithMaterial ) )
{
SceneTracker . RemoveMaterial ( DatasmithMaterial ) ;
}
}
}
2022-03-24 10:41:30 -04:00
for ( Texmap * Texture : MaterialTracker . GetActualTexmaps ( ) )
{
TSet < FMaterialTracker * > & MaterialTrackersForTexture = UsedTextureToMaterialTracker [ Texture ] ;
MaterialTrackersForTexture . Remove ( & MaterialTracker ) ;
if ( ! MaterialTrackersForTexture . Num ( ) ) // No tracked materials are using this texture anymore
{
UsedTextureToMaterialTracker . Remove ( Texture ) ;
for ( const TSharedPtr < IDatasmithTextureElement > & TextureElement : UsedTextureToDatasmithElement [ Texture ] )
{
SceneTracker . RemoveTexture ( TextureElement ) ;
}
UsedTextureToDatasmithElement . Remove ( Texture ) ;
}
}
2021-11-07 23:43:01 -05:00
MaterialTracker . ResetActualMaterialAndTextures ( ) ;
}
FMaterialTracker * FMaterialsCollectionTracker : : AddMaterial ( Mtl * Material )
{
if ( FMaterialTrackerHandle * HandlePtr = MaterialTrackers . Find ( Material ) )
{
return HandlePtr - > GetMaterialTracker ( ) ;
}
// Track material if not yet
FMaterialTrackerHandle & MaterialTrackerHandle = MaterialTrackers . Emplace ( Material , Material ) ;
InvalidatedMaterialTrackers . Add ( MaterialTrackerHandle . GetMaterialTracker ( ) ) ;
return MaterialTrackerHandle . GetMaterialTracker ( ) ;
}
void FMaterialsCollectionTracker : : InvalidateMaterial ( Mtl * Material )
{
if ( FMaterialTrackerHandle * MaterialTrackerHandle = MaterialTrackers . Find ( Material ) )
{
InvalidatedMaterialTrackers . Add ( MaterialTrackerHandle - > GetMaterialTracker ( ) ) ;
}
}
}
# include "Windows/HideWindowsPlatformTypes.h"
# endif // NEW_DIRECTLINK_PLUGIN