sdlwindow.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. unit sdlwindow;
  2. {
  3. $Id: sdlwindow.pas,v 1.9 2006/10/22 18:55:25 savage Exp $
  4. }
  5. {******************************************************************************}
  6. { }
  7. { JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer }
  8. { SDL Window Wrapper }
  9. { }
  10. { }
  11. { The initial developer of this Pascal code was : }
  12. { Dominique Louis <[email protected]> }
  13. { }
  14. { Portions created by Dominique Louis are }
  15. { Copyright (C) 2004 - 2100 Dominique Louis. }
  16. { }
  17. { }
  18. { Contributor(s) }
  19. { -------------- }
  20. { Dominique Louis <[email protected]> }
  21. { }
  22. { Obtained through: }
  23. { Joint Endeavour of Delphi Innovators ( Project JEDI ) }
  24. { }
  25. { You may retrieve the latest version of this file at the Project }
  26. { JEDI home page, located at http://delphi-jedi.org }
  27. { }
  28. { The contents of this file are used with permission, subject to }
  29. { the Mozilla Public License Version 1.1 (the "License"); you may }
  30. { not use this file except in compliance with the License. You may }
  31. { obtain a copy of the License at }
  32. { http://www.mozilla.org/MPL/MPL-1.1.html }
  33. { }
  34. { Software distributed under the License is distributed on an }
  35. { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
  36. { implied. See the License for the specific language governing }
  37. { rights and limitations under the License. }
  38. { }
  39. { Description }
  40. { ----------- }
  41. { SDL Window Wrapper }
  42. { }
  43. { }
  44. { Requires }
  45. { -------- }
  46. { SDL.dll on Windows platforms }
  47. { libSDL-1.1.so.0 on Linux platform }
  48. { }
  49. { Programming Notes }
  50. { ----------------- }
  51. { }
  52. { }
  53. { }
  54. { }
  55. { Revision History }
  56. { ---------------- }
  57. { January 31 2003 - DL : Initial creation }
  58. { }
  59. {
  60. $Log: sdlwindow.pas,v $
  61. Revision 1.9 2006/10/22 18:55:25 savage
  62. Slight Change to handle OpenGL context
  63. Revision 1.8 2005/08/03 18:57:32 savage
  64. Various updates and additions. Mainly to handle OpenGL 3D Window support and better cursor support for the mouse class
  65. Revision 1.7 2004/09/30 22:35:47 savage
  66. Changes, enhancements and additions as required to get SoAoS working.
  67. Revision 1.6 2004/09/12 21:52:58 savage
  68. Slight changes to fix some issues with the sdl classes.
  69. Revision 1.5 2004/05/10 21:11:49 savage
  70. changes required to help get SoAoS off the ground.
  71. Revision 1.4 2004/05/01 14:59:27 savage
  72. Updated code
  73. Revision 1.3 2004/04/23 10:45:28 savage
  74. Changes made by Dean Ellis to work more modularly.
  75. Revision 1.2 2004/03/31 10:06:41 savage
  76. Changed so that it now compiles, but is untested.
  77. Revision 1.1 2004/02/05 00:08:20 savage
  78. Module 1.0 release
  79. }
  80. {******************************************************************************}
  81. interface
  82. {$i jedi-sdl.inc}
  83. uses
  84. Classes,
  85. sdl,
  86. sdlinput,
  87. sdlticks;
  88. type
  89. TSDLNotifyEvent = procedure {$IFNDEF NOT_OO}of object{$ENDIF};
  90. TSDLUpdateEvent = procedure( aElapsedTime : single ) {$IFNDEF NOT_OO}of object{$ENDIF};
  91. TSDLResizeEvent = procedure( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ) {$IFNDEF NOT_OO}of object{$ENDIF};
  92. TSDLUserEvent = procedure( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer ) {$IFNDEF NOT_OO}of object{$ENDIF};
  93. TSDLActiveEvent = procedure( aGain: UInt8; aState: UInt8 ) {$IFNDEF NOT_OO}of object{$ENDIF};
  94. TSDLBaseWindow = class( TObject )
  95. private
  96. FDisplaySurface : PSDL_Surface;
  97. FVideoFlags : Uint32;
  98. FOnDestroy: TSDLNotifyEvent;
  99. FOnCreate: TSDLNotifyEvent;
  100. FOnShow: TSDLNotifyEvent;
  101. FOnResize: TSDLResizeEvent;
  102. FOnUpdate: TSDLUpdateEvent;
  103. FOnRender: TSDLNotifyEvent;
  104. FOnClose: TSDLNotifyEvent;
  105. FLoaded: Boolean;
  106. FRendering: Boolean;
  107. FHeight: integer;
  108. FBitDepth: integer;
  109. FWidth: integer;
  110. FInputManager: TSDLInputManager;
  111. FCaptionText : PChar;
  112. FIconName : PChar;
  113. FOnActive: TSDLActiveEvent;
  114. FOnQuit: TSDLNotifyEvent;
  115. FOnExpose: TSDLNotifyEvent;
  116. FOnUser: TSDLUserEvent;
  117. FTimer : TSDLTicks;
  118. protected
  119. procedure DoActive( aGain: UInt8; aState: UInt8 );
  120. procedure DoCreate;
  121. procedure DoClose;
  122. procedure DoDestroy;
  123. procedure DoUpdate( aElapsedTime : single );
  124. procedure DoQuit;
  125. procedure DoRender;
  126. procedure DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
  127. procedure DoShow;
  128. procedure DoUser( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer );
  129. procedure DoExpose;
  130. procedure Render; virtual;
  131. procedure Update( aElapsedTime : single ); virtual;
  132. procedure InitialiseObjects; virtual;
  133. procedure RestoreObjects; virtual;
  134. procedure DeleteObjects; virtual;
  135. function Flip : integer; virtual;
  136. property OnActive : TSDLActiveEvent read FOnActive write FOnActive;
  137. property OnClose: TSDLNotifyEvent read FOnClose write FOnClose;
  138. property OnDestroy : TSDLNotifyEvent read FOnDestroy write FOnDestroy;
  139. property OnCreate : TSDLNotifyEvent read FOnCreate write FOnCreate;
  140. property OnUpdate: TSDLUpdateEvent read FOnUpdate write FOnUpdate;
  141. property OnQuit : TSDLNotifyEvent read FOnQuit write FOnQuit;
  142. property OnResize : TSDLResizeEvent read FOnResize write FOnResize;
  143. property OnRender: TSDLNotifyEvent read FOnRender write FOnRender;
  144. property OnShow : TSDLNotifyEvent read FOnShow write FOnShow;
  145. property OnUser : TSDLUserEvent read FOnUser write FOnUser;
  146. property OnExpose : TSDLNotifyEvent read FOnExpose write FOnExpose;
  147. property DisplaySurface: PSDL_Surface read FDisplaySurface;
  148. public
  149. property InputManager : TSDLInputManager read FInputManager;
  150. property Loaded : Boolean read FLoaded;
  151. property Width : integer read FWidth;
  152. property Height : integer read FHeight;
  153. property BitDepth : integer read FBitDepth;
  154. property Rendering : Boolean read FRendering write FRendering;
  155. procedure SetCaption( const aCaptionText : string; const aIconName : string );
  156. procedure GetCaption( var aCaptionText : string; var aIconName : string );
  157. procedure SetIcon( aIcon : PSDL_Surface; aMask: UInt8 );
  158. procedure ActivateVideoMode;
  159. constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ); virtual;
  160. destructor Destroy; override;
  161. procedure InitialiseEnvironment;
  162. function Show : Boolean; virtual;
  163. end;
  164. TSDLCustomWindow = class( TSDLBaseWindow )
  165. public
  166. property OnCreate;
  167. property OnDestroy;
  168. property OnClose;
  169. property OnShow;
  170. property OnResize;
  171. property OnRender;
  172. property OnUpdate;
  173. property DisplaySurface;
  174. end;
  175. TSDL2DWindow = class( TSDLCustomWindow )
  176. public
  177. constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_DOUBLEBUF or SDL_SWSURFACE); override;
  178. procedure Render; override;
  179. procedure Update( aElapsedTime : single ); override;
  180. procedure InitialiseObjects; override;
  181. procedure RestoreObjects; override;
  182. procedure DeleteObjects; override;
  183. function Flip : integer; override;
  184. end;
  185. TSDL3DWindow = class( TSDLCustomWindow )
  186. public
  187. constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_OPENGL or SDL_DOUBLEBUF); override;
  188. function Flip : integer; override;
  189. procedure Render; override;
  190. procedure Update( aElapsedTime : single ); override;
  191. procedure InitialiseObjects; override;
  192. procedure RestoreObjects; override;
  193. procedure DeleteObjects; override;
  194. end;
  195. implementation
  196. uses
  197. logger,
  198. SysUtils;
  199. { TSDLBaseWindow }
  200. procedure TSDLBaseWindow.ActivateVideoMode;
  201. begin
  202. FDisplaySurface := SDL_SetVideoMode( FWidth, FHeight, FBitDepth, FVideoFlags);
  203. if (FDisplaySurface = nil) then
  204. begin
  205. Log.LogError( Format('Could not set video mode: %s', [SDL_GetError]), 'Main');
  206. exit;
  207. end;
  208. SetCaption( 'Made with JEDI-SDL', 'JEDI-SDL Icon' );
  209. end;
  210. constructor TSDLBaseWindow.Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
  211. begin
  212. inherited Create;
  213. SDL_Init(SDL_INIT_EVERYTHING);
  214. FInputManager := TSDLInputManager.Create( [ itJoystick, itKeyBoard, itMouse ]);
  215. FTimer := TSDLTicks.Create;
  216. FWidth := aWidth;
  217. FHeight := aHeight;
  218. FBitDepth := aBitDepth;
  219. FVideoFlags := aVideoFlags;
  220. DoCreate;
  221. end;
  222. procedure TSDLBaseWindow.DeleteObjects;
  223. begin
  224. FLoaded := False;
  225. end;
  226. destructor TSDLBaseWindow.Destroy;
  227. begin
  228. DoDestroy;
  229. if FLoaded then
  230. DeleteObjects;
  231. if FInputManager <> nil then
  232. FreeAndNil( FInputManager );
  233. if FTimer <> nil then
  234. FreeAndNil( FTimer );
  235. if FDisplaySurface <> nil then
  236. SDL_FreeSurface( FDisplaySurface );
  237. inherited Destroy;
  238. SDL_Quit;
  239. end;
  240. procedure TSDLBaseWindow.DoActive(aGain, aState: UInt8);
  241. begin
  242. if Assigned( FOnActive ) then
  243. begin
  244. FOnActive( aGain, aState );
  245. end;
  246. end;
  247. procedure TSDLBaseWindow.DoClose;
  248. begin
  249. if Assigned( FOnClose ) then
  250. begin
  251. FOnClose;
  252. end;
  253. end;
  254. procedure TSDLBaseWindow.DoCreate;
  255. begin
  256. if Assigned( FOnCreate ) then
  257. begin
  258. FOnCreate;
  259. end;
  260. end;
  261. procedure TSDLBaseWindow.DoDestroy;
  262. begin
  263. if Assigned( FOnDestroy ) then
  264. begin
  265. FOnDestroy;
  266. end;
  267. end;
  268. procedure TSDLBaseWindow.DoExpose;
  269. begin
  270. if Assigned( FOnExpose ) then
  271. begin
  272. FOnExpose;
  273. end;
  274. end;
  275. procedure TSDLBaseWindow.DoUpdate( aElapsedTime : single );
  276. begin
  277. if Assigned( FOnUpdate ) then
  278. begin
  279. FOnUpdate( aElapsedTime );
  280. end;
  281. end;
  282. procedure TSDLBaseWindow.DoQuit;
  283. begin
  284. FRendering := false;
  285. if Assigned( FOnQuit ) then
  286. begin
  287. FOnQuit;
  288. end;
  289. end;
  290. procedure TSDLBaseWindow.DoRender;
  291. begin
  292. if Assigned( FOnRender ) then
  293. begin
  294. FOnRender;
  295. end;
  296. end;
  297. procedure TSDLBaseWindow.DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
  298. begin
  299. // resize to the new size
  300. SDL_FreeSurface(FDisplaySurface);
  301. FWidth := aWidth;
  302. FHeight := aHeight;
  303. FBitDepth := aBitDepth;
  304. FVideoFlags := aVideoFlags;
  305. FDisplaySurface := SDL_SetVideoMode(aWidth, aHeight, aBitDepth, aVideoFlags);
  306. if Assigned( FOnResize ) then
  307. begin
  308. FOnResize( aWidth, aHeight, aBitDepth, aVideoFlags );
  309. end;
  310. end;
  311. procedure TSDLBaseWindow.DoShow;
  312. begin
  313. if Assigned( FOnShow ) then
  314. begin
  315. FOnShow;
  316. end;
  317. end;
  318. procedure TSDLBaseWindow.DoUser(aType: UInt8; aCode: integer; aData1, aData2: Pointer);
  319. begin
  320. if Assigned( FOnUser ) then
  321. begin
  322. FOnUser( aType, aCode, aData1, aData2 );
  323. end;
  324. end;
  325. function TSDLBaseWindow.Flip : integer;
  326. begin
  327. result := 0;
  328. end;
  329. procedure TSDLBaseWindow.GetCaption( var aCaptionText : string; var aIconName : string );
  330. begin
  331. aCaptionText := string( FCaptionText );
  332. aIconName := string( FIconName );
  333. end;
  334. procedure TSDLBaseWindow.InitialiseEnvironment;
  335. begin
  336. InitialiseObjects;
  337. RestoreObjects;
  338. end;
  339. procedure TSDLBaseWindow.InitialiseObjects;
  340. begin
  341. FLoaded := True;
  342. end;
  343. procedure TSDLBaseWindow.Update( aElapsedTime : single );
  344. begin
  345. DoUpdate( aElapsedTime );
  346. end;
  347. procedure TSDLBaseWindow.Render;
  348. begin
  349. DoRender;
  350. end;
  351. procedure TSDLBaseWindow.RestoreObjects;
  352. begin
  353. FLoaded := false;
  354. end;
  355. procedure TSDLBaseWindow.SetCaption( const aCaptionText : string; const aIconName : string );
  356. begin
  357. if FCaptionText <> aCaptionText then
  358. begin
  359. FCaptionText := PChar( aCaptionText );
  360. FIconName := PChar( aIconName );
  361. SDL_WM_SetCaption( FCaptionText, FIconName );
  362. end;
  363. end;
  364. procedure TSDLBaseWindow.SetIcon(aIcon: PSDL_Surface; aMask: UInt8);
  365. begin
  366. SDL_WM_SetIcon( aIcon, aMask );
  367. end;
  368. function TSDLBaseWindow.Show : Boolean;
  369. var
  370. eBaseWindowEvent : TSDL_Event;
  371. begin
  372. DoShow;
  373. FTimer.Init;
  374. FRendering := true;
  375. // repeat until we are told not to render
  376. while FRendering do
  377. begin
  378. // wait for an event
  379. while SDL_PollEvent( @eBaseWindowEvent ) > 0 do
  380. begin
  381. // check for a quit event
  382. case eBaseWindowEvent.type_ of
  383. SDL_ACTIVEEVENT :
  384. begin
  385. DoActive( eBaseWindowEvent.active.gain, eBaseWindowEvent.active.state );
  386. end;
  387. SDL_QUITEV :
  388. begin
  389. DoQuit;
  390. DoClose;
  391. end;
  392. SDL_USEREVENT :
  393. begin
  394. DoUser( eBaseWindowEvent.user.type_, eBaseWindowEvent.user.code, eBaseWindowEvent.user.data1, eBaseWindowEvent.user.data2 );
  395. end;
  396. SDL_VIDEOEXPOSE :
  397. begin
  398. DoExpose;
  399. end;
  400. SDL_VIDEORESIZE :
  401. begin
  402. DoResize( eBaseWindowEvent.resize.w, eBaseWindowEvent.resize.h, FDisplaySurface.format.BitsPerPixel, FVideoflags );
  403. end;
  404. end;
  405. InputManager.UpdateInputs( eBaseWindowEvent );
  406. end;
  407. // Prepare the Next Frame
  408. Update( FTimer.GetElapsedSeconds );
  409. // Display the Next Frame
  410. Render;
  411. // Flip the surfaces
  412. Flip;
  413. end;
  414. Result := FRendering;
  415. end;
  416. { TSDL2DWindow }
  417. constructor TSDL2DWindow.Create(aWidth, aHeight, aBitDepth: integer; aVideoFlags: Uint32);
  418. begin
  419. // make sure double buffer is always included in the video flags
  420. inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_DOUBLEBUF);
  421. end;
  422. procedure TSDL2DWindow.DeleteObjects;
  423. begin
  424. inherited;
  425. end;
  426. function TSDL2DWindow.Flip: integer;
  427. begin
  428. // let's show the back buffer
  429. result := SDL_Flip( FDisplaySurface );
  430. end;
  431. procedure TSDL2DWindow.InitialiseObjects;
  432. begin
  433. inherited;
  434. end;
  435. procedure TSDL2DWindow.Update( aElapsedTime : single );
  436. begin
  437. inherited;
  438. end;
  439. procedure TSDL2DWindow.Render;
  440. begin
  441. inherited;
  442. end;
  443. procedure TSDL2DWindow.RestoreObjects;
  444. begin
  445. inherited;
  446. end;
  447. { TSDL3DWindow }
  448. constructor TSDL3DWindow.Create(aWidth,
  449. aHeight, aBitDepth: integer; aVideoFlags: Uint32);
  450. begin
  451. // make sure opengl is always included in the video flags
  452. inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_OPENGL or SDL_DOUBLEBUF);
  453. end;
  454. procedure TSDL3DWindow.DeleteObjects;
  455. begin
  456. inherited;
  457. end;
  458. function TSDL3DWindow.Flip : integer;
  459. begin
  460. SDL_GL_SwapBuffers;
  461. result := 0;
  462. end;
  463. procedure TSDL3DWindow.InitialiseObjects;
  464. begin
  465. inherited;
  466. end;
  467. procedure TSDL3DWindow.Update( aElapsedTime : single );
  468. begin
  469. inherited;
  470. end;
  471. procedure TSDL3DWindow.Render;
  472. begin
  473. inherited;
  474. end;
  475. procedure TSDL3DWindow.RestoreObjects;
  476. begin
  477. inherited;
  478. end;
  479. end.