GFxPlayerTinyD3D9.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /**********************************************************************
  2. Filename : GFxPlayerTinyD3D9.cpp
  3. Content : Tiny GFxPlayer sample for Direct3D 9.
  4. Created : March 13, 2008
  5. Authors : Michael Antonov, Dmitry Polenur
  6. Copyright : (c) 2001-2008 Scaleform Corp. All Rights Reserved.
  7. Licensees may use this file in accordance with the valid Scaleform
  8. Commercial License Agreement provided with the software.
  9. This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
  10. THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
  11. ***********************************************************************
  12. --- GFxPlayerTiny Description ---
  13. GFxPlayerTiny is the simplest possible GFx player implementation
  14. provided for each target platform. The player loads a single specified
  15. file (or "Window.swf" by default) and plays it back while handling
  16. input. Developers should go through this sample in detail before
  17. performing engine integration.
  18. The sample illustrates the following concepts:
  19. - Performing minimal Win32 system and D3D9 initialization required
  20. for running GFx.
  21. - Creating GRendererD3D9 and configuring it to work with
  22. a pre-configured video mode.
  23. - Initializing GFxLoader with renderer and other settings and
  24. using it to load a SWF/GFX file into a GFxMovieDef.
  25. - Creating a movie instance (GFxMovieView) from GFxMovieDef.
  26. - Playing back the movie by calling Advance and Display every frame.
  27. - Feeding mouse/keyboard events to the movie by calling HandleEvent.
  28. - Handling player-generated events by installing GFxFSCommandHandler.
  29. **********************************************************************/
  30. // RakNet: Fix 'fd_set' : 'struct' type redefinition
  31. #include "WindowsIncludes.h"
  32. // GFx Includes
  33. #include "GFile.h"
  34. #include "GFxPlayer.h"
  35. #include "GFxLoader.h"
  36. #include "GRendererD3D9.h"
  37. // System Includes
  38. #include <windows.h>
  39. #include <d3d9.h>
  40. // SWF Filename we will load by default.
  41. #define FXPLAYER_FILENAME "Resources/AutopatcherClientGFx3_CS3.swf"
  42. // Window title to use for the application.
  43. #define FXPLAYER_APP_TITLE "Scaleform GFxPlayerTinyD3D9 v" GFC_FX_VERSION_STRING
  44. // KevinJ: Does all the work of the autopatcher
  45. #include "AutopatcherClientGFx3Impl.h"
  46. // Need for delegates to work with the CLIK widgets
  47. #include "FxGameDelegate.h"
  48. // ***** FxPlayerTiny Application Class
  49. // FxPlayerTiny class encapsulates all of the system setup and GFxPlayer
  50. // program state needed for playback. FxPlayerTiny is created in main() /
  51. // WinMain() and contains most of the program logic in its Run function.
  52. class FxPlayerTiny
  53. {
  54. // Win32 window state variables.
  55. const char* pWndClassName;
  56. HWND hWnd;
  57. HINSTANCE hInstance;
  58. // Direct3D state variables.
  59. LPDIRECT3D9 pD3D; // Used to create the D3D9Device.
  60. LPDIRECT3DDEVICE9 pDevice; // Our rendering device.
  61. D3DPRESENT_PARAMETERS PresentParams;
  62. // Scaleform GFx object pointers.
  63. GPtr<GFxMovieDef> pMovieDef;
  64. GPtr<GFxMovieView> pMovie;
  65. GPtr<GRendererD3D9> pRenderer;
  66. GPtr<GFxRenderConfig> pRenderConfig;
  67. UInt32 MovieLastTime;
  68. // Toggle states.
  69. bool Wireframe;
  70. bool ControlKeyDown;
  71. bool AAEnabled;
  72. bool Paused; // Set when the movie is paused in the player.
  73. // Playback filename and window size.
  74. GString FileName;
  75. int Width;
  76. int Height;
  77. public:
  78. FxPlayerTiny(LPSTR pfilename);
  79. ~FxPlayerTiny();
  80. // Initialize the player and run playback loop.
  81. int Run();
  82. // Advance playback and render a frame.
  83. void AdvanceAndDisplay();
  84. // Input handler functions. Process mouse and keyboard and pass
  85. // appropriate GFxEvent notifications to GFxMovieView::HandleEvent.
  86. void OnKey(UInt keyCode, bool downFlag);
  87. void OnMouse(GFxEvent::EventType eventType, UInt button, SInt x, SInt y);
  88. void HandleKeyEvent(UInt keyCode, bool downFlag);
  89. // System window and rendering setup.
  90. bool SetupWindow(const GString& name);
  91. HRESULT ResetD3D();
  92. // Windows message handler functions. StaticWindowProc is called by the
  93. // system and delegates most of its processing to MemberWndProc.
  94. LRESULT MemberWndProc(UINT msg, WPARAM wParam, LPARAM lParam);
  95. static LRESULT CALLBACK StaticWindowProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam);
  96. };
  97. // A sample implementation of GFxFSCommandHandler. Users can install such a
  98. // handler to receive notifications from fscommand() calls in ActionScript.
  99. // Note that in many cases it is better to use GFxExternalInterface instead
  100. // since it allows for better argument passing through ExternalInterface.call.
  101. class FxPlayerFSCommandHandler : public GFxFSCommandHandler
  102. {
  103. public:
  104. virtual void Callback(GFxMovieView* pmovie, const char* pcommand, const char* parg)
  105. {
  106. // Do not log anything since we don't have a console.
  107. // printf("Command: %s, Args: %s", pcommand, parg);
  108. GUNUSED3(pmovie, pcommand, parg);
  109. }
  110. };
  111. // ***** FxPlayerTiny Class Implementation
  112. FxPlayerTiny::FxPlayerTiny(LPSTR pfilename)
  113. {
  114. pD3D = Direct3DCreate9(D3D_SDK_VERSION);
  115. pDevice = NULL;
  116. pWndClassName = "Direct3D_Window_Class";
  117. hWnd = 0;
  118. hInstance = 0;
  119. Wireframe = 0;
  120. ControlKeyDown = 0;
  121. AAEnabled = 1;
  122. Paused = 0;
  123. // Window size and filename.
  124. Width = 800;
  125. Height = 600;
  126. FileName = pfilename;
  127. }
  128. FxPlayerTiny::~FxPlayerTiny()
  129. {
  130. if (pDevice)
  131. pDevice->Release();
  132. if (pD3D)
  133. pD3D->Release();
  134. UnregisterClass(pWndClassName, hInstance);
  135. }
  136. // Called from main()/WindMain() after settings are initialized to execute
  137. // most of the program logic. Responsible for setting up the window,
  138. // loading movies and containing the playback/message loop.
  139. int FxPlayerTiny::Run()
  140. {
  141. if (!SetupWindow(GString(FXPLAYER_APP_TITLE " ") + FileName))
  142. return 1;
  143. // Show the window.
  144. ShowWindow(hWnd, SW_SHOWDEFAULT);
  145. UpdateWindow(hWnd);
  146. // Create and Configure GFxLoader.
  147. GFxLoader loader;
  148. // Developers set states on the loader to modify loading and playback behavior.
  149. // If you need to load files from a custom package, for example, you can
  150. // create a GFxFileOpener derived class that loads files in a custom way.
  151. // Here GFxFileOpener and GFxFSCommandHandler are set for sample purposes.
  152. GPtr<GFxFileOpener> pfileOpener = *new GFxFileOpener;
  153. loader.SetFileOpener(pfileOpener);
  154. GPtr<GFxFSCommandHandler> pcommandHandler = *new FxPlayerFSCommandHandler;
  155. loader.SetFSCommandHandler(pcommandHandler);
  156. // For D3D, it is good to override image creator to keep image data,
  157. // so that it can be restored in case of a lost device.
  158. GPtr<GFxImageCreator> pimageCreator = *new GFxImageCreator(1);
  159. loader.SetImageCreator(pimageCreator);
  160. // Load the movie file and create its instance.
  161. if (!(pMovieDef = *loader.CreateMovie(FileName)))
  162. {
  163. GString errorString = "Unable to load file: ";
  164. errorString += FileName;
  165. MessageBox(NULL, errorString.ToCStr(), "Error", MB_OK | MB_ICONEXCLAMATION);
  166. return 1;
  167. }
  168. if (!(pMovie = *pMovieDef->CreateInstance()))
  169. return 1;
  170. // Create renderer.
  171. if (!(pRenderer = *GRendererD3D9::CreateRenderer()))
  172. return 1;
  173. // Configure renderer in "Dependent mode", honoring externally
  174. // configured device settings.
  175. if (!pRenderer->SetDependentVideoMode(pDevice, &PresentParams, 0, hWnd))
  176. return 1;
  177. // Set renderer on loader so that it is also applied to all children.
  178. pRenderConfig = *new GFxRenderConfig(pRenderer, GFxRenderConfig::RF_EdgeAA | GFxRenderConfig::RF_StrokeNormal);
  179. loader.SetRenderConfig(pRenderConfig);
  180. // Set playback view to span the entire window.
  181. pMovie->SetViewport(Width, Height, 0,0, Width, Height);
  182. // If you wanted to use the movie as a transparent HUD overlay, you would
  183. // set Background Alpha to 0. We don't need to do this for player sample.
  184. // pMovie->SetBackgroundAlpha(0.0f);
  185. // Store initial timing, so that we can determine
  186. // how much to advance Flash playback.
  187. MovieLastTime = timeGetTime();
  188. // Application / Player message loop.
  189. MSG msg;
  190. ZeroMemory(&msg, sizeof(msg));
  191. // KevinJ: 1/3 functions, Init()
  192. // Path to current exe is used to the patcher can restart itself if needed
  193. RakNet::AutopatcherClientGFx3Impl acgi;
  194. char buff[512];
  195. GetModuleFileName(0, buff, 512);
  196. GPtr<FxDelegate> pDelegate = *new FxDelegate;
  197. pMovie->SetExternalInterface(pDelegate);
  198. acgi.Init(buff, pDelegate, pMovie);
  199. while(msg.message != WM_QUIT)
  200. {
  201. if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
  202. {
  203. TranslateMessage(&msg);
  204. DispatchMessage(&msg);
  205. }
  206. else
  207. {
  208. // Check for lost D3D Devices.
  209. if (pRenderer)
  210. {
  211. GRendererD3D9::DisplayStatus status = pRenderer->CheckDisplayStatus();
  212. if (status == GRendererD3D9::DisplayStatus_Unavailable)
  213. { ::Sleep(10); continue; }
  214. if (status == GRendererD3D9::DisplayStatus_NeedsReset)
  215. {
  216. if (!SUCCEEDED(ResetD3D()))
  217. continue;
  218. }
  219. }
  220. // Advance movie animation and render it to screen.
  221. AdvanceAndDisplay();
  222. }
  223. // KevinJ: 2/3 functions, periodic update
  224. acgi.Update();
  225. }
  226. // KevinJ: 3/3 functions, Shutdown()
  227. acgi.Shutdown();
  228. return 0;
  229. }
  230. // Advances GFx animation and draws the scene.
  231. void FxPlayerTiny::AdvanceAndDisplay()
  232. {
  233. // Clear the back buffer to a black color.
  234. pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(200,200,200), 1.0f, 0);
  235. // *** GFx Rendering
  236. if (pMovie)
  237. {
  238. // GRendererD3D9 does not modify D3DRS_FILLMODE, so we can set it here.
  239. pDevice->SetRenderState(D3DRS_FILLMODE,
  240. Wireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
  241. UInt32 time = timeGetTime();
  242. Float delta = ((Float)(time - MovieLastTime)) / 1000.0f;
  243. // Advance time and display the movie.
  244. if (!Paused)
  245. pMovie->Advance(delta);
  246. pMovie->Display();
  247. MovieLastTime = time;
  248. }
  249. // Present the back buffer contents to the display.
  250. pDevice->Present(NULL, NULL, NULL, NULL);
  251. }
  252. // Helper function that converts Windows VK keyCode values
  253. // to GFxKeyEvents and routes them to GFxPlayer.
  254. void FxPlayerTiny::HandleKeyEvent(UInt keyCode, bool downFlag)
  255. {
  256. GFxKey::Code key(GFxKey::VoidSymbol);
  257. if (keyCode >= 'A' && keyCode <= 'Z')
  258. {
  259. key = (GFxKey::Code) ((keyCode - 'A') + GFxKey::A);
  260. }
  261. else if (keyCode >= VK_F1 && keyCode <= VK_F15)
  262. {
  263. key = (GFxKey::Code) ((keyCode - VK_F1) + GFxKey::F1);
  264. }
  265. else if (keyCode >= VK_NUMPAD0 && keyCode <= VK_NUMPAD9)
  266. {
  267. key = (GFxKey::Code) ((keyCode - VK_NUMPAD0) + GFxKey::KP_0);
  268. }
  269. else
  270. {
  271. // Use a look-up table for keys don't correlate in order,.
  272. struct {
  273. int vk;
  274. GFxKey::Code gs;
  275. } table[] =
  276. {
  277. { VK_RETURN, GFxKey::Return },
  278. { VK_ESCAPE, GFxKey::Escape },
  279. { VK_LEFT, GFxKey::Left },
  280. { VK_UP, GFxKey::Up },
  281. { VK_RIGHT, GFxKey::Right },
  282. { VK_DOWN, GFxKey::Down },
  283. { VK_SPACE, GFxKey::Space },
  284. { VK_BACK, GFxKey::Backspace },
  285. { VK_DELETE, GFxKey::Delete },
  286. { VK_INSERT, GFxKey::Insert },
  287. // TODO: fill this out some more
  288. { 0, GFxKey::VoidSymbol }
  289. };
  290. for (int i = 0; table[i].vk != 0; i++)
  291. {
  292. if (keyCode == (UInt)table[i].vk)
  293. {
  294. key = table[i].gs;
  295. break;
  296. }
  297. }
  298. }
  299. if (key != GFxKey::VoidSymbol)
  300. {
  301. if (pMovie)
  302. {
  303. // Pass Key events to the movie so that can be handled in ActionScript.
  304. GFxKeyEvent event(downFlag ? GFxEvent::KeyDown : GFxKeyEvent::KeyUp, key);
  305. pMovie->HandleEvent(event);
  306. }
  307. }
  308. }
  309. // OnKey handles system keys by first interpreting some Ctrl+Key combinations
  310. // in a special way and passing the rest of them to the movie.
  311. void FxPlayerTiny::OnKey(UInt keyCode, bool downFlag)
  312. {
  313. if (!pMovie)
  314. return;
  315. bool ctrl = ControlKeyDown;
  316. if (keyCode == VK_CONTROL)
  317. {
  318. ControlKeyDown = downFlag;
  319. return;
  320. }
  321. if (keyCode == VK_MENU && downFlag)
  322. ControlKeyDown = false; // to enable Ctrl-Alt-... combinations to work
  323. if (ctrl && downFlag)
  324. {
  325. switch(keyCode)
  326. {
  327. case 'W':
  328. Wireframe = !Wireframe;
  329. break;
  330. case 'A':
  331. AAEnabled = ! AAEnabled;
  332. {
  333. UInt32 rendererFlags = pRenderConfig->GetRenderFlags() &
  334. ~GFxRenderConfig::RF_EdgeAA;
  335. if (AAEnabled)
  336. rendererFlags |= GFxRenderConfig::RF_EdgeAA;
  337. pRenderConfig->SetRenderFlags(rendererFlags);
  338. }
  339. break;
  340. case 'P':
  341. Paused = !Paused;
  342. break;
  343. }
  344. }
  345. else if (!ctrl)
  346. {
  347. HandleKeyEvent(keyCode, downFlag);
  348. }
  349. }
  350. void FxPlayerTiny::OnMouse(GFxEvent::EventType eventType, UInt button, SInt x, SInt y)
  351. {
  352. if (pMovie)
  353. {
  354. GFxMouseEvent mevent(eventType, button, (Float)x, (Float)y);
  355. pMovie->HandleEvent(mevent);
  356. }
  357. }
  358. // Setup Application Window and initialize Direct3D.
  359. bool FxPlayerTiny::SetupWindow(const GString& name)
  360. {
  361. hInstance = GetModuleHandle(NULL);
  362. // Register the window class
  363. WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, StaticWindowProc,
  364. 0L, sizeof(FxPlayerTiny*),
  365. hInstance, NULL, NULL, NULL, NULL,
  366. pWndClassName, NULL };
  367. RegisterClassEx(&wc);
  368. // Create the application's window.
  369. RECT r = { 100,100, 100 + Width, 100 + Height };
  370. ::AdjustWindowRect(&r, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
  371. HWND hWnd = CreateWindow(pWndClassName, name.ToCStr(),
  372. WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,
  373. r.left, r.top, r.right-r.left, r.bottom - r.top,
  374. GetDesktopWindow(), NULL, wc.hInstance, (LPVOID) this );
  375. if (!pD3D)
  376. return 0;
  377. // Set up the structure used to create the D3DDevice
  378. ZeroMemory(&PresentParams, sizeof(PresentParams));
  379. PresentParams.Windowed = TRUE;
  380. PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
  381. PresentParams.BackBufferFormat = D3DFMT_UNKNOWN;
  382. PresentParams.BackBufferWidth = Width;
  383. PresentParams.BackBufferHeight = Height;
  384. PresentParams.EnableAutoDepthStencil = 1;
  385. PresentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
  386. //PresentParams.MultiSampleQuality = D3DMULTISAMPLE_4_SAMPLES;
  387. // Create the D3DDevice
  388. if (FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  389. D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  390. &PresentParams, &pDevice ) ))
  391. {
  392. return 0;
  393. }
  394. return 1;
  395. }
  396. // Resets the D3D device and recreates triangle geometry.
  397. HRESULT FxPlayerTiny::ResetD3D()
  398. {
  399. // Set new mode
  400. if( FAILED(pDevice->Reset(&PresentParams) ))
  401. return E_FAIL;
  402. return S_OK;
  403. }
  404. // Window Message handler. Interprets windows messages and dispatches
  405. // mouse/keyboard input to the OnMouse/OnKeyboard functions.
  406. LRESULT FxPlayerTiny::MemberWndProc(UINT msg, WPARAM wParam, LPARAM lParam)
  407. {
  408. switch(msg)
  409. {
  410. case WM_DESTROY:
  411. PostQuitMessage(0);
  412. return 0;
  413. case WM_SETCURSOR:
  414. if (LOWORD(lParam)==HTCLIENT)
  415. {
  416. ::SetCursor(::LoadCursor(0, IDC_ARROW));
  417. return 0;
  418. }
  419. break;
  420. // *** The following logic is used to route input to GFxPlayer.
  421. case WM_MOUSEMOVE:
  422. OnMouse(GFxEvent::MouseMove, 0, LOWORD(lParam), HIWORD(lParam));
  423. return 0;
  424. case WM_LBUTTONDOWN:
  425. ::SetCapture(hWnd);
  426. OnMouse(GFxEvent::MouseDown, 0, LOWORD(lParam), HIWORD(lParam));
  427. return 0;
  428. case WM_LBUTTONUP:
  429. ::ReleaseCapture();
  430. OnMouse(GFxEvent::MouseUp, 0, LOWORD(lParam), HIWORD(lParam));
  431. return 0;
  432. case WM_KEYDOWN:
  433. OnKey((UInt)wParam, 1);
  434. return 0;
  435. case WM_KEYUP:
  436. OnKey((UInt)wParam, 0);
  437. return 0;
  438. case WM_CHAR:
  439. {
  440. UInt32 wcharCode = (UInt32)wParam;
  441. if (pMovie && wcharCode)
  442. {
  443. GFxCharEvent event(wcharCode);
  444. pMovie->HandleEvent(event);
  445. }
  446. }
  447. break;
  448. }
  449. return DefWindowProc(hWnd, msg, wParam, lParam);
  450. }
  451. // Static window function called by Windows for message processing. Implementation
  452. // delegates message processing to MemberWndProc.
  453. LRESULT CALLBACK FxPlayerTiny::StaticWindowProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  454. {
  455. FxPlayerTiny *papp;
  456. // The first message to ever come in sets the long value to class pointer.
  457. if (iMsg == WM_NCCREATE)
  458. {
  459. papp = (FxPlayerTiny*) ((LPCREATESTRUCT)lParam)->lpCreateParams;
  460. if (!papp)
  461. return DefWindowProcW(hwnd,iMsg,wParam,lParam);
  462. #ifdef GFC_64BIT_POINTERS
  463. SetWindowLongPtr(hwnd, 0, (LONG_PTR)papp);
  464. #else
  465. SetWindowLong(hwnd, 0, (LONG)(size_t)papp);
  466. #endif
  467. papp->hWnd = hwnd;
  468. }
  469. // Use size_t to quiet /Wp64 warning.
  470. if ( (papp=((FxPlayerTiny*)(size_t)GetWindowLongPtr(hwnd,0))) == 0 )
  471. return DefWindowProcW(hwnd,iMsg,wParam,lParam);
  472. // Call non-static member to Windows handle messages.
  473. return papp->MemberWndProc(iMsg, wParam, lParam);
  474. }
  475. // ***** WinMain() - Application entry point.
  476. // The main function implementation creates the FxPlayerTiny class,
  477. // passes it the filename and calls Run. FxPlayerTiny::Run is responsible
  478. // for all of the rendering setup and movie playback.
  479. INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, INT)
  480. {
  481. GFxSystem gfxInit;
  482. int result = 1;
  483. {
  484. // If command line is empty, use the default filename.
  485. LPSTR pfilename = (!lpCmdLine || !lpCmdLine[0]) ?
  486. FXPLAYER_FILENAME :lpCmdLine;
  487. FxPlayerTiny player(pfilename);
  488. result = player.Run();
  489. }
  490. return result;
  491. }
粤ICP备19079148号