2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "../Game_local.h"
33 #include "../../MayaImport/maya_main.h"
35 /***********************************************************************
37 Maya conversion functions
39 ***********************************************************************/
41 static idStr Maya_Error;
43 static exporterInterface_t Maya_ConvertModel = NULL;
44 static exporterShutdown_t Maya_Shutdown = NULL;
45 static int importDLL = 0;
47 bool idModelExport::initialized = false;
51 idModelExport::idModelExport
54 idModelExport::idModelExport() {
60 idModelExport::Shutdown
63 void idModelExport::Shutdown( void ) {
64 if ( Maya_Shutdown ) {
69 sys->DLL_Unload( importDLL );
74 Maya_ConvertModel = NULL;
81 idModelExport::CheckMayaInstall
83 Determines if Maya is installed on the user's machine
86 bool idModelExport::CheckMayaInstall( void ) {
93 lres = RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Alias|Wavefront\\Maya\\4.5\\Setup\\InstallPath", &hKey );
95 if ( lres != ERROR_SUCCESS ) {
99 lres = RegQueryValueEx( hKey, "MAYA_INSTALL_LOCATION", NULL, (unsigned long*)&lType, (unsigned char*)NULL, (unsigned long*)NULL );
103 if ( lres != ERROR_SUCCESS ) {
111 // only check the non-version specific key so that we only have to update the maya dll when new versions are released
112 lres = RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Alias|Wavefront\\Maya", &hKey );
115 if ( lres != ERROR_SUCCESS ) {
123 =====================
124 idModelExport::LoadMayaDll
126 Checks to see if we can load the Maya export dll
127 =====================
129 void idModelExport::LoadMayaDll( void ) {
130 exporterDLLEntry_t dllEntry;
131 char dllPath[ MAX_OSPATH ];
133 fileSystem->FindDLL( "MayaImport", dllPath, false );
134 if ( !dllPath[ 0 ] ) {
137 importDLL = sys->DLL_Load( dllPath );
142 // look up the dll interface functions
143 dllEntry = ( exporterDLLEntry_t )sys->DLL_GetProcAddress( importDLL, "dllEntry" );
144 Maya_ConvertModel = ( exporterInterface_t )sys->DLL_GetProcAddress( importDLL, "Maya_ConvertModel" );
145 Maya_Shutdown = ( exporterShutdown_t )sys->DLL_GetProcAddress( importDLL, "Maya_Shutdown" );
146 if ( !Maya_ConvertModel || !dllEntry || !Maya_Shutdown ) {
147 Maya_ConvertModel = NULL;
148 Maya_Shutdown = NULL;
149 sys->DLL_Unload( importDLL );
151 gameLocal.Error( "Invalid interface on export DLL." );
155 // initialize the DLL
156 if ( !dllEntry( MD5_VERSION, common, sys ) ) {
158 Maya_ConvertModel = NULL;
159 Maya_Shutdown = NULL;
160 sys->DLL_Unload( importDLL );
162 gameLocal.Error( "Export DLL init failed." );
168 =====================
169 idModelExport::ConvertMayaToMD5
171 Checks if a Maya model should be converted to an MD5, and converts if if the time/date or
172 version number has changed.
173 =====================
175 bool idModelExport::ConvertMayaToMD5( void ) {
176 ID_TIME_T sourceTime;
182 // check if our DLL got loaded
183 if ( initialized && !Maya_ConvertModel ) {
184 Maya_Error = "MayaImport dll not loaded.";
188 // if idAnimManager::forceExport is set then we always reexport Maya models
189 if ( idAnimManager::forceExport ) {
193 // get the source file's time
194 if ( fileSystem->ReadFile( src, NULL, &sourceTime ) < 0 ) {
195 // source file doesn't exist
199 // get the destination file's time
200 if ( !force && ( fileSystem->ReadFile( dest, NULL, &destTime ) >= 0 ) ) {
201 idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
203 parser.LoadFile( dest );
205 // read the file version
206 if ( parser.CheckTokenString( MD5_VERSION_STRING ) ) {
207 version = parser.ParseInt();
209 // check the command line
210 if ( parser.CheckTokenString( "commandline" ) ) {
211 parser.ReadToken( &cmdLine );
213 // check the file time, scale, and version
214 if ( ( destTime >= sourceTime ) && ( version == MD5_VERSION ) && ( cmdLine == commandLine ) ) {
222 // if this is the first time we've been run, check if Maya is installed and load our DLL
223 if ( !initialized ) {
226 if ( !CheckMayaInstall() ) {
227 Maya_Error = "Maya not installed in registry.";
233 // check if our DLL got loaded
234 if ( !Maya_ConvertModel ) {
235 Maya_Error = "Could not load MayaImport dll.";
240 // we need to make sure we have a full path, so convert the filename to an OS path
241 // _D3XP :: we work out of the cdpath, at least until we get Alienbrain
242 src = fileSystem->RelativePathToOSPath( src, "fs_cdpath" );
243 dest = fileSystem->RelativePathToOSPath( dest, "fs_cdpath" );
245 dest.ExtractFilePath( path );
246 if ( path.Length() ) {
247 fileSystem->CreateOSPath( path );
250 // get the os path in case it needs to create one
251 path = fileSystem->RelativePathToOSPath( "", "fs_cdpath" /* _D3XP */ );
253 common->SetRefreshOnPrint( true );
254 Maya_Error = Maya_ConvertModel( path, commandLine );
255 common->SetRefreshOnPrint( false );
256 if ( Maya_Error != "Ok" ) {
260 // conversion succeded
269 void idModelExport::Reset( void ) {
278 idModelExport::ExportModel
281 bool idModelExport::ExportModel( const char *model ) {
282 const char *game = cvarSystem->GetCVarString( "fs_game" );
283 if ( strlen(game) == 0 ) {
290 dest.SetFileExtension( MD5_MESH_EXT );
292 sprintf( commandLine, "mesh %s -dest %s -game %s", src.c_str(), dest.c_str(), game );
293 if ( !ConvertMayaToMD5() ) {
294 gameLocal.Printf( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
303 idModelExport::ExportAnim
306 bool idModelExport::ExportAnim( const char *anim ) {
307 const char *game = cvarSystem->GetCVarString( "fs_game" );
308 if ( strlen(game) == 0 ) {
315 dest.SetFileExtension( MD5_ANIM_EXT );
317 sprintf( commandLine, "anim %s -dest %s -game %s", src.c_str(), dest.c_str(), game );
318 if ( !ConvertMayaToMD5() ) {
319 gameLocal.Printf( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
328 idModelExport::ParseOptions
331 bool idModelExport::ParseOptions( idLexer &lex ) {
336 if ( !lex.ReadToken( &token ) ) {
337 lex.Error( "Expected filename" );
344 while( lex.ReadToken( &token ) ) {
345 if ( token == "-" ) {
346 if ( !lex.ReadToken( &token ) ) {
347 lex.Error( "Expecting option" );
350 if ( token == "sourcedir" ) {
351 if ( !lex.ReadToken( &token ) ) {
352 lex.Error( "Missing pathname after -sourcedir" );
356 } else if ( token == "destdir" ) {
357 if ( !lex.ReadToken( &token ) ) {
358 lex.Error( "Missing pathname after -destdir" );
362 } else if ( token == "dest" ) {
363 if ( !lex.ReadToken( &token ) ) {
364 lex.Error( "Missing filename after -dest" );
369 commandLine += va( " -%s", token.c_str() );
372 commandLine += va( " %s", token.c_str() );
376 if ( sourcedir.Length() ) {
378 sourcedir.BackSlashesToSlashes();
379 sprintf( src, "%s/%s", sourcedir.c_str(), src.c_str() );
382 if ( destdir.Length() ) {
384 destdir.BackSlashesToSlashes();
385 sprintf( dest, "%s/%s", destdir.c_str(), dest.c_str() );
393 idModelExport::ParseExportSection
396 int idModelExport::ParseExportSection( idParser &parser ) {
399 idStr defaultCommands;
405 const char *game = cvarSystem->GetCVarString( "fs_game" );
407 if ( strlen(game) == 0 ) {
411 // only export sections that match our export mask
412 if ( g_exportMask.GetString()[ 0 ] ) {
413 if ( parser.CheckTokenString( "{" ) ) {
414 parser.SkipBracedSection( false );
418 parser.ReadToken( &token );
419 if ( token.Icmp( g_exportMask.GetString() ) ) {
420 parser.SkipBracedSection();
423 parser.ExpectTokenString( "{" );
424 } else if ( !parser.CheckTokenString( "{" ) ) {
425 // skip the export mask
426 parser.ReadToken( &token );
427 parser.ExpectTokenString( "{" );
432 lex.SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
436 if ( !parser.ReadToken( &command ) ) {
437 parser.Error( "Unexpoected end-of-file" );
441 if ( command == "}" ) {
445 if ( command == "options" ) {
446 parser.ParseRestOfLine( defaultCommands );
447 } else if ( command == "addoptions" ) {
448 parser.ParseRestOfLine( temp );
449 defaultCommands += " ";
450 defaultCommands += temp;
451 } else if ( ( command == "mesh" ) || ( command == "anim" ) || ( command == "camera" ) ) {
452 if ( !parser.ReadToken( &token ) ) {
453 parser.Error( "Expected filename" );
457 parser.ParseRestOfLine( parms );
459 if ( defaultCommands.Length() ) {
460 sprintf( temp, "%s %s", temp.c_str(), defaultCommands.c_str() );
463 if ( parms.Length() ) {
464 sprintf( temp, "%s %s", temp.c_str(), parms.c_str() );
467 lex.LoadMemory( temp, temp.Length(), parser.GetFileName() );
470 if ( ParseOptions( lex ) ) {
471 const char *game = cvarSystem->GetCVarString( "fs_game" );
472 if ( strlen(game) == 0 ) {
476 if ( command == "mesh" ) {
477 dest.SetFileExtension( MD5_MESH_EXT );
478 } else if ( command == "anim" ) {
479 dest.SetFileExtension( MD5_ANIM_EXT );
480 } else if ( command == "camera" ) {
481 dest.SetFileExtension( MD5_CAMERA_EXT );
483 dest.SetFileExtension( command );
485 idStr back = commandLine;
486 sprintf( commandLine, "%s %s -dest %s -game %s%s", command.c_str(), src.c_str(), dest.c_str(), game, commandLine.c_str() );
487 if ( ConvertMayaToMD5() ) {
490 parser.Warning( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
495 parser.Error( "Unknown token: %s", command.c_str() );
496 parser.SkipBracedSection( false );
506 idModelExport::ExportDefFile
509 int idModelExport::ExportDefFile( const char *filename ) {
510 idParser parser( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
516 if ( !parser.LoadFile( filename ) ) {
517 gameLocal.Printf( "Could not load '%s'\n", filename );
521 while( parser.ReadToken( &token ) ) {
522 if ( token == "export" ) {
523 count += ParseExportSection( parser );
525 parser.ReadToken( &token );
526 parser.SkipBracedSection();
535 idModelExport::ExportModels
538 int idModelExport::ExportModels( const char *pathname, const char *extension ) {
546 if ( !CheckMayaInstall() ) {
547 // if Maya isn't installed, don't bother checking if we have anims to export
551 gameLocal.Printf( "--------- Exporting models --------\n" );
552 if ( !g_exportMask.GetString()[ 0 ] ) {
553 gameLocal.Printf( " Export mask: '%s'\n", g_exportMask.GetString() );
558 files = fileSystem->ListFiles( pathname, extension );
559 for( i = 0; i < files->GetNumFiles(); i++ ) {
560 count += ExportDefFile( va( "%s/%s", pathname, files->GetFile( i ) ) );
562 fileSystem->FreeFileList( files );
564 gameLocal.Printf( "...%d models exported.\n", count );
565 gameLocal.Printf( "-----------------------------------\n" );