2019-12-26 23:01:54 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-04 13:11:45 -04:00
# include "DatasmithMaxLogger.h"
2022-06-07 02:12:06 -04:00
# include "DatasmithMaxDirectLink.h"
2019-10-04 13:11:45 -04:00
# include "DatasmithMaxExporterDefines.h"
# include "HAL/UnrealMemory.h"
# include "Windows/AllowWindowsPlatformTypes.h"
MAX_INCLUDES_START
# include "max.h"
MAX_INCLUDES_END
DatasmithMaxLogger & DatasmithMaxLogger : : Get ( )
{
static TSharedRef < DatasmithMaxLogger > Instance = MakeShared < DatasmithMaxLogger > ( ) ; // Create a shared ref because we support TSharedFromThis
return Instance . Get ( ) ;
}
void DatasmithMaxLogger : : Purge ( )
{
ResetGeneralErrors ( ) ;
ResetTextureErrors ( ) ;
ResetMissingAssetErrors ( ) ;
PartialSupportedMats . Empty ( ) ;
UnsupportedMats . Empty ( ) ;
PartialSupportedMaps . Empty ( ) ;
UnsupportedMaps . Empty ( ) ;
UnsupportedLight . Empty ( ) ;
FailUVs . Empty ( ) ;
FailObjs . Empty ( ) ;
InvalidTransforms . Empty ( ) ;
}
void DatasmithMaxLogger : : AddPartialSupportedMat ( Mtl * Mat )
{
for ( int i = 0 ; i < PartialSupportedMats . Num ( ) ; i + + )
{
if ( Mat - > ClassID ( ) = = PartialSupportedMats [ i ] - > ClassID ( ) )
{
return ;
}
}
PartialSupportedMats . Add ( Mat ) ;
}
void DatasmithMaxLogger : : AddUnsupportedMat ( Mtl * Mat )
{
for ( int i = 0 ; i < UnsupportedMats . Num ( ) ; i + + )
{
if ( Mat - > ClassID ( ) = = UnsupportedMats [ i ] - > ClassID ( ) )
{
return ;
}
}
UnsupportedMats . Add ( Mat ) ;
}
void DatasmithMaxLogger : : AddPartialSupportedMap ( Texmap * Map )
{
for ( int i = 0 ; i < PartialSupportedMaps . Num ( ) ; i + + )
{
if ( Map - > ClassID ( ) = = PartialSupportedMaps [ i ] - > ClassID ( ) )
{
return ;
}
}
PartialSupportedMaps . Add ( Map ) ;
}
void DatasmithMaxLogger : : AddUnsupportedMap ( Texmap * Map )
{
2022-06-07 02:12:06 -04:00
2019-10-04 13:11:45 -04:00
for ( int i = 0 ; i < UnsupportedMaps . Num ( ) ; i + + )
{
if ( Map - > ClassID ( ) = = UnsupportedMaps [ i ] - > ClassID ( ) )
{
return ;
}
}
2022-06-07 02:12:06 -04:00
MSTR Classname ;
Map - > GetClassName ( Classname ) ;
DatasmithMaxDirectLink : : LogWarning ( FString : : Printf ( TEXT ( " Unsupported texmap \" %s \" of type %s (0x%08x-0x%08x) " ) , Map - > GetName ( ) . ToBSTR ( ) , Classname . ToBSTR ( ) , Map - > ClassID ( ) . PartA ( ) , Map - > ClassID ( ) . PartB ( ) ) ) ;
2019-10-04 13:11:45 -04:00
UnsupportedMaps . Add ( Map ) ;
}
void DatasmithMaxLogger : : AddUnsupportedLight ( INode * Light )
{
for ( int i = 0 ; i < UnsupportedLight . Num ( ) ; i + + )
{
if ( Light - > ClassID ( ) = = UnsupportedLight [ i ] - > ClassID ( ) )
{
return ;
}
}
UnsupportedLight . Add ( Light ) ;
}
void DatasmithMaxLogger : : AddUnsupportedUV ( INode * Node )
{
FailUVs . AddUnique ( Node ) ;
}
void DatasmithMaxLogger : : AddInvalidObj ( INode * Node )
{
FailObjs . AddUnique ( Node ) ;
}
TArray < INode * > DatasmithMaxLogger : : GetInvalidObjects ( ) const
{
return FailObjs ;
}
void DatasmithMaxLogger : : AddInvalidTransform ( INode * Node )
{
InvalidTransforms . AddUnique ( Node ) ;
}
bool DatasmithMaxLogger : : HasWarnings ( )
{
if ( GetGeneralErrorsCount ( ) > 0 | | GetTextureErrorsCount ( ) > 0 | | GetMissingAssetErrorsCount ( ) > 0 | |
PartialSupportedMats . Num ( ) > 0 | | UnsupportedMats . Num ( ) > 0 | |
PartialSupportedMaps . Num ( ) > 0 | | UnsupportedMaps . Num ( ) > 0 | | UnsupportedLight . Num ( ) > 0 | | FailUVs . Num ( ) > 0 )
{
return true ;
}
else
{
return false ;
}
}
bool DatasmithMaxLogger : : CopyToClipBoard ( )
{
if ( ShowMessage . IsEmpty ( ) )
{
return false ;
}
if ( OpenClipboard ( NULL ) )
{
EmptyClipboard ( ) ;
HGLOBAL HClipboardData ;
size_t Num = ( ShowMessage . Len ( ) + 1 ) * sizeof ( WCHAR ) ;
HClipboardData = GlobalAlloc ( NULL , Num ) ;
WCHAR * PchData = ( WCHAR * ) GlobalLock ( HClipboardData ) ;
FMemory : : Memcpy ( PchData , * ShowMessage , Num ) ;
SetClipboardData ( CF_UNICODETEXT , HClipboardData ) ;
GlobalUnlock ( HClipboardData ) ;
CloseClipboard ( ) ;
return true ;
}
return false ;
}
void DatasmithMaxLogger : : AddItem ( const TCHAR * Msg , HWND Handle , FString & FullMsg )
{
SendDlgItemMessage ( Handle , IDC_ERROR_MSG_LIST , LB_ADDSTRING , NULL , ( LPARAM ) Msg ) ;
FullMsg + = Msg ;
FullMsg + = LINE_TERMINATOR ;
}
void DatasmithMaxLogger : : AddObjectList ( TArray < INode * > ObjectList , HWND Handle , const TCHAR * Header , const TCHAR * Description )
{
const int32 MAX_ITEMS_TO_SHOW = 20 ;
if ( ObjectList . Num ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( * ( FString ( TEXT ( " \t " ) ) + Header ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
if ( Description & & FCString : : Strlen ( Description ) )
{
AddItem ( Description , Handle , ShowMessage ) ;
}
FString ObjectListString ;
int j = 0 ;
for ( int i = 0 ; i < FMath : : Min ( ObjectList . Num ( ) , MAX_ITEMS_TO_SHOW ) ; i + + )
{
if ( j > 0 )
{
ObjectListString + = TEXT ( " , [ " ) ;
}
else
{
ObjectListString + = TEXT ( " [ " ) ;
}
ObjectListString + = ObjectList [ i ] - > GetName ( ) ;
ObjectListString + = TEXT ( " ] " ) ;
j + + ;
if ( j = = 4 )
{
j = 0 ;
AddItem ( * ObjectListString , Handle , ShowMessage ) ;
ObjectListString . Empty ( ) ;
}
}
if ( ! ObjectListString . IsEmpty ( ) )
{
AddItem ( * ObjectListString , Handle , ShowMessage ) ;
}
if ( ObjectList . Num ( ) > MAX_ITEMS_TO_SHOW )
{
ObjectListString = TEXT ( " ...and " ) + FString : : FromInt ( ObjectList . Num ( ) - MAX_ITEMS_TO_SHOW ) + TEXT ( " more " ) ;
AddItem ( * ObjectListString , Handle , ShowMessage ) ;
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
}
2021-12-16 19:33:40 -05:00
FString DatasmithMaxLogger : : GetLightDescription ( INode * LightNode )
{
ObjectState State = LightNode - > EvalWorldState ( 0 ) ;
LightObject * Light = ( LightObject * ) State . obj ;
MSTR Classname ;
Light - > GetClassName ( Classname ) ;
return FString : : Printf ( TEXT ( " \" %s \" of type %s (0x%08x-0x%08x) " ) , LightNode - > GetName ( ) , Classname . ToBSTR ( ) , Light - > ClassID ( ) . PartA ( ) , Light - > ClassID ( ) . PartB ( ) ) ;
}
2019-10-04 13:11:45 -04:00
void DatasmithMaxLogger : : Show ( HWND Handle )
{
ShowMessage = TEXT ( " " ) ;
if ( GetGeneralErrorsCount ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t GENERAL MESSAGES " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < GetGeneralErrorsCount ( ) ; i + + )
{
AddItem ( GetGeneralError ( i ) , Handle , ShowMessage ) ;
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
if ( GetMissingAssetErrorsCount ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t MISSING EXTERNAL FILES " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " One or more file required to export correctly to Unreal is missing, " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " which can produce incorrect results. We recommend that you solve the issue " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " with the 3ds Max's Asset Tracking tool prior to export. " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < GetMissingAssetErrorsCount ( ) ; i + + )
{
AddItem ( GetMissingAssetError ( i ) , Handle , ShowMessage ) ;
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
// Invalid Objects
AddObjectList ( FailObjs , Handle , TEXT ( " INVALID OBJECTS (unsupported, corrupted or too small geometry?) " ) ) ;
if ( PartialSupportedMats . Num ( ) > 0 | | PartialSupportedMaps . Num ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t PARTIALLY SUPPORTED " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < PartialSupportedMats . Num ( ) ; i + + )
{
MSTR Classname ;
PartialSupportedMats [ i ] - > GetClassName ( Classname ) ;
FString Msg = TEXT ( " Materials of type " ) + FString ( Classname . ToBSTR ( ) ) + TEXT ( " are not supported and its first children will be used. " ) ;
AddItem ( * Msg , Handle , ShowMessage ) ;
}
for ( int i = 0 ; i < PartialSupportedMaps . Num ( ) ; i + + )
{
MSTR Classname ;
PartialSupportedMaps [ i ] - > GetClassName ( Classname ) ; ;
FString Msg = TEXT ( " Texmaps of type " ) + FString ( Classname . ToBSTR ( ) ) + TEXT ( " are not supported and its first children will be used. " ) ;
AddItem ( * Msg , Handle , ShowMessage ) ;
}
ShowMessage + = TEXT ( " \n \n " ) ;
SendDlgItemMessage ( Handle , IDC_ERROR_MSG_LIST , LB_ADDSTRING , NULL , ( LPARAM ) TEXT ( " \n " ) ) ;
SendDlgItemMessage ( Handle , IDC_ERROR_MSG_LIST , LB_ADDSTRING , NULL , ( LPARAM ) TEXT ( " \n " ) ) ;
}
if ( UnsupportedMats . Num ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t MATERIALS " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " Some materials used in the scene are not supported by the Unreal Datasmith format in the moment. They will not be imported inside Unreal Engine. " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < UnsupportedMats . Num ( ) ; i + + )
{
MSTR Classname ;
UnsupportedMats [ i ] - > GetClassName ( Classname ) ;
Mtl * Mat = UnsupportedMats [ i ] ;
FString Msg = FString : : Printf ( TEXT ( " \" %s \" of type %s (0x%08x-0x%08x) " ) , Mat - > GetName ( ) . ToBSTR ( ) , Classname . ToBSTR ( ) , Mat - > ClassID ( ) . PartA ( ) , Mat - > ClassID ( ) . PartB ( ) ) ;
AddItem ( * Msg , Handle , ShowMessage ) ;
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
if ( UnsupportedMaps . Num ( ) > 0 | | GetTextureErrorsCount ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t TEXTUREMAPS " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
if ( UnsupportedMaps . Num ( ) > 0 )
{
AddItem ( TEXT ( " Some texture maps used in the scene are not supported by the Unreal Datasmith format in the moment. They will not be imported inside Unreal Engine. " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < UnsupportedMaps . Num ( ) ; i + + )
{
MSTR Classname ;
UnsupportedMaps [ i ] - > GetClassName ( Classname ) ;
Texmap * Map = UnsupportedMaps [ i ] ;
FString Msg = FString : : Printf ( TEXT ( " \" %s \" of type %s (0x%08x-0x%08x) " ) , Map - > GetName ( ) . ToBSTR ( ) , Classname . ToBSTR ( ) , Map - > ClassID ( ) . PartA ( ) , Map - > ClassID ( ) . PartB ( ) ) ;
AddItem ( * Msg , Handle , ShowMessage ) ;
}
}
if ( GetTextureErrorsCount ( ) > 0 )
{
for ( int i = 0 ; i < GetTextureErrorsCount ( ) ; i + + )
{
AddItem ( GetTextureError ( i ) , Handle , ShowMessage ) ;
}
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
if ( UnsupportedLight . Num ( ) > 0 )
{
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " \t LIGHTS " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " ------------------------------------------------------------------------------------------ " ) , Handle , ShowMessage ) ;
AddItem ( TEXT ( " Some lights used in the scene are not supported by the Unreal Datasmith format in the moment. They will not be imported inside Unreal Engine. " ) , Handle , ShowMessage ) ;
for ( int i = 0 ; i < UnsupportedLight . Num ( ) ; i + + )
{
2021-12-16 19:33:40 -05:00
FString Msg = GetLightDescription ( UnsupportedLight [ i ] ) ;
2019-10-04 13:11:45 -04:00
AddItem ( * Msg , Handle , ShowMessage ) ;
}
AddItem ( TEXT ( " \n \n " ) , Handle , ShowMessage ) ;
}
// Invalid UVs
AddObjectList ( FailUVs , Handle , TEXT ( " MESHES WITHOUT UV CHANNEL 2 (USED FOR LIGHT BAKING) " ) ) ;
// Invalid Transforms
FString InvalidTransformsDescription = TEXT ( " Some objects have customized pivots and nonuniform scales. " ) + FString ( LINE_TERMINATOR ) ;
InvalidTransformsDescription + = TEXT ( " Those combinations are not supported by Unreal and will produce incorrect results. " ) + FString ( LINE_TERMINATOR ) ;
InvalidTransformsDescription + = TEXT ( " It is recommended to use the Reset XForm Utility on those objects: " ) + FString ( LINE_TERMINATOR ) ;
AddObjectList ( InvalidTransforms , Handle , TEXT ( " INVALID TRANSFORMS " ) , * InvalidTransformsDescription ) ;
}
INT_PTR CALLBACK MsgListDlgProc ( HWND hDlg , UINT iMsg , WPARAM wParam , LPARAM lParam )
{
int Tabs [ 3 ] = { 24 , 24 , 24 } ;
switch ( iMsg )
{
case WM_INITDIALOG :
CenterWindow ( hDlg , GetWindow ( hDlg , GW_OWNER ) ) ;
SendDlgItemMessage ( hDlg , IDC_ERROR_MSG_LIST , LB_RESETCONTENT , 0 , 0 ) ;
SendDlgItemMessage ( hDlg , IDC_ERROR_MSG_LIST , LB_SETTABSTOPS , ( WPARAM ) 3 , ( LPARAM ) Tabs ) ;
EnableWindow ( GetDlgItem ( hDlg , IDSELECTINVALID ) , DatasmithMaxLogger : : Get ( ) . GetInvalidObjects ( ) . Num ( ) > 0 ) ;
DatasmithMaxLogger : : Get ( ) . Show ( hDlg ) ;
return TRUE ;
case WM_COMMAND :
switch ( LOWORD ( wParam ) )
{
case IDCOPY :
DatasmithMaxLogger : : Get ( ) . CopyToClipBoard ( ) ;
break ;
case IDSELECTINVALID :
INodeTab SelectedNodes ;
for ( int i = 0 ; i < DatasmithMaxLogger : : Get ( ) . GetInvalidObjects ( ) . Num ( ) ; i + + )
{
SelectedNodes . AppendNode ( DatasmithMaxLogger : : Get ( ) . GetInvalidObjects ( ) [ i ] ) ;
}
GetCOREInterface ( ) - > ClearNodeSelection ( ) ;
GetCOREInterface ( ) - > SelectNodeTab ( SelectedNodes , TRUE , TRUE ) ;
break ;
}
break ;
case WM_CLOSE :
EndDialog ( hDlg , TRUE ) ;
break ;
case WM_SIZE :
{
int DialogWidth = ( int ) LOWORD ( lParam ) ;
int DialogHeight = ( int ) HIWORD ( lParam ) ;
HWND hList = GetDlgItem ( hDlg , IDC_ERROR_MSG_LIST ) ;
HWND hCopy = GetDlgItem ( hDlg , IDCOPY ) ;
HWND hInvalid = GetDlgItem ( hDlg , IDSELECTINVALID ) ;
MoveWindow ( hList , 6 , 7 , ( DialogWidth - 12 ) , ( DialogHeight - 42 ) , true ) ;
MoveWindow ( hCopy , 24 , DialogHeight - 31 , ( DialogWidth / 2 - 24 ) , 26 , true ) ;
MoveWindow ( hInvalid , ( DialogWidth / 2 ) + 3 , DialogHeight - 31 , ( DialogWidth / 2 - 23 ) , 26 , true ) ;
break ;
}
}
return FALSE ;
}
# include "Windows/HideWindowsPlatformTypes.h"