@@ -36,6 +36,14 @@ public class ModelExporter : System.IDisposable
36
36
37
37
const string ProgressBarTitle = "Fbx Export" ;
38
38
39
+ const char MayaNamespaceSeparator = ':' ;
40
+
41
+ // replace invalid chars with this one
42
+ const char InvalidCharReplacement = '_' ;
43
+
44
+ const string RegexCharStart = "[" ;
45
+ const string RegexCharEnd = "]" ;
46
+
39
47
const int UnitScaleFactor = 100 ;
40
48
41
49
/// <summary>
@@ -241,13 +249,13 @@ public void ExportTexture (Material unityMaterial, string unityPropName,
241
249
/// <summary>
242
250
/// Get the color of a material, or grey if we can't find it.
243
251
/// </summary>
244
- public FbxDouble3 GetMaterialColor ( Material unityMaterial , string unityPropName )
252
+ public FbxDouble3 GetMaterialColor ( Material unityMaterial , string unityPropName , float defaultValue = 1 )
245
253
{
246
254
if ( ! unityMaterial ) {
247
- return new FbxDouble3 ( 0.5 ) ;
255
+ return new FbxDouble3 ( defaultValue ) ;
248
256
}
249
257
if ( ! unityMaterial . HasProperty ( unityPropName ) ) {
250
- return new FbxDouble3 ( 0.5 ) ;
258
+ return new FbxDouble3 ( defaultValue ) ;
251
259
}
252
260
var unityColor = unityMaterial . GetColor ( unityPropName ) ;
253
261
return new FbxDouble3 ( unityColor . r , unityColor . g , unityColor . b ) ;
@@ -478,6 +486,10 @@ protected int ExportComponents (
478
486
{
479
487
int numObjectsExported = exportProgress ;
480
488
489
+ if ( FbxExporters . EditorTools . ExportSettings . instance . mayaCompatibleNames ) {
490
+ unityGo . name = ConvertToMayaCompatibleName ( unityGo . name ) ;
491
+ }
492
+
481
493
// create an FbxNode and add it as a child of parent
482
494
FbxNode fbxNode = FbxNode . Create ( fbxScene , unityGo . name ) ;
483
495
NumNodes ++ ;
@@ -736,7 +748,10 @@ public static bool OnValidateMenuItem ()
736
748
}
737
749
738
750
// Add a menu item called "Export Model..." to a GameObject's context menu.
739
- [ MenuItem ( "GameObject/Export Model... %e" , false , 30 ) ]
751
+ // NOTE: The ellipsis at the end of the Menu Item name prevents the context
752
+ // from being passed to command, thus resulting in OnContextItem()
753
+ // being called only once regardless of what is selected.
754
+ [ MenuItem ( "GameObject/Export Model..." , false , 30 ) ]
740
755
static void OnContextItem ( MenuCommand command )
741
756
{
742
757
OnExport ( ) ;
@@ -849,6 +864,11 @@ public Material Material {
849
864
if ( ! renderer ) {
850
865
return null ;
851
866
}
867
+
868
+ if ( FbxExporters . EditorTools . ExportSettings . instance . mayaCompatibleNames ) {
869
+ renderer . sharedMaterial . name = ConvertToMayaCompatibleName ( renderer . sharedMaterial . name ) ;
870
+ }
871
+
852
872
// .material instantiates a new material, which is bad
853
873
// most of the time.
854
874
return renderer . sharedMaterial ;
@@ -967,13 +987,19 @@ private static void OnExport ()
967
987
? Application . dataPath
968
988
: System . IO . Path . GetDirectoryName ( LastFilePath ) ;
969
989
970
- var filename = string . IsNullOrEmpty ( LastFilePath )
971
- ? MakeFileName ( basename : FileBaseName , extension : Extension )
972
- : System . IO . Path . GetFileName ( LastFilePath ) ;
990
+ GameObject [ ] selectedGOs = Selection . GetFiltered < GameObject > ( SelectionMode . TopLevel ) ;
991
+ string filename = null ;
992
+ if ( selectedGOs . Length == 1 ) {
993
+ filename = ConvertToValidFilename ( selectedGOs [ 0 ] . name + ".fbx" ) ;
994
+ } else {
995
+ filename = string . IsNullOrEmpty ( LastFilePath )
996
+ ? MakeFileName ( basename : FileBaseName , extension : Extension )
997
+ : System . IO . Path . GetFileName ( LastFilePath ) ;
998
+ }
973
999
974
1000
var title = string . Format ( "Export Model FBX ({0})" , FileBaseName ) ;
975
1001
976
- var filePath = EditorUtility . SaveFilePanel ( title , directory , filename , "" ) ;
1002
+ var filePath = EditorUtility . SaveFilePanel ( title , directory , filename , "fbx " ) ;
977
1003
978
1004
if ( string . IsNullOrEmpty ( filePath ) ) {
979
1005
return ;
@@ -1022,6 +1048,56 @@ private static void EnsureDirectory (string path)
1022
1048
Directory . CreateDirectory ( fileInfo . Directory . FullName ) ;
1023
1049
}
1024
1050
}
1051
+
1052
+ /// <summary>
1053
+ /// Removes the diacritics (i.e. accents) from letters.
1054
+ /// e.g. é becomes e
1055
+ /// </summary>
1056
+ /// <returns>Text with accents removed.</returns>
1057
+ /// <param name="text">Text.</param>
1058
+ private static string RemoveDiacritics ( string text )
1059
+ {
1060
+ var normalizedString = text . Normalize ( System . Text . NormalizationForm . FormD ) ;
1061
+ var stringBuilder = new System . Text . StringBuilder ( ) ;
1062
+
1063
+ foreach ( var c in normalizedString )
1064
+ {
1065
+ var unicodeCategory = System . Globalization . CharUnicodeInfo . GetUnicodeCategory ( c ) ;
1066
+ if ( unicodeCategory != System . Globalization . UnicodeCategory . NonSpacingMark )
1067
+ {
1068
+ stringBuilder . Append ( c ) ;
1069
+ }
1070
+ }
1071
+
1072
+ return stringBuilder . ToString ( ) . Normalize ( System . Text . NormalizationForm . FormC ) ;
1073
+ }
1074
+
1075
+ private static string ConvertToMayaCompatibleName ( string name )
1076
+ {
1077
+ string newName = RemoveDiacritics ( name ) ;
1078
+
1079
+ if ( char . IsDigit ( newName [ 0 ] ) ) {
1080
+ newName = newName . Insert ( 0 , InvalidCharReplacement . ToString ( ) ) ;
1081
+ }
1082
+
1083
+ for ( int i = 0 ; i < newName . Length ; i ++ ) {
1084
+ if ( ! char . IsLetterOrDigit ( newName , i ) ) {
1085
+ if ( i < newName . Length - 1 && newName [ i ] == MayaNamespaceSeparator ) {
1086
+ continue ;
1087
+ }
1088
+ newName = newName . Replace ( newName [ i ] , InvalidCharReplacement ) ;
1089
+ }
1090
+ }
1091
+ return newName ;
1092
+ }
1093
+
1094
+ public static string ConvertToValidFilename ( string filename )
1095
+ {
1096
+ return System . Text . RegularExpressions . Regex . Replace ( filename ,
1097
+ RegexCharStart + new string ( Path . GetInvalidFileNameChars ( ) ) + RegexCharEnd ,
1098
+ InvalidCharReplacement . ToString ( )
1099
+ ) ;
1100
+ }
1025
1101
}
1026
1102
}
1027
1103
}
0 commit comments