unit sdlwindow;
{
$Id: sdlwindow.pas,v 1.9 2006/10/22 18:55:25 savage Exp $
}
{******************************************************************************}
{ }
{ JEDI-SDL : Pascal units for SDL - Simple DirectMedia Layer }
{ SDL Window Wrapper }
{ }
{ }
{ The initial developer of this Pascal code was : }
{ Dominique Louis <Dominique@SavageSoftware.com.au> }
{ }
{ Portions created by Dominique Louis are }
{ Copyright (C) 2004 - 2100 Dominique Louis. }
{ }
{ }
{ Contributor(s) }
{ -------------- }
{ Dominique Louis <Dominique@SavageSoftware.com.au> }
{ }
{ Obtained through: }
{ Joint Endeavour of Delphi Innovators ( Project JEDI ) }
{ }
{ You may retrieve the latest version of this file at the Project }
{ JEDI home page, located at http://delphi-jedi.org }
{ }
{ The contents of this file are used with permission, subject to }
{ the Mozilla Public License Version 1.1 (the "License"); you may }
{ not use this file except in compliance with the License. You may }
{ obtain a copy of the License at }
{ http://www.mozilla.org/MPL/MPL-1.1.html }
{ }
{ Software distributed under the License is distributed on an }
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
{ implied. See the License for the specific language governing }
{ rights and limitations under the License. }
{ }
{ Description }
{ ----------- }
{ SDL Window Wrapper }
{ }
{ }
{ Requires }
{ -------- }
{ SDL.dll on Windows platforms }
{ libSDL-1.1.so.0 on Linux platform }
{ }
{ Programming Notes }
{ ----------------- }
{ }
{ }
{ }
{ }
{ Revision History }
{ ---------------- }
{ January 31 2003 - DL : Initial creation }
{ }
{
$Log: sdlwindow.pas,v $
Revision 1.9 2006/10/22 18:55:25 savage
Slight Change to handle OpenGL context
Revision 1.8 2005/08/03 18:57:32 savage
Various updates and additions. Mainly to handle OpenGL 3D Window support and better cursor support for the mouse class
Revision 1.7 2004/09/30 22:35:47 savage
Changes, enhancements and additions as required to get SoAoS working.
Revision 1.6 2004/09/12 21:52:58 savage
Slight changes to fix some issues with the sdl classes.
Revision 1.5 2004/05/10 21:11:49 savage
changes required to help get SoAoS off the ground.
Revision 1.4 2004/05/01 14:59:27 savage
Updated code
Revision 1.3 2004/04/23 10:45:28 savage
Changes made by Dean Ellis to work more modularly.
Revision 1.2 2004/03/31 10:06:41 savage
Changed so that it now compiles, but is untested.
Revision 1.1 2004/02/05 00:08:20 savage
Module 1.0 release
}
{******************************************************************************}
interface
{$i jedi-sdl.inc}
uses
Classes,
sdl,
sdlinput,
sdlticks;
type
TSDLNotifyEvent = procedure {$IFNDEF NOT_OO}of object{$ENDIF};
TSDLUpdateEvent = procedure( aElapsedTime : single ) {$IFNDEF NOT_OO}of object{$ENDIF};
TSDLResizeEvent = procedure( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ) {$IFNDEF NOT_OO}of object{$ENDIF};
TSDLUserEvent = procedure( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer ) {$IFNDEF NOT_OO}of object{$ENDIF};
TSDLActiveEvent = procedure( aGain: UInt8; aState: UInt8 ) {$IFNDEF NOT_OO}of object{$ENDIF};
TSDLBaseWindow = class( TObject )
private
FDisplaySurface : PSDL_Surface;
FVideoFlags : Uint32;
FOnDestroy: TSDLNotifyEvent;
FOnCreate: TSDLNotifyEvent;
FOnShow: TSDLNotifyEvent;
FOnResize: TSDLResizeEvent;
FOnUpdate: TSDLUpdateEvent;
FOnRender: TSDLNotifyEvent;
FOnClose: TSDLNotifyEvent;
FLoaded: Boolean;
FRendering: Boolean;
FHeight: integer;
FBitDepth: integer;
FWidth: integer;
FInputManager: TSDLInputManager;
FCaptionText : PChar;
FIconName : PChar;
FOnActive: TSDLActiveEvent;
FOnQuit: TSDLNotifyEvent;
FOnExpose: TSDLNotifyEvent;
FOnUser: TSDLUserEvent;
FTimer : TSDLTicks;
protected
procedure DoActive( aGain: UInt8; aState: UInt8 );
procedure DoCreate;
procedure DoClose;
procedure DoDestroy;
procedure DoUpdate( aElapsedTime : single );
procedure DoQuit;
procedure DoRender;
procedure DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
procedure DoShow;
procedure DoUser( aType : UInt8; aCode : integer; aData1 : Pointer; aData2 : Pointer );
procedure DoExpose;
procedure Render; virtual;
procedure Update( aElapsedTime : single ); virtual;
procedure InitialiseObjects; virtual;
procedure RestoreObjects; virtual;
procedure DeleteObjects; virtual;
function Flip : integer; virtual;
property OnActive : TSDLActiveEvent read FOnActive write FOnActive;
property OnClose: TSDLNotifyEvent read FOnClose write FOnClose;
property OnDestroy : TSDLNotifyEvent read FOnDestroy write FOnDestroy;
property OnCreate : TSDLNotifyEvent read FOnCreate write FOnCreate;
property OnUpdate: TSDLUpdateEvent read FOnUpdate write FOnUpdate;
property OnQuit : TSDLNotifyEvent read FOnQuit write FOnQuit;
property OnResize : TSDLResizeEvent read FOnResize write FOnResize;
property OnRender: TSDLNotifyEvent read FOnRender write FOnRender;
property OnShow : TSDLNotifyEvent read FOnShow write FOnShow;
property OnUser : TSDLUserEvent read FOnUser write FOnUser;
property OnExpose : TSDLNotifyEvent read FOnExpose write FOnExpose;
property DisplaySurface: PSDL_Surface read FDisplaySurface;
public
property InputManager : TSDLInputManager read FInputManager;
property Loaded : Boolean read FLoaded;
property Width : integer read FWidth;
property Height : integer read FHeight;
property BitDepth : integer read FBitDepth;
property Rendering : Boolean read FRendering write FRendering;
procedure SetCaption( const aCaptionText : string; const aIconName : string );
procedure GetCaption( var aCaptionText : string; var aIconName : string );
procedure SetIcon( aIcon : PSDL_Surface; aMask: UInt8 );
procedure ActivateVideoMode;
constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 ); virtual;
destructor Destroy; override;
procedure InitialiseEnvironment;
function Show : Boolean; virtual;
end;
TSDLCustomWindow = class( TSDLBaseWindow )
public
property OnCreate;
property OnDestroy;
property OnClose;
property OnShow;
property OnResize;
property OnRender;
property OnUpdate;
property DisplaySurface;
end;
TSDL2DWindow = class( TSDLCustomWindow )
public
constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_DOUBLEBUF or SDL_SWSURFACE); override;
procedure Render; override;
procedure Update( aElapsedTime : single ); override;
procedure InitialiseObjects; override;
procedure RestoreObjects; override;
procedure DeleteObjects; override;
function Flip : integer; override;
end;
TSDL3DWindow = class( TSDLCustomWindow )
public
constructor Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 = SDL_OPENGL or SDL_DOUBLEBUF); override;
function Flip : integer; override;
procedure Render; override;
procedure Update( aElapsedTime : single ); override;
procedure InitialiseObjects; override;
procedure RestoreObjects; override;
procedure DeleteObjects; override;
end;
implementation
uses
logger,
SysUtils;
{ TSDLBaseWindow }
procedure TSDLBaseWindow.ActivateVideoMode;
begin
FDisplaySurface := SDL_SetVideoMode( FWidth, FHeight, FBitDepth, FVideoFlags);
if (FDisplaySurface = nil) then
begin
Log.LogError( Format('Could not set video mode: %s', [SDL_GetError]), 'Main');
exit;
end;
SetCaption( 'Made with JEDI-SDL', 'JEDI-SDL Icon' );
end;
constructor TSDLBaseWindow.Create( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
begin
inherited Create;
SDL_Init(SDL_INIT_EVERYTHING);
FInputManager := TSDLInputManager.Create( [ itJoystick, itKeyBoard, itMouse ]);
FTimer := TSDLTicks.Create;
FWidth := aWidth;
FHeight := aHeight;
FBitDepth := aBitDepth;
FVideoFlags := aVideoFlags;
DoCreate;
end;
procedure TSDLBaseWindow.DeleteObjects;
begin
FLoaded := False;
end;
destructor TSDLBaseWindow.Destroy;
begin
DoDestroy;
if FLoaded then
DeleteObjects;
if FInputManager <> nil then
FreeAndNil( FInputManager );
if FTimer <> nil then
FreeAndNil( FTimer );
if FDisplaySurface <> nil then
SDL_FreeSurface( FDisplaySurface );
inherited Destroy;
SDL_Quit;
end;
procedure TSDLBaseWindow.DoActive(aGain, aState: UInt8);
begin
if Assigned( FOnActive ) then
begin
FOnActive( aGain, aState );
end;
end;
procedure TSDLBaseWindow.DoClose;
begin
if Assigned( FOnClose ) then
begin
FOnClose;
end;
end;
procedure TSDLBaseWindow.DoCreate;
begin
if Assigned( FOnCreate ) then
begin
FOnCreate;
end;
end;
procedure TSDLBaseWindow.DoDestroy;
begin
if Assigned( FOnDestroy ) then
begin
FOnDestroy;
end;
end;
procedure TSDLBaseWindow.DoExpose;
begin
if Assigned( FOnExpose ) then
begin
FOnExpose;
end;
end;
procedure TSDLBaseWindow.DoUpdate( aElapsedTime : single );
begin
if Assigned( FOnUpdate ) then
begin
FOnUpdate( aElapsedTime );
end;
end;
procedure TSDLBaseWindow.DoQuit;
begin
FRendering := false;
if Assigned( FOnQuit ) then
begin
FOnQuit;
end;
end;
procedure TSDLBaseWindow.DoRender;
begin
if Assigned( FOnRender ) then
begin
FOnRender;
end;
end;
procedure TSDLBaseWindow.DoResize( aWidth : integer; aHeight : integer; aBitDepth : integer; aVideoFlags : Uint32 );
begin
// resize to the new size
SDL_FreeSurface(FDisplaySurface);
FWidth := aWidth;
FHeight := aHeight;
FBitDepth := aBitDepth;
FVideoFlags := aVideoFlags;
FDisplaySurface := SDL_SetVideoMode(aWidth, aHeight, aBitDepth, aVideoFlags);
if Assigned( FOnResize ) then
begin
FOnResize( aWidth, aHeight, aBitDepth, aVideoFlags );
end;
end;
procedure TSDLBaseWindow.DoShow;
begin
if Assigned( FOnShow ) then
begin
FOnShow;
end;
end;
procedure TSDLBaseWindow.DoUser(aType: UInt8; aCode: integer; aData1, aData2: Pointer);
begin
if Assigned( FOnUser ) then
begin
FOnUser( aType, aCode, aData1, aData2 );
end;
end;
function TSDLBaseWindow.Flip : integer;
begin
result := 0;
end;
procedure TSDLBaseWindow.GetCaption( var aCaptionText : string; var aIconName : string );
begin
aCaptionText := string( FCaptionText );
aIconName := string( FIconName );
end;
procedure TSDLBaseWindow.InitialiseEnvironment;
begin
InitialiseObjects;
RestoreObjects;
end;
procedure TSDLBaseWindow.InitialiseObjects;
begin
FLoaded := True;
end;
procedure TSDLBaseWindow.Update( aElapsedTime : single );
begin
DoUpdate( aElapsedTime );
end;
procedure TSDLBaseWindow.Render;
begin
DoRender;
end;
procedure TSDLBaseWindow.RestoreObjects;
begin
FLoaded := false;
end;
procedure TSDLBaseWindow.SetCaption( const aCaptionText : string; const aIconName : string );
begin
if FCaptionText <> aCaptionText then
begin
FCaptionText := PChar( aCaptionText );
FIconName := PChar( aIconName );
SDL_WM_SetCaption( FCaptionText, FIconName );
end;
end;
procedure TSDLBaseWindow.SetIcon(aIcon: PSDL_Surface; aMask: UInt8);
begin
SDL_WM_SetIcon( aIcon, aMask );
end;
function TSDLBaseWindow.Show : Boolean;
var
eBaseWindowEvent : TSDL_Event;
begin
DoShow;
FTimer.Init;
FRendering := true;
// repeat until we are told not to render
while FRendering do
begin
// wait for an event
while SDL_PollEvent( @eBaseWindowEvent ) > 0 do
begin
// check for a quit event
case eBaseWindowEvent.type_ of
SDL_ACTIVEEVENT :
begin
DoActive( eBaseWindowEvent.active.gain, eBaseWindowEvent.active.state );
end;
SDL_QUITEV :
begin
DoQuit;
DoClose;
end;
SDL_USEREVENT :
begin
DoUser( eBaseWindowEvent.user.type_, eBaseWindowEvent.user.code, eBaseWindowEvent.user.data1, eBaseWindowEvent.user.data2 );
end;
SDL_VIDEOEXPOSE :
begin
DoExpose;
end;
SDL_VIDEORESIZE :
begin
DoResize( eBaseWindowEvent.resize.w, eBaseWindowEvent.resize.h, FDisplaySurface.format.BitsPerPixel, FVideoflags );
end;
end;
InputManager.UpdateInputs( eBaseWindowEvent );
end;
// Prepare the Next Frame
Update( FTimer.GetElapsedSeconds );
// Display the Next Frame
Render;
// Flip the surfaces
Flip;
end;
Result := FRendering;
end;
{ TSDL2DWindow }
constructor TSDL2DWindow.Create(aWidth, aHeight, aBitDepth: integer; aVideoFlags: Uint32);
begin
// make sure double buffer is always included in the video flags
inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_DOUBLEBUF);
end;
procedure TSDL2DWindow.DeleteObjects;
begin
inherited;
end;
function TSDL2DWindow.Flip: integer;
begin
// let's show the back buffer
result := SDL_Flip( FDisplaySurface );
end;
procedure TSDL2DWindow.InitialiseObjects;
begin
inherited;
end;
procedure TSDL2DWindow.Update( aElapsedTime : single );
begin
inherited;
end;
procedure TSDL2DWindow.Render;
begin
inherited;
end;
procedure TSDL2DWindow.RestoreObjects;
begin
inherited;
end;
{ TSDL3DWindow }
constructor TSDL3DWindow.Create(aWidth,
aHeight, aBitDepth: integer; aVideoFlags: Uint32);
begin
// make sure opengl is always included in the video flags
inherited Create(aWidth,aHeight, aBitDepth, aVideoFlags or SDL_OPENGL or SDL_DOUBLEBUF);
end;
procedure TSDL3DWindow.DeleteObjects;
begin
inherited;
end;
function TSDL3DWindow.Flip : integer;
begin
SDL_GL_SwapBuffers;
result := 0;
end;
procedure TSDL3DWindow.InitialiseObjects;
begin
inherited;
end;
procedure TSDL3DWindow.Update( aElapsedTime : single );
begin
inherited;
end;
procedure TSDL3DWindow.Render;
begin
inherited;
end;
procedure TSDL3DWindow.RestoreObjects;
begin
inherited;
end;
end.