Counter Strike : Global Offensive Source Code
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.

439 lines
13 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "vgui/ILocalize.h"
  9. #include "vgui/ISystem.h"
  10. #include "sfuimemoryfile.h"
  11. #include <vstdlib/vstrtools.h>
  12. #if defined( _PS3 )
  13. #include "ps3/ps3_win32stubs.h"
  14. #endif
  15. #include "../../game/shared/econ/econ_item_view_helpers.h"
  16. // NOTE: This must be the last file included!!!
  17. #include "tier0/memdbgon.h"
  18. using namespace SF::GFx;
  19. ConVar dev_scaleform_debug( "dev_scaleform_debug", "0", FCVAR_DEVELOPMENTONLY );
  20. /*************************************
  21. * memory allocation wrapper
  22. */
  23. void* CScaleformSysAlloc::Alloc( SF::UPInt size, SF::UPInt align )
  24. {
  25. return MemAlloc_AllocAlignedUnattributed( size, align );
  26. }
  27. void CScaleformSysAlloc::Free( void* ptr, SF::UPInt size, SF::UPInt align )
  28. {
  29. MemAlloc_FreeAligned( ptr );
  30. }
  31. void* CScaleformSysAlloc::Realloc( void* oldPtr, SF::UPInt oldSize, SF::UPInt newSize, SF::UPInt align )
  32. {
  33. return MemAlloc_ReallocAligned( oldPtr, newSize, align );
  34. }
  35. /*****************************************************
  36. * This redirects the scaleform logging calls to CSTrike
  37. */
  38. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_SCALEFORM, "Scaleform" );
  39. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_SCALEFORM_SCRIPT, "ScaleformScript" );
  40. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_SCALEFORM_PARSE, "ScaleformParse" );
  41. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_SCALEFORM_AS, "ScaleformAS" );
  42. #define SCALEFORM_LOG_COLOR (::Color(180,180,255, 255))
  43. void ScaleformUILogging::LogMessageVarg( SF::LogMessageId messageId, const char* pfmt, va_list argList )
  44. {
  45. if ( !dev_scaleform_debug.GetBool() )
  46. return;
  47. const char *pPrefix = "SF: ";
  48. LoggingChannelID_t logChannel = LOG_SCALEFORM;
  49. switch ( messageId & SF::LogChannel_Mask )
  50. {
  51. case SF::LogChannel_Debug:
  52. pPrefix = "SF (Debug): ";
  53. break;
  54. case SF::LogChannel_Render:
  55. pPrefix = "SF (Render): ";
  56. break;
  57. case SF::LogChannel_Script:
  58. logChannel = LOG_SCALEFORM_SCRIPT;
  59. pPrefix = "SF (Script): ";
  60. break;
  61. case SF::LogChannel_Parse:
  62. logChannel = LOG_SCALEFORM_PARSE;
  63. pPrefix = "SF (Parse): ";
  64. break;
  65. case SF::LogChannel_Action:
  66. logChannel = LOG_SCALEFORM_AS;
  67. pPrefix = "SF (Action): ";
  68. break;
  69. }
  70. LoggingSeverity_t logSeverity;
  71. switch ( messageId.GetMessageType() )
  72. {
  73. case SF::LogMessage_Error:
  74. logSeverity = LS_WARNING;
  75. break;
  76. case SF::LogMessage_Warning:
  77. logSeverity = LS_WARNING;
  78. break;
  79. case SF::LogMessage_Text:
  80. logSeverity = LS_MESSAGE;
  81. break;
  82. default:
  83. logSeverity = LS_MESSAGE;
  84. break;
  85. }
  86. if ( LoggingSystem_IsChannelEnabled( logChannel, logSeverity ) )
  87. {
  88. tchar formattedMessage[MAX_LOGGING_MESSAGE_LENGTH];
  89. Tier0Internal_vsntprintf( formattedMessage, sizeof( formattedMessage )-1, pfmt, argList );
  90. formattedMessage[sizeof( formattedMessage ) - 1] = 0;
  91. // optional categorizing prefix
  92. if ( pPrefix )
  93. {
  94. LoggingSystem_LogDirect( logChannel, logSeverity, SCALEFORM_LOG_COLOR, pPrefix );
  95. }
  96. LoggingSystem_LogDirect( logChannel, logSeverity, SCALEFORM_LOG_COLOR, formattedMessage );
  97. // scaleform messages randomly lack terminal \n, add to prevent undesired joined spew
  98. int len = _tcslen( formattedMessage );
  99. if ( len > 0 && formattedMessage[len-1] != '\n' )
  100. {
  101. LoggingSystem_LogDirect( logChannel, logSeverity, SCALEFORM_LOG_COLOR, "\n" );
  102. }
  103. }
  104. }
  105. /****************************************************************
  106. * contains the adapter methods for clipboard
  107. */
  108. void ScaleformClipboard::OnTextStore( const wchar_t* ptext, SF::UPInt len )
  109. {
  110. if ( ptext && len )
  111. {
  112. g_pVGuiSystem->SetClipboardText( ptext, len );
  113. }
  114. }
  115. /****************************************************************
  116. * contains the adapter methods for translations
  117. */
  118. unsigned int ScaleformTranslatorAdapter::GetCaps( void ) const
  119. {
  120. return Cap_StripTrailingNewLines;
  121. }
  122. void ScaleformTranslatorAdapter::Translate( TranslateInfo* tinfo )
  123. {
  124. const wchar_t* pkey = tinfo->GetKey();
  125. if ( pkey && ( *pkey == L'#' ) )
  126. {
  127. int len = Q_wcslen( pkey );
  128. char *asciiString = ( char * ) stackalloc( len + 1 );
  129. V_UnicodeToUTF8( pkey, asciiString, len + 1 );
  130. bool isHTML = false;
  131. const wchar_t* translated = SFINST.Translate( asciiString, &isHTML );
  132. tinfo->SetResultHtml( translated );
  133. }
  134. }
  135. /********************
  136. * used by CreateAPI. It attaches the movieview to the GFxValue of the api
  137. */
  138. void ScaleformMovieUserData::OnDestroy( Movie* pmovie, void* pobject )
  139. {
  140. m_pMovie = NULL;
  141. Release();
  142. }
  143. /*******************************
  144. * this defines the actual m_Callback function for the function handler class
  145. */
  146. void ScaleformFunctionHandlerAdapter::Call( const Params& params )
  147. {
  148. ScaleformCallbackHolder* pCallback = ( ScaleformCallbackHolder* ) params.pUserData;
  149. if ( pCallback )
  150. {
  151. pCallback->Execute(const_cast<Params*>(&params ));
  152. }
  153. }
  154. void ScaleformCallbackHolder::OnDestroy( Movie* pmovie, void* pobject )
  155. {
  156. Release();
  157. }
  158. /********************************
  159. * this lets scaleform use the valve file location stuff
  160. */
  161. SF::File* ScaleformFileOpener::OpenFile( const char *purl, int flags, int modes )
  162. {
  163. MEM_ALLOC_CREDIT();
  164. return OpenFileEx( purl, NULL, flags, modes );
  165. }
  166. SF::SInt64 ScaleformFileOpener::GetFileModifyTime( const char *purl )
  167. {
  168. SF::SInt64 result = g_pFullFileSystem->GetFileTime( purl, "GAME" );
  169. return !result ? -1 : 0;
  170. }
  171. // Implementation that allows us to override the log.
  172. SF::File* ScaleformFileOpener::OpenFileEx( const char *pfilename, Log *plog, int flags, int modes )
  173. {
  174. MEM_ALLOC_CREDIT();
  175. if ( ( flags & ~SF::FileConstants::Open_Buffered ) != SF::FileConstants::Open_Read )
  176. {
  177. if ( plog )
  178. {
  179. plog->LogError( "Error: GFxLoader cannot open '%s' for writing. writing is not supported\n", pfilename );
  180. }
  181. return NULL;
  182. }
  183. SFUIMemoryFile* pin = new SFUIMemoryFile( pfilename );
  184. const char* realName = SFINST.CorrectFlashFileName( pfilename );
  185. extern IScaleformSlotInitController *g_pExternalScaleformSlotInitController;
  186. // is this an image stored in the stringtables?
  187. if ( char const *szExternalImg = StringAfterPrefix( realName, "img://stringtables:" ) )
  188. {
  189. // skip width and height attributes if they exist "(64x128):"
  190. const char * szExternalImgPostSizeParm = strstr( szExternalImg, "):" );
  191. if ( szExternalImgPostSizeParm != NULL )
  192. {
  193. szExternalImg = szExternalImgPostSizeParm + 2;
  194. }
  195. int length = 0;
  196. const void * pImageData = NULL;
  197. if ( g_pExternalScaleformSlotInitController )
  198. {
  199. pImageData = g_pExternalScaleformSlotInitController->GetStringUserData( "InfoPanel", szExternalImg, &length );
  200. if ( pImageData )
  201. {
  202. pin->GetBuffer().SetExternalBuffer( (void *)pImageData, length, 0, pin->GetBuffer().READ_ONLY );
  203. pin->Init();
  204. }
  205. else
  206. {
  207. pin->Release();
  208. pin = NULL;
  209. }
  210. }
  211. }
  212. else if ( g_pFullFileSystem->ReadFile( realName, "GAME", pin->GetBuffer() ) )
  213. {
  214. if ( g_pExternalScaleformSlotInitController )
  215. g_pExternalScaleformSlotInitController->OnFileLoadedByScaleform( realName, pin->GetBuffer().Base(), pin->GetBuffer().TellPut() );
  216. pin->Init();
  217. }
  218. else
  219. {
  220. if ( g_pExternalScaleformSlotInitController )
  221. g_pExternalScaleformSlotInitController->OnFileLoadedByScaleform( realName, NULL, 0 );
  222. pin->Release();
  223. pin = NULL;
  224. if ( plog )
  225. {
  226. plog->LogError( "Error: GFxLoader failed to open '%s'\n", realName );
  227. }
  228. }
  229. return pin;
  230. }
  231. /********************************
  232. * this lets scaleform use our gamer icons and any other dynamic textures
  233. */
  234. CScaleformImageCreator::CScaleformImageCreator( IScaleformUI *pSFUI, TextureManager* textureManager /* = 0 */)
  235. : ImageCreator( textureManager ), m_pScaleformUI( pSFUI )
  236. {
  237. }
  238. Image* CScaleformImageCreator::LoadProtocolImage(const ImageCreateInfo& info, const SF::String& url)
  239. {
  240. MEM_ALLOC_CREDIT();
  241. // We use this to handle loadMovie calls from action script that
  242. // we can use to load player avatar icons, inventory item images, Chrome HTML images, or extern files on disk.
  243. // The url coming in should be something like this: img://<type>_<data>
  244. //
  245. // This is for loading external image sitting on disk
  246. // Syntax1: img://loadfile:mylocalfile.jpg - loads the file, can be JPG, PNG, PGA, or DDS (must be uncompressed)
  247. // Syntax2: img://loadfile:(64x64):mylocalfile.jpg - loads the file, returns a transparent texture of given size if doesn't exist
  248. //
  249. char const *szExternalImg = StringAfterPrefix( url, "img://loadfile:" );
  250. // allow loadjpeg until flash is updated to use loadfile
  251. if ( !szExternalImg )
  252. {
  253. szExternalImg = StringAfterPrefix( url, "img://loadjpeg:" );
  254. }
  255. if ( szExternalImg )
  256. {
  257. // Parse width and height attributes
  258. uint width = 0, height = 0;
  259. if ( szExternalImg[0] == '(' )
  260. {
  261. width = Q_atoi( szExternalImg + 1 );
  262. szExternalImg = strchr( szExternalImg, 'x' );
  263. if ( !szExternalImg )
  264. return NULL;
  265. height = Q_atoi( szExternalImg + 1 );
  266. szExternalImg = strstr( szExternalImg, "):" );
  267. if ( !szExternalImg )
  268. return NULL;
  269. szExternalImg += 2;
  270. }
  271. char chLocalPath[ 2*MAX_PATH + 1 ] = {};
  272. const char *pchFullImgPath = szExternalImg[0] ? g_pFullFileSystem->RelativePathToFullPath( szExternalImg, "GAME", chLocalPath, Q_ARRAYSIZE( chLocalPath ) - 1 ) : NULL;
  273. if ( pchFullImgPath )
  274. {
  275. Image *pImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->CreateImageFromFile( pchFullImgPath, info, width, height );
  276. return pImage;
  277. }
  278. }
  279. // "img://avatar_[xuid]" where [xuid] is the xuid of the player whose avatar we want to load.
  280. else if ( char const *szAvatarXuid = StringAfterPrefix( url, "img://avatar_" ) )
  281. {
  282. int64 xuid = Q_atoi64( szAvatarXuid );
  283. ScaleformUIAvatarImage* pAvatarImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->GetAvatarImage( xuid );
  284. if ( pAvatarImage )
  285. {
  286. return pAvatarImage->GetImage();
  287. }
  288. }
  289. // "img://inventory_[itemid]" where [itemid] is the item's id from GetItemIDbyIndex() in the inventory component.
  290. else if ( char const *szInventoryItemId = StringAfterPrefix( url, "img://inventory_" ) )
  291. {
  292. uint64 itemid = Q_atoi64( szInventoryItemId );
  293. // look up image here using xuid and itemid and return it
  294. ScaleformUIInventoryImage* pInventoryImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->GetInventoryImage( itemid );
  295. if ( pInventoryImage )
  296. {
  297. return pInventoryImage->GetImage();
  298. }
  299. }
  300. // "img://itemdata_[defindex]_[paintindex]" where [defindex] & [paintindex] are econ item definition and paint indices.
  301. else if ( StringHasPrefix( url, "img://itemdata_" ) )
  302. {
  303. uint16 iDefIndex = 0;
  304. uint16 iPaintIndex = 0;
  305. {
  306. CUtlVector< char* > urlFragments;
  307. V_SplitString( url, "_", urlFragments );
  308. iDefIndex = ( uint16 ) atoi( urlFragments[1] );
  309. iPaintIndex = ( uint16 ) atoi( urlFragments[2] );
  310. urlFragments.PurgeAndDeleteElements();
  311. }
  312. uint64 ullItemId = CombinedItemIdMakeFromDefIndexAndPaint( iDefIndex, iPaintIndex );
  313. // look up image here using defindex and paintindex and return it
  314. ScaleformUIInventoryImage* pInventoryImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->GetInventoryImage( ullItemId );
  315. if ( pInventoryImage )
  316. {
  317. return pInventoryImage->GetImage();
  318. }
  319. }
  320. else if ( char const *szBilinearChromeImg = StringAfterPrefix( url, "img://chrome_" ) ) // using bilinear filtering
  321. {
  322. int64 imageid = Q_atoi64( szBilinearChromeImg );
  323. // look up image here using xuid and itemid and return it
  324. ScaleformUIChromeHTMLImage* pChromeImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->GetChromeHTMLImage( imageid );
  325. if ( pChromeImage )
  326. {
  327. return pChromeImage->GetImage();
  328. }
  329. }
  330. else if ( char const *szPointSampleChromeImg = StringAfterPrefix( url, "imgps://chrome_" ) ) // point sampling filtering
  331. {
  332. int64 imageid = Q_atoi64( szPointSampleChromeImg );
  333. // look up image here using xuid and itemid and return it
  334. ScaleformUIChromeHTMLImage* pChromeImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->GetChromeHTMLImage( imageid );
  335. if ( pChromeImage )
  336. {
  337. return pChromeImage->GetImage();
  338. }
  339. }
  340. else if ( char const *szExternalImg = StringAfterPrefix( url, "img://stringtables:" ) )
  341. {
  342. // Parse width and height attributes
  343. uint width = 0, height = 0;
  344. if ( szExternalImg[ 0 ] == '(' )
  345. {
  346. width = Q_atoi( szExternalImg + 1 );
  347. szExternalImg = strchr( szExternalImg, 'x' );
  348. if ( !szExternalImg )
  349. return NULL;
  350. height = Q_atoi( szExternalImg + 1 );
  351. szExternalImg = strstr( szExternalImg, "):" );
  352. if ( !szExternalImg )
  353. return NULL;
  354. szExternalImg += 2;
  355. }
  356. if ( !szExternalImg || !szExternalImg[ 0 ] )
  357. return NULL;
  358. // we're going to pass in the whole url because the prefix will signal to the file loader to get the data from stringtables rather than from the filesystem
  359. Image *pImage = ( ( ScaleformUIImpl* )m_pScaleformUI )->CreateImageFromFile( url, info, width, height );
  360. if ( pImage )
  361. return pImage;
  362. }
  363. return NULL;
  364. }