doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Anim_Import.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
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.
13 
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.
18 
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/>.
21 
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.
23 
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.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "../Game_local.h"
33 #include "../../MayaImport/maya_main.h"
34 
35 /***********************************************************************
36 
37  Maya conversion functions
38 
39 ***********************************************************************/
40 
41 static idStr Maya_Error;
42 
45 static int importDLL = 0;
46 
47 bool idModelExport::initialized = false;
48 
49 /*
50 ====================
51 idModelExport::idModelExport
52 ====================
53 */
55  Reset();
56 }
57 
58 /*
59 ====================
60 idModelExport::Shutdown
61 ====================
62 */
64  if ( Maya_Shutdown ) {
65  Maya_Shutdown();
66  }
67 
68  if ( importDLL ) {
69  sys->DLL_Unload( importDLL );
70  }
71 
72  importDLL = 0;
75  Maya_Error.Clear();
76  initialized = false;
77 }
78 
79 /*
80 =====================
81 idModelExport::CheckMayaInstall
82 
83 Determines if Maya is installed on the user's machine
84 =====================
85 */
87 #ifndef _WIN32
88  return false;
89 #elif 0
90  HKEY hKey;
91  long lres, lType;
92 
93  lres = RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Alias|Wavefront\\Maya\\4.5\\Setup\\InstallPath", &hKey );
94 
95  if ( lres != ERROR_SUCCESS ) {
96  return false;
97  }
98 
99  lres = RegQueryValueEx( hKey, "MAYA_INSTALL_LOCATION", NULL, (unsigned long*)&lType, (unsigned char*)NULL, (unsigned long*)NULL );
100 
101  RegCloseKey( hKey );
102 
103  if ( lres != ERROR_SUCCESS ) {
104  return false;
105  }
106  return true;
107 #else
108  HKEY hKey;
109  long lres;
110 
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 );
113  RegCloseKey( hKey );
114 
115  if ( lres != ERROR_SUCCESS ) {
116  return false;
117  }
118  return true;
119 #endif
120 }
121 
122 /*
123 =====================
124 idModelExport::LoadMayaDll
125 
126 Checks to see if we can load the Maya export dll
127 =====================
128 */
131  char dllPath[ MAX_OSPATH ];
132 
133  fileSystem->FindDLL( "MayaImport", dllPath, false );
134  if ( !dllPath[ 0 ] ) {
135  return;
136  }
137  importDLL = sys->DLL_Load( dllPath );
138  if ( !importDLL ) {
139  return;
140  }
141 
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 ) {
149  sys->DLL_Unload( importDLL );
150  importDLL = 0;
151  gameLocal.Error( "Invalid interface on export DLL." );
152  return;
153  }
154 
155  // initialize the DLL
156  if ( !dllEntry( MD5_VERSION, common, sys ) ) {
157  // init failed
160  sys->DLL_Unload( importDLL );
161  importDLL = 0;
162  gameLocal.Error( "Export DLL init failed." );
163  return;
164  }
165 }
166 
167 /*
168 =====================
169 idModelExport::ConvertMayaToMD5
170 
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 =====================
174 */
176  ID_TIME_T sourceTime;
177  ID_TIME_T destTime;
178  int version;
179  idToken cmdLine;
180  idStr path;
181 
182  // check if our DLL got loaded
183  if ( initialized && !Maya_ConvertModel ) {
184  Maya_Error = "MayaImport dll not loaded.";
185  return false;
186  }
187 
188  // if idAnimManager::forceExport is set then we always reexport Maya models
190  force = true;
191  }
192 
193  // get the source file's time
194  if ( fileSystem->ReadFile( src, NULL, &sourceTime ) < 0 ) {
195  // source file doesn't exist
196  return true;
197  }
198 
199  // get the destination file's time
200  if ( !force && ( fileSystem->ReadFile( dest, NULL, &destTime ) >= 0 ) ) {
202 
203  parser.LoadFile( dest );
204 
205  // read the file version
206  if ( parser.CheckTokenString( MD5_VERSION_STRING ) ) {
207  version = parser.ParseInt();
208 
209  // check the command line
210  if ( parser.CheckTokenString( "commandline" ) ) {
211  parser.ReadToken( &cmdLine );
212 
213  // check the file time, scale, and version
214  if ( ( destTime >= sourceTime ) && ( version == MD5_VERSION ) && ( cmdLine == commandLine ) ) {
215  // don't convert it
216  return true;
217  }
218  }
219  }
220  }
221 
222  // if this is the first time we've been run, check if Maya is installed and load our DLL
223  if ( !initialized ) {
224  initialized = true;
225 
226  if ( !CheckMayaInstall() ) {
227  Maya_Error = "Maya not installed in registry.";
228  return false;
229  }
230 
231  LoadMayaDll();
232 
233  // check if our DLL got loaded
234  if ( !Maya_ConvertModel ) {
235  Maya_Error = "Could not load MayaImport dll.";
236  return false;
237  }
238  }
239 
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" );
244 
245  dest.ExtractFilePath( path );
246  if ( path.Length() ) {
247  fileSystem->CreateOSPath( path );
248  }
249 
250  // get the os path in case it needs to create one
251  path = fileSystem->RelativePathToOSPath( "", "fs_cdpath" /* _D3XP */ );
252 
253  common->SetRefreshOnPrint( true );
254  Maya_Error = Maya_ConvertModel( path, commandLine );
255  common->SetRefreshOnPrint( false );
256  if ( Maya_Error != "Ok" ) {
257  return false;
258  }
259 
260  // conversion succeded
261  return true;
262 }
263 
264 /*
265 ====================
266 idModelExport::Reset
267 ====================
268 */
269 void idModelExport::Reset( void ) {
270  force = false;
271  commandLine = "";
272  src = "";
273  dest = "";
274 }
275 
276 /*
277 ====================
278 idModelExport::ExportModel
279 ====================
280 */
281 bool idModelExport::ExportModel( const char *model ) {
282  const char *game = cvarSystem->GetCVarString( "fs_game" );
283  if ( strlen(game) == 0 ) {
284  game = BASE_GAMEDIR;
285  }
286 
287  Reset();
288  src = model;
289  dest = model;
291 
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() );
295  return false;
296  }
297 
298  return true;
299 }
300 
301 /*
302 ====================
303 idModelExport::ExportAnim
304 ====================
305 */
306 bool idModelExport::ExportAnim( const char *anim ) {
307  const char *game = cvarSystem->GetCVarString( "fs_game" );
308  if ( strlen(game) == 0 ) {
309  game = BASE_GAMEDIR;
310  }
311 
312  Reset();
313  src = anim;
314  dest = anim;
316 
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() );
320  return false;
321  }
322 
323  return true;
324 }
325 
326 /*
327 ====================
328 idModelExport::ParseOptions
329 ====================
330 */
332  idToken token;
333  idStr destdir;
334  idStr sourcedir;
335 
336  if ( !lex.ReadToken( &token ) ) {
337  lex.Error( "Expected filename" );
338  return false;
339  }
340 
341  src = token;
342  dest = token;
343 
344  while( lex.ReadToken( &token ) ) {
345  if ( token == "-" ) {
346  if ( !lex.ReadToken( &token ) ) {
347  lex.Error( "Expecting option" );
348  return false;
349  }
350  if ( token == "sourcedir" ) {
351  if ( !lex.ReadToken( &token ) ) {
352  lex.Error( "Missing pathname after -sourcedir" );
353  return false;
354  }
355  sourcedir = token;
356  } else if ( token == "destdir" ) {
357  if ( !lex.ReadToken( &token ) ) {
358  lex.Error( "Missing pathname after -destdir" );
359  return false;
360  }
361  destdir = token;
362  } else if ( token == "dest" ) {
363  if ( !lex.ReadToken( &token ) ) {
364  lex.Error( "Missing filename after -dest" );
365  return false;
366  }
367  dest = token;
368  } else {
369  commandLine += va( " -%s", token.c_str() );
370  }
371  } else {
372  commandLine += va( " %s", token.c_str() );
373  }
374  }
375 
376  if ( sourcedir.Length() ) {
377  src.StripPath();
378  sourcedir.BackSlashesToSlashes();
379  sprintf( src, "%s/%s", sourcedir.c_str(), src.c_str() );
380  }
381 
382  if ( destdir.Length() ) {
383  dest.StripPath();
384  destdir.BackSlashesToSlashes();
385  sprintf( dest, "%s/%s", destdir.c_str(), dest.c_str() );
386  }
387 
388  return true;
389 }
390 
391 /*
392 ====================
393 idModelExport::ParseExportSection
394 ====================
395 */
397  idToken command;
398  idToken token;
399  idStr defaultCommands;
400  idLexer lex;
401  idStr temp;
402  idStr parms;
403  int count;
404 
405  const char *game = cvarSystem->GetCVarString( "fs_game" );
406 
407  if ( strlen(game) == 0 ) {
408  game = BASE_GAMEDIR;
409  }
410 
411  // only export sections that match our export mask
412  if ( g_exportMask.GetString()[ 0 ] ) {
413  if ( parser.CheckTokenString( "{" ) ) {
414  parser.SkipBracedSection( false );
415  return 0;
416  }
417 
418  parser.ReadToken( &token );
419  if ( token.Icmp( g_exportMask.GetString() ) ) {
420  parser.SkipBracedSection();
421  return 0;
422  }
423  parser.ExpectTokenString( "{" );
424  } else if ( !parser.CheckTokenString( "{" ) ) {
425  // skip the export mask
426  parser.ReadToken( &token );
427  parser.ExpectTokenString( "{" );
428  }
429 
430  count = 0;
431 
433 
434  while( 1 ) {
435 
436  if ( !parser.ReadToken( &command ) ) {
437  parser.Error( "Unexpoected end-of-file" );
438  break;
439  }
440 
441  if ( command == "}" ) {
442  break;
443  }
444 
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" );
454  }
455 
456  temp = token;
457  parser.ParseRestOfLine( parms );
458 
459  if ( defaultCommands.Length() ) {
460  sprintf( temp, "%s %s", temp.c_str(), defaultCommands.c_str() );
461  }
462 
463  if ( parms.Length() ) {
464  sprintf( temp, "%s %s", temp.c_str(), parms.c_str() );
465  }
466 
467  lex.LoadMemory( temp, temp.Length(), parser.GetFileName() );
468 
469  Reset();
470  if ( ParseOptions( lex ) ) {
471  const char *game = cvarSystem->GetCVarString( "fs_game" );
472  if ( strlen(game) == 0 ) {
473  game = BASE_GAMEDIR;
474  }
475 
476  if ( command == "mesh" ) {
478  } else if ( command == "anim" ) {
480  } else if ( command == "camera" ) {
482  } else {
483  dest.SetFileExtension( command );
484  }
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() ) {
488  count++;
489  } else {
490  parser.Warning( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
491  }
492  }
493  lex.FreeSource();
494  } else {
495  parser.Error( "Unknown token: %s", command.c_str() );
496  parser.SkipBracedSection( false );
497  break;
498  }
499  }
500 
501  return count;
502 }
503 
504 /*
505 ================
506 idModelExport::ExportDefFile
507 ================
508 */
509 int idModelExport::ExportDefFile( const char *filename ) {
511  idToken token;
512  int count;
513 
514  count = 0;
515 
516  if ( !parser.LoadFile( filename ) ) {
517  gameLocal.Printf( "Could not load '%s'\n", filename );
518  return 0;
519  }
520 
521  while( parser.ReadToken( &token ) ) {
522  if ( token == "export" ) {
523  count += ParseExportSection( parser );
524  } else {
525  parser.ReadToken( &token );
526  parser.SkipBracedSection();
527  }
528  }
529 
530  return count;
531 }
532 
533 /*
534 ================
535 idModelExport::ExportModels
536 ================
537 */
538 int idModelExport::ExportModels( const char *pathname, const char *extension ) {
539  int count;
540 
541  count = 0;
542 
543  idFileList *files;
544  int i;
545 
546  if ( !CheckMayaInstall() ) {
547  // if Maya isn't installed, don't bother checking if we have anims to export
548  return 0;
549  }
550 
551  gameLocal.Printf( "--------- Exporting models --------\n" );
552  if ( !g_exportMask.GetString()[ 0 ] ) {
553  gameLocal.Printf( " Export mask: '%s'\n", g_exportMask.GetString() );
554  }
555 
556  count = 0;
557 
558  files = fileSystem->ListFiles( pathname, extension );
559  for( i = 0; i < files->GetNumFiles(); i++ ) {
560  count += ExportDefFile( va( "%s/%s", pathname, files->GetFile( i ) ) );
561  }
562  fileSystem->FreeFileList( files );
563 
564  gameLocal.Printf( "...%d models exported.\n", count );
565  gameLocal.Printf( "-----------------------------------\n" );
566 
567  return count;
568 }
void Error(const char *str,...) const id_attribute((format(printf
Definition: Parser.cpp:318
#define MD5_ANIM_EXT
Definition: Model.h:43
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
virtual idFileList * ListFiles(const char *relativePath, const char *extension, bool sort=false, bool fullRelativePath=false, const char *gamedir=NULL)=0
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
bool force
Definition: Anim.h:206
const char * Maya_ConvertModel(const char *ospath, const char *commandline)
Definition: maya_main.cpp:3086
void FreeSource(void)
Definition: Lexer.cpp:1676
virtual int ReadFile(const char *relativePath, void **buffer, ID_TIME_T *timestamp=NULL)=0
int Length(void) const
Definition: Str.h:702
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
int GetNumFiles(void) const
Definition: FileSystem.h:126
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
#define MD5_VERSION_STRING
Definition: Model.h:41
bool ExportAnim(const char *anim)
void Maya_Shutdown(void)
Definition: maya_main.cpp:3071
int ExpectTokenString(const char *string)
Definition: Parser.cpp:2402
Definition: Token.h:71
void SetFlags(int flags)
Definition: Lexer.h:298
bool dllEntry(int version, idCommon *common, idSys *sys)
Definition: maya_main.cpp:3109
GLuint src
Definition: glext.h:5390
idStr commandLine
Definition: Anim.h:203
#define MD5_CAMERA_EXT
Definition: Model.h:44
int i
Definition: process.py:33
int Icmp(const char *text) const
Definition: Str.h:667
idStr & BackSlashesToSlashes(void)
Definition: Str.cpp:727
void ExtractFilePath(idStr &dest) const
Definition: Str.cpp:902
idStr & StripPath(void)
Definition: Str.cpp:885
bool ParseOptions(idLexer &lex)
struct version_s version
int ReadToken(idToken *token)
Definition: Parser.cpp:2338
Definition: Lexer.h:137
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
virtual void * DLL_GetProcAddress(int dllHandle, const char *procName)=0
GLuint GLuint GLsizei count
Definition: glext.h:2845
int ExportDefFile(const char *filename)
int ParseInt(void)
Definition: Parser.cpp:2775
#define BASE_GAMEDIR
Definition: Licensee.h:46
idSys * sys
Definition: maya_main.cpp:48
static bool forceExport
Definition: Anim.h:609
virtual int DLL_Load(const char *dllName)=0
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
virtual const char * GetCVarString(const char *name) const =0
const char * GetFile(int index) const
Definition: FileSystem.h:127
void void Warning(const char *str,...) const id_attribute((format(printf
Definition: Parser.cpp:335
bool ExportModel(const char *model)
const char * path
Definition: sws.c:117
void Clear(void)
Definition: Str.h:724
virtual void FreeFileList(idFileList *fileList)=0
idGameLocal gameLocal
Definition: Game_local.cpp:64
int ExportModels(const char *pathname, const char *extension)
int LoadMemory(const char *ptr, int length, const char *name, int startLine=1)
Definition: Lexer.cpp:1646
#define MAX_OSPATH
Definition: posix_main.cpp:47
virtual const char * RelativePathToOSPath(const char *relativePath, const char *basePath="fs_devpath")=0
bool(* exporterDLLEntry_t)(int version, idCommon *common, idSys *sys)
Definition: maya_main.h:41
const char * GetString(void) const
Definition: CVarSystem.h:141
virtual void DLL_Unload(int dllHandle)=0
int ParseExportSection(idParser &parser)
static void LoadMayaDll(void)
#define MD5_MESH_EXT
Definition: Model.h:42
int LoadFile(const char *filename, bool OSPath=false)
Definition: Parser.cpp:3013
void(* exporterShutdown_t)(void)
Definition: maya_main.h:43
const char * ParseRestOfLine(idStr &out)
Definition: Parser.cpp:2723
int CheckTokenString(const char *string)
Definition: Parser.cpp:2491
Definition: Str.h:116
void Reset(void)
int SkipBracedSection(bool parseFirstBrace=true)
Definition: Parser.cpp:2611
static void Shutdown(void)
Definition: Anim_Import.cpp:63
const char * c_str(void) const
Definition: Str.h:487
idCVar g_exportMask("g_exportMask","", CVAR_GAME,"")
static bool CheckMayaInstall(void)
Definition: Anim_Import.cpp:86
idGame * game
Definition: Game_local.cpp:65
virtual void CreateOSPath(const char *OSPath)=0
virtual void SetRefreshOnPrint(bool set)=0
char * va(const char *fmt,...)
Definition: Str.cpp:1568
virtual void FindDLL(const char *basename, char dllPath[MAX_OSPATH], bool updateChecksum)=0
#define MD5_VERSION
Definition: Model.h:45
idStr dest
Definition: Anim.h:205
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
const char *(* exporterInterface_t)(const char *ospath, const char *commandline)
Definition: maya_main.h:42
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
const char * GetFileName(void) const
Definition: Parser.h:247
bool ConvertMayaToMD5(void)
static bool initialized
Definition: Anim.h:200