Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
10 KiB

  1. //=============================================================================
  2. //
  3. //========= Copyright Valve Corporation, All rights reserved. ============//
  4. // The contents may be used and/or copied only with the written permission of
  5. // Valve, L.L.C., or in accordance with the terms and conditions stipulated in
  6. // the agreement/contract under which the contents have been supplied.
  7. //
  8. // $Header: $
  9. // $NoKeywords: $
  10. //
  11. //=============================================================================
  12. // Standard includes
  13. #include <ctype.h>
  14. #include <io.h>
  15. // Valve includes
  16. #include "appframework/AppFramework.h"
  17. #include "datamodel/idatamodel.h"
  18. #include "filesystem.h"
  19. #include "icommandline.h"
  20. #include "materialsystem/imaterialsystem.h"
  21. #include "mathlib/mathlib.h"
  22. #include "tier1/tier1.h"
  23. #include "tier2/tier2.h"
  24. #include "tier2/tier2dm.h"
  25. #include "tier3/tier3.h"
  26. #include "tier1/UtlStringMap.h"
  27. #include "vstdlib/vstdlib.h"
  28. #include "vstdlib/iprocessutils.h"
  29. #include "tier2/p4helpers.h"
  30. #include "p4lib/ip4.h"
  31. // Lua includes
  32. #include <lua.h>
  33. #include <lauxlib.h>
  34. #include <lualib.h>
  35. // Local includes
  36. #include "dmxedit.h"
  37. //-----------------------------------------------------------------------------
  38. // The application object
  39. //-----------------------------------------------------------------------------
  40. class CDmxEditApp : public CDefaultAppSystemGroup< CSteamAppSystemGroup >
  41. {
  42. public:
  43. // Methods of IApplication
  44. virtual bool Create();
  45. virtual bool PreInit( );
  46. virtual int Main();
  47. virtual void PostShutdown();
  48. void PrintHelp( bool bWiki = false );
  49. };
  50. DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( CDmxEditApp );
  51. //-----------------------------------------------------------------------------
  52. // The application object
  53. //-----------------------------------------------------------------------------
  54. bool CDmxEditApp::Create()
  55. {
  56. AppSystemInfo_t appSystems[] =
  57. {
  58. { "vstdlib.dll", PROCESS_UTILS_INTERFACE_VERSION },
  59. { "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
  60. { "p4lib.dll", P4_INTERFACE_VERSION },
  61. { "", "" } // Required to terminate the list
  62. };
  63. AddSystems( appSystems );
  64. IMaterialSystem *pMaterialSystem = reinterpret_cast< IMaterialSystem * >( FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION ) );
  65. if ( !pMaterialSystem )
  66. {
  67. Error( "// ERROR: Unable to connect to material system interface!\n" );
  68. return false;
  69. }
  70. pMaterialSystem->SetShaderAPI( "shaderapiempty.dll" );
  71. return true;
  72. }
  73. //-----------------------------------------------------------------------------
  74. //
  75. //-----------------------------------------------------------------------------
  76. bool CDmxEditApp::PreInit( )
  77. {
  78. CreateInterfaceFn factory = GetFactory();
  79. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
  80. ConnectTier1Libraries( &factory, 1 );
  81. ConnectTier2Libraries( &factory, 1 );
  82. ConnectTier3Libraries( &factory, 1 );
  83. if ( !ConnectDataModel( factory ) )
  84. return false;
  85. if ( InitDataModel( ) != INIT_OK )
  86. return false;
  87. if ( !g_pFullFileSystem || !g_pDataModel )
  88. {
  89. Error( "// ERROR: dmxedit is missing a required interface!\n" );
  90. return false;
  91. }
  92. return true;
  93. }
  94. //-----------------------------------------------------------------------------
  95. //
  96. //-----------------------------------------------------------------------------
  97. void CDmxEditApp::PostShutdown()
  98. {
  99. ShutdownDataModel();
  100. DisconnectDataModel();
  101. DisconnectTier3Libraries();
  102. DisconnectTier2Libraries();
  103. DisconnectTier1Libraries();
  104. }
  105. //-----------------------------------------------------------------------------
  106. // The application object
  107. //-----------------------------------------------------------------------------
  108. int CDmxEditApp::Main()
  109. {
  110. // This bit of hackery allows us to access files on the harddrive
  111. g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
  112. if ( CommandLine()->CheckParm( "-h" ) || CommandLine()->CheckParm( "-help" ) )
  113. {
  114. PrintHelp();
  115. return 0;
  116. }
  117. if ( CommandLine()->CheckParm( "-wiki" ) )
  118. {
  119. PrintHelp( true );
  120. return 0;
  121. }
  122. CUtlStringMap< CUtlString > setVars;
  123. CUtlString sGame;
  124. const int nParamCount = CommandLine()->ParmCount();
  125. for ( int i = 0; i < nParamCount - 1; ++i )
  126. {
  127. const char *pCmd = CommandLine()->GetParm( i );
  128. const char *pArg = CommandLine()->GetParm( i + 1 );
  129. if ( StringHasPrefix( pCmd, "-s" ) )
  130. {
  131. const char *const pEquals = strchr( pArg, '=' );
  132. if ( !pEquals )
  133. {
  134. Warning( "Warning: Invalid command line args, no ='s in -set argument: %s %s\n", pCmd, pArg );
  135. }
  136. char buf[ BUFSIZ ];
  137. Q_strncpy( buf, pArg, pEquals - pArg + 1 );
  138. const CUtlString sKey( buf );
  139. CUtlString sVal( pEquals + 1 );
  140. if ( !V_isdigit( *sVal.Get() ) && *sVal.Get() != '-' && *sVal.Get() != '"' )
  141. {
  142. CUtlString sqVal( "\"" );
  143. sqVal += sVal;
  144. sqVal += "\"";
  145. sVal = sqVal;
  146. }
  147. setVars[ sKey ] = sVal;
  148. if ( !Q_stricmp( sKey.Get(), "game" ) && sGame.IsEmpty() )
  149. {
  150. sGame = sKey;
  151. }
  152. ++i;
  153. }
  154. else if ( StringHasPrefix( pCmd, "-g" ) )
  155. {
  156. if ( *pArg == '"' )
  157. {
  158. sGame = pArg;
  159. }
  160. else
  161. {
  162. sGame = ( "\"" );
  163. sGame += pArg;
  164. sGame += "\"";
  165. }
  166. }
  167. else if ( StringHasPrefix( pCmd, "-nop4" ) )
  168. {
  169. // Don't issue warning on -nop4
  170. }
  171. else if ( StringHasPrefix( pCmd, "-coe" ) || StringHasPrefix( pCmd, "-ContinueOnError" ) )
  172. {
  173. // Don't issue warning on -nop4
  174. }
  175. else if ( StringHasPrefix( pCmd, "-" ) )
  176. {
  177. Warning( "Warning: Unknown command line argument: %s\n", pCmd );
  178. }
  179. }
  180. // Do Perforce Stuff
  181. if ( CommandLine()->FindParm( "-nop4" ) )
  182. g_p4factory->SetDummyMode( true );
  183. g_p4factory->SetOpenFileChangeList( "dmxedit" );
  184. for ( int i = CommandLine()->ParmCount() - 1; i >= 1; --i )
  185. {
  186. const char *pParam = CommandLine()->GetParm( i );
  187. if ( _access( pParam, 04 ) == 0 )
  188. {
  189. CDmxEditLua dmxEditLua;
  190. for ( int i = 0; i < setVars.GetNumStrings(); ++i )
  191. {
  192. dmxEditLua.SetVar( setVars.String( i ), setVars[ i ] );
  193. }
  194. if ( !sGame.IsEmpty() )
  195. {
  196. dmxEditLua.SetGame( sGame );
  197. }
  198. return dmxEditLua.DoIt( pParam );
  199. }
  200. }
  201. Error( "Cannot find any file to execute from passed command line arguments\n\n" );
  202. PrintHelp();
  203. return -1;
  204. }
  205. //-----------------------------------------------------------------------------
  206. //
  207. //-----------------------------------------------------------------------------
  208. CUtlString Wikize( lua_State *pLuaState, const char *pWikiString )
  209. {
  210. CUtlString retVal( pWikiString );
  211. lua_pushstring( pLuaState, "string");
  212. lua_gettable( pLuaState, LUA_GLOBALSINDEX );
  213. lua_pushstring( pLuaState, "gsub");
  214. lua_gettable( pLuaState, -2);
  215. lua_pushstring( pLuaState, pWikiString );
  216. lua_pushstring( pLuaState, "([$#]%w+)" );
  217. lua_pushstring( pLuaState, "'''%0'''" );
  218. if ( lua_pcall( pLuaState, 3, 1, 0 ) == 0 )
  219. {
  220. if ( lua_isstring( pLuaState, -1 ) )
  221. {
  222. retVal = lua_tostring( pLuaState, -1 );
  223. }
  224. lua_pop( pLuaState, 1 );
  225. }
  226. return retVal;
  227. }
  228. //-----------------------------------------------------------------------------
  229. //
  230. //-----------------------------------------------------------------------------
  231. template < class T_t >
  232. int Sort_LuaFunc_s( const T_t *pA, const T_t *pB )
  233. {
  234. return Q_stricmp( (*pA)->m_pFuncName, (*pB)->m_pFuncName );
  235. }
  236. //-----------------------------------------------------------------------------
  237. //
  238. //-----------------------------------------------------------------------------
  239. void CDmxEditApp::PrintHelp( bool bWiki /* = false */ )
  240. {
  241. CUtlVector< LuaFunc_s * > luaFuncs;
  242. for ( LuaFunc_s *pFunc = LuaFunc_s::s_pFirstFunc; pFunc; pFunc = pFunc->m_pNextFunc )
  243. {
  244. luaFuncs.AddToTail( pFunc );
  245. }
  246. luaFuncs.Sort( Sort_LuaFunc_s );
  247. if ( bWiki && LuaFunc_s::s_pFirstFunc )
  248. {
  249. lua_State *pLuaState = lua_open();
  250. if ( pLuaState )
  251. {
  252. luaL_openlibs( pLuaState );
  253. CUtlString wikiString;
  254. for ( int i = 0; i < luaFuncs.Count(); ++i )
  255. {
  256. const LuaFunc_s *pFunc = luaFuncs[ i ];
  257. if ( pFunc != LuaFunc_s::s_pFirstFunc )
  258. {
  259. Msg( "\n" );
  260. }
  261. Msg( ";%s( %s );\n", pFunc->m_pFuncName, pFunc->m_pFuncPrototype );
  262. Msg( ":%s\n", Wikize( pLuaState, pFunc->m_pFuncDesc ).Get() );
  263. }
  264. return;
  265. }
  266. }
  267. Msg( "\n" );
  268. Msg( "NAME\n" );
  269. Msg( " dmxedit - Edit dmx files\n" );
  270. Msg( "\n" );
  271. Msg( "SYNOPSIS\n" );
  272. Msg( " dmxedit [ -h | -help ] [ -game <$game> ] [ -set $var=val ] [ script.lua ]\n" );
  273. Msg( "\n" );
  274. Msg( " -h | -help : Prints this information\n" );
  275. Msg( " -g | -game <$game> : Sets the VPROJECT environment variable to the specified game.\n" );
  276. Msg( " -s | -set <$var=val> : Sets the lua variable var to the specified val before the script is run.\n" );
  277. Msg( "\n" );
  278. Msg( "DESCRIPTION\n" );
  279. Msg( " Edits dmx files by executing a lua script of dmx editing functions\n" );
  280. Msg( "\n" );
  281. if ( !LuaFunc_s::s_pFirstFunc )
  282. return;
  283. Msg( "FUNCTIONS\n" );
  284. const char *pWhitespace = " \t";
  285. for ( int i = 0; i < luaFuncs.Count(); ++i )
  286. {
  287. const LuaFunc_s *pFunc = luaFuncs[ i ];
  288. Msg( " %s( %s );\n", pFunc->m_pFuncName, pFunc->m_pFuncPrototype );
  289. Msg( " * " );
  290. CUtlString tmpStr;
  291. const char *pWordBegin = pFunc->m_pFuncDesc + strspn( pFunc->m_pFuncDesc, pWhitespace );
  292. const char *pWhiteSpaceBegin = pWordBegin;
  293. const char *pWordEnd = pWordBegin + strcspn( pWordBegin, pWhitespace );
  294. bool bNewline = false;
  295. while ( *pWordBegin )
  296. {
  297. if ( pWordEnd - pWhiteSpaceBegin + tmpStr.Length() > 70 )
  298. {
  299. if ( bNewline )
  300. {
  301. Msg( " " );
  302. }
  303. else
  304. {
  305. bNewline = true;
  306. }
  307. Msg( "%s\n", tmpStr.Get() );
  308. tmpStr.Set( "" );
  309. }
  310. if ( tmpStr.Length() )
  311. {
  312. tmpStr += CUtlString( pWhiteSpaceBegin, pWordEnd - pWhiteSpaceBegin + 1);
  313. }
  314. else
  315. {
  316. tmpStr += CUtlString( pWordBegin, pWordEnd - pWordBegin + 1 );
  317. }
  318. pWhiteSpaceBegin = pWordEnd;
  319. pWordBegin = pWhiteSpaceBegin + strspn( pWhiteSpaceBegin, pWhitespace );
  320. pWordEnd = pWordBegin + strcspn( pWordBegin, pWhitespace );
  321. }
  322. if ( tmpStr.Length() )
  323. {
  324. if ( bNewline )
  325. {
  326. Msg( " " );
  327. }
  328. Msg( "%s\n", tmpStr.Get() );
  329. }
  330. Msg( "\n" );
  331. }
  332. Msg( "CREDITS\n" );
  333. Msg( " Lua Copyright � 1994-2006 Lua.org, PUC-Rio.\n ");
  334. Msg( "\n" );
  335. }