@@ -39,32 +39,35 @@ public override void OnInspectorGUI() {
39
39
"Export objects centered around the union of the bounding box of selected objects" ) ,
40
40
exportSettings . centerObjects
41
41
) ;
42
-
42
+
43
43
GUILayout . BeginHorizontal ( ) ;
44
44
GUILayout . Label ( new GUIContent (
45
45
"Export Path:" ,
46
46
"Relative path for saving Model Prefabs." ) ) ;
47
47
48
- EditorGUILayout . SelectableLabel ( GetRelativePath ( exportSettings . convertToModelSavePath , Application . dataPath ) ,
49
- EditorStyles . textField , GUILayout . MinWidth ( SelectableLabelMinWidth ) , GUILayout . Height ( EditorGUIUtility . singleLineHeight ) ) ;
48
+ var pathLabel = ExportSettings . GetRelativeSavePath ( ) ;
49
+ if ( pathLabel == "./" ) { pathLabel = "(Assets root)" ; }
50
+ EditorGUILayout . SelectableLabel ( pathLabel ,
51
+ EditorStyles . textField ,
52
+ GUILayout . MinWidth ( SelectableLabelMinWidth ) ,
53
+ GUILayout . Height ( EditorGUIUtility . singleLineHeight ) ) ;
50
54
51
55
if ( GUILayout . Button ( "Browse" , EditorStyles . miniButton , GUILayout . Width ( BrowseButtonWidth ) ) ) {
52
- string initialPath = exportSettings . convertToModelSavePath ;
53
- bool initialPathIsValid = true ;
54
- if ( string . IsNullOrEmpty ( initialPath ) ) {
55
- initialPathIsValid = false ;
56
- }
57
- string path = EditorUtility . OpenFolderPanel (
58
- "Select Model Prefabs Path" , initialPathIsValid ? initialPath : Application . dataPath , null
59
- ) ;
56
+ string initialPath = ExportSettings . GetAbsoluteSavePath ( ) ;
57
+ string fullPath = EditorUtility . OpenFolderPanel (
58
+ "Select Model Prefabs Path" , initialPath , null
59
+ ) ;
60
60
61
61
// Unless the user canceled, make sure they chose something in the Assets folder.
62
- if ( ! string . IsNullOrEmpty ( path ) ) {
63
- if ( path . StartsWith ( Application . dataPath ) ) {
64
- exportSettings . convertToModelSavePath = path ;
65
- } else {
66
- Debug . LogWarning ( "Please select a location in Assets/" ) ;
67
- }
62
+ if ( ! string . IsNullOrEmpty ( fullPath ) ) {
63
+ var relativePath = GetRelativePath ( Application . dataPath , fullPath ) ;
64
+ if ( string . IsNullOrEmpty ( relativePath )
65
+ || relativePath == ".."
66
+ || relativePath . StartsWith ( ".." + Path . DirectorySeparatorChar ) ) {
67
+ Debug . LogWarning ( "Please select a location in the Assets folder" ) ;
68
+ } else {
69
+ ExportSettings . SetRelativeSavePath ( relativePath ) ;
70
+ }
68
71
}
69
72
}
70
73
@@ -78,40 +81,86 @@ public override void OnInspectorGUI() {
78
81
}
79
82
}
80
83
81
- private string GetRelativePath ( string filePath , string folder ) {
82
- Uri pathUri ;
83
- try {
84
- pathUri = new Uri ( filePath ) ;
85
- }
86
- catch ( UriFormatException ) {
87
- return filePath ;
88
- }
89
- if ( ! folder . EndsWith ( Path . DirectorySeparatorChar . ToString ( ) ) ) {
90
- folder += Path . DirectorySeparatorChar ;
84
+ private string GetRelativePath ( string fromDir , string toDir ) {
85
+ // https://stackoverflow.com/questions/275689/how-to-get-relative-path-from-absolute-path
86
+ // With fixes to handle that fromDir and toDir are both directories (not files).
87
+ if ( String . IsNullOrEmpty ( fromDir ) ) throw new ArgumentNullException ( "fromDir" ) ;
88
+ if ( String . IsNullOrEmpty ( toDir ) ) throw new ArgumentNullException ( "toDir" ) ;
89
+
90
+ // MakeRelativeUri assumes the path is a file unless it ends with a
91
+ // path separator, so add one. Having multiple in a row is no problem.
92
+ fromDir += Path . DirectorySeparatorChar ;
93
+ toDir += Path . DirectorySeparatorChar ;
94
+
95
+ // Workaround for https://bugzilla.xamarin.com/show_bug.cgi?id=5921
96
+ fromDir += Path . DirectorySeparatorChar ;
97
+
98
+ Uri fromUri = new Uri ( fromDir ) ;
99
+ Uri toUri = new Uri ( toDir ) ;
100
+
101
+ if ( fromUri . Scheme != toUri . Scheme ) { return null ; } // path can't be made relative.
102
+
103
+ Uri relativeUri = fromUri . MakeRelativeUri ( toUri ) ;
104
+ String relativePath = Uri . UnescapeDataString ( relativeUri . ToString ( ) ) ;
105
+
106
+ if ( string . IsNullOrEmpty ( relativePath ) ) {
107
+ // The relative path is empty if it's the same directory.
108
+ relativePath = "./" ;
91
109
}
92
- Uri folderUri = new Uri ( folder ) ;
93
- string relativePath = Uri . UnescapeDataString (
94
- folderUri . MakeRelativeUri ( pathUri ) . ToString ( ) . Replace ( '/' , Path . DirectorySeparatorChar )
95
- ) ;
96
- if ( ! relativePath . StartsWith ( "Assets" ) ) {
97
- relativePath = string . Format ( "Assets{0}{1}" , Path . DirectorySeparatorChar , relativePath ) ;
110
+
111
+ if ( toUri . Scheme . Equals ( "file" , StringComparison . InvariantCultureIgnoreCase ) ) {
112
+ relativePath = relativePath . Replace ( Path . AltDirectorySeparatorChar , Path . DirectorySeparatorChar ) ;
98
113
}
114
+
99
115
return relativePath ;
100
116
}
101
117
}
102
118
103
119
[ FilePath ( "ProjectSettings/FbxExportSettings.asset" , FilePathAttribute . Location . ProjectFolder ) ]
104
120
public class ExportSettings : FbxExporters . EditorTools . ScriptableSingleton < ExportSettings >
105
121
{
122
+ public const string kDefaultSavePath = "Objects" ;
123
+
106
124
public bool weldVertices = true ;
107
125
public bool embedTextures = false ;
108
126
public bool mayaCompatibleNames = true ;
109
127
public bool centerObjects = true ;
110
- public string convertToModelSavePath ;
111
128
112
- void OnEnable ( )
113
- {
114
- convertToModelSavePath = Path . Combine ( Application . dataPath , "Objects" ) ;
129
+ /// <summary>
130
+ /// The path where Convert To Model will save the new fbx and prefab.
131
+ /// This is relative to the Application.dataPath
132
+ /// </summary>
133
+ [ SerializeField ]
134
+ string convertToModelSavePath = kDefaultSavePath ;
135
+
136
+ /// <summary>
137
+ /// The path where Convert To Model will save the new fbx and prefab.
138
+ /// This is relative to the Application.dataPath
139
+ /// </summary>
140
+ public static string GetRelativeSavePath ( ) {
141
+ var relativePath = instance . convertToModelSavePath ;
142
+ if ( string . IsNullOrEmpty ( relativePath ) ) {
143
+ relativePath = kDefaultSavePath ;
144
+ }
145
+ return relativePath ;
146
+ }
147
+
148
+ /// <summary>
149
+ /// The path where Convert To Model will save the new fbx and prefab.
150
+ /// This is an absolute path
151
+ /// </summary>
152
+ public static string GetAbsoluteSavePath ( ) {
153
+ var relativePath = GetRelativeSavePath ( ) ;
154
+ var absolutePath = Path . Combine ( Application . dataPath , relativePath ) ;
155
+ return Path . GetFullPath ( absolutePath ) ;
156
+ }
157
+
158
+ /// <summary>
159
+ /// Set the path where Convert To Model will save the new fbx and prefab.
160
+ /// This is interpreted as being relative to the Application.dataPath
161
+ /// </summary>
162
+ public static void SetRelativeSavePath ( string newPath ) {
163
+ instance . convertToModelSavePath = newPath ;
115
164
}
116
165
117
166
[ MenuItem ( "Edit/Project Settings/Fbx Export" , priority = 300 ) ]
0 commit comments