2018-12-08 09:32:09 -05:00
/ * OpenDiablo 2 - An open source re - implementation of Diablo 2 in C #
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
* /
using System ;
2018-11-22 00:18:42 -05:00
using System.Drawing ;
2018-11-28 19:28:41 -05:00
using System.Linq ;
2018-11-23 20:51:32 -05:00
using System.Runtime.InteropServices ;
2018-11-28 19:28:41 -05:00
using OpenDiablo2.Common.Interfaces ;
2018-12-07 18:45:54 -05:00
using OpenDiablo2.Common.Interfaces.Drawing ;
2018-11-28 19:28:41 -05:00
using OpenDiablo2.Common.Models ;
using SDL2 ;
2018-11-22 00:18:42 -05:00
namespace OpenDiablo2.SDL2_
{
2018-11-29 17:58:56 -05:00
public sealed class SDL2RenderWindow : IRenderWindow , IMouseInfoProvider , IKeyboardInfoProvider
2018-11-22 00:18:42 -05:00
{
private static readonly log4net . ILog log = log4net . LogManager . GetLogger ( System . Reflection . MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2018-11-22 14:30:37 -05:00
2018-12-08 09:32:09 -05:00
private readonly IntPtr window , renderer ;
private readonly bool fullscreen ;
2018-11-29 18:20:38 -05:00
2018-11-22 18:46:24 -05:00
public bool IsRunning { get ; private set ; }
2018-11-22 00:56:36 -05:00
public int MouseX { get ; internal set ; } = 0 ;
public int MouseY { get ; internal set ; } = 0 ;
public bool LeftMouseDown { get ; internal set ; } = false ;
2018-12-02 16:34:00 -05:00
public bool LeftMousePressed { get ; internal set ; } = false ;
2018-11-22 00:56:36 -05:00
public bool RightMouseDown { get ; internal set ; } = false ;
2018-11-22 18:46:24 -05:00
public bool ReserveMouse { get ; set ; } = false ;
2018-11-22 00:56:36 -05:00
2018-11-23 20:51:32 -05:00
public OnKeyPressed KeyPressCallback { get ; set ; }
2018-11-29 23:26:51 -05:00
private IMouseCursor mouseCursor = null ;
public IMouseCursor MouseCursor
{
get = > mouseCursor ;
set
{
if ( mouseCursor = = value )
return ;
SetCursor ( value ) ;
}
}
2018-11-22 14:30:37 -05:00
private readonly IMPQProvider mpqProvider ;
private readonly IPaletteProvider paletteProvider ;
2018-11-22 22:53:05 -05:00
private readonly IResourceManager resourceManager ;
2018-11-27 20:02:18 -05:00
private readonly GlobalConfiguration globalConfig ;
2018-11-28 19:28:41 -05:00
private readonly Func < IGameState > getGameState ;
2018-11-27 00:56:54 -05:00
private readonly Func < IMapEngine > getMapEngine ;
2018-11-22 00:18:42 -05:00
2018-11-22 14:30:37 -05:00
public SDL2RenderWindow (
2018-11-27 20:02:18 -05:00
GlobalConfiguration globalConfig ,
2018-11-22 14:30:37 -05:00
IMPQProvider mpqProvider ,
2018-11-22 22:53:05 -05:00
IPaletteProvider paletteProvider ,
2018-11-25 14:15:13 -05:00
IResourceManager resourceManager ,
2018-11-28 19:28:41 -05:00
Func < IGameState > getGameState ,
2018-11-27 00:56:54 -05:00
Func < IMapEngine > getMapEngine
2018-11-22 14:30:37 -05:00
)
2018-11-22 00:18:42 -05:00
{
2018-11-27 20:02:18 -05:00
this . globalConfig = globalConfig ;
2018-11-22 14:30:37 -05:00
this . mpqProvider = mpqProvider ;
this . paletteProvider = paletteProvider ;
2018-11-22 22:53:05 -05:00
this . resourceManager = resourceManager ;
2018-11-28 19:28:41 -05:00
this . getGameState = getGameState ;
2018-11-27 00:56:54 -05:00
this . getMapEngine = getMapEngine ;
2018-11-29 18:20:38 -05:00
this . fullscreen = globalConfig . FullScreen ;
2018-11-22 00:18:42 -05:00
SDL . SDL_Init ( SDL . SDL_INIT_EVERYTHING ) ;
if ( SDL . SDL_SetHint ( SDL . SDL_HINT_RENDER_SCALE_QUALITY , "0" ) = = SDL . SDL_bool . SDL_FALSE )
throw new ApplicationException ( $"Unable to Init hinting: {SDL.SDL_GetError()}" ) ;
2018-11-29 18:20:38 -05:00
window = SDL . SDL_CreateWindow ( "OpenDiablo2" , SDL . SDL_WINDOWPOS_UNDEFINED , SDL . SDL_WINDOWPOS_UNDEFINED , 800 , 600 ,
SDL . SDL_WindowFlags . SDL_WINDOW_SHOWN | ( fullscreen ? SDL . SDL_WindowFlags . SDL_WINDOW_FULLSCREEN : 0 ) ) ;
2018-11-22 00:18:42 -05:00
if ( window = = IntPtr . Zero )
throw new ApplicationException ( $"Unable to create SDL Window: {SDL.SDL_GetError()}" ) ;
2018-11-29 17:58:56 -05:00
renderer = SDL . SDL_CreateRenderer ( window , - 1 , SDL . SDL_RendererFlags . SDL_RENDERER_ACCELERATED | SDL . SDL_RendererFlags . SDL_RENDERER_PRESENTVSYNC ) ;
2018-11-22 00:18:42 -05:00
if ( renderer = = IntPtr . Zero )
throw new ApplicationException ( $"Unable to create SDL Window: {SDL.SDL_GetError()}" ) ;
2018-11-23 20:51:32 -05:00
SDL . SDL_SetRenderDrawBlendMode ( renderer , SDL . SDL_BlendMode . SDL_BLENDMODE_BLEND ) ;
2018-11-28 19:28:41 -05:00
SDL . SDL_GL_SetSwapInterval ( 1 ) ;
2018-11-27 20:02:18 -05:00
SDL . SDL_ShowCursor ( globalConfig . MouseMode = = eMouseMode . Hardware ? 1 : 0 ) ;
2018-11-22 00:56:36 -05:00
2018-11-22 18:46:24 -05:00
IsRunning = true ;
2018-11-22 00:18:42 -05:00
}
2018-11-22 18:46:24 -05:00
public void Quit ( ) = > IsRunning = false ;
2018-11-22 00:18:42 -05:00
public void Dispose ( )
{
SDL . SDL_DestroyRenderer ( renderer ) ;
SDL . SDL_DestroyWindow ( window ) ;
SDL . SDL_Quit ( ) ;
}
2018-11-23 20:51:32 -05:00
public unsafe bool KeyIsPressed ( int scancode )
{
2018-12-08 09:32:09 -05:00
byte * keys = ( byte * ) SDL . SDL_GetKeyboardState ( out int numKeys ) ;
2018-11-23 20:51:32 -05:00
return keys [ scancode ] > 0 ;
}
2018-11-22 00:18:42 -05:00
public void Clear ( )
{
2018-11-23 15:22:35 -05:00
SDL . SDL_SetRenderTarget ( renderer , IntPtr . Zero ) ;
SDL . SDL_SetRenderDrawColor ( renderer , 0 , 0 , 0 , 255 ) ;
2018-11-22 00:18:42 -05:00
SDL . SDL_RenderClear ( renderer ) ;
}
2018-11-29 23:26:51 -05:00
public unsafe void Sync ( )
2018-11-22 00:18:42 -05:00
{
2018-11-29 23:26:51 -05:00
if ( globalConfig . MouseMode = = eMouseMode . Software )
{
var cursor = mouseCursor as SDL2MouseCursor ;
var texture = cursor . SWTexture ;
var srcRect = new SDL . SDL_Rect
{
x = 0 ,
y = 0 ,
w = cursor . ImageSize . Width ,
h = cursor . ImageSize . Height
} ;
var destRect = new SDL . SDL_Rect
{
x = MouseX - cursor . Hotspot . X ,
y = MouseY - cursor . Hotspot . Y ,
w = cursor . ImageSize . Width ,
h = cursor . ImageSize . Height
} ;
SDL . SDL_RenderCopy ( renderer , texture , ref srcRect , ref destRect ) ;
}
2018-11-22 00:18:42 -05:00
SDL . SDL_RenderPresent ( renderer ) ;
}
2018-11-23 20:51:32 -05:00
public unsafe void Update ( )
2018-11-22 00:18:42 -05:00
{
2018-12-02 16:34:00 -05:00
LeftMousePressed = false ;
2018-11-22 00:18:42 -05:00
while ( SDL . SDL_PollEvent ( out SDL . SDL_Event evt ) ! = 0 )
{
2018-11-22 00:56:36 -05:00
if ( evt . type = = SDL . SDL_EventType . SDL_MOUSEMOTION )
{
MouseX = evt . motion . x ;
MouseY = evt . motion . y ;
continue ;
}
2018-11-22 18:46:24 -05:00
else if ( evt . type = = SDL . SDL_EventType . SDL_MOUSEBUTTONDOWN )
{
2018-11-24 23:49:56 -05:00
switch ( ( uint ) evt . button . button )
2018-11-22 18:46:24 -05:00
{
case SDL . SDL_BUTTON_LEFT :
2018-12-02 16:34:00 -05:00
LeftMousePressed = true ; // Cannot find a better to handle a single press
2018-11-22 18:46:24 -05:00
LeftMouseDown = true ;
break ;
case SDL . SDL_BUTTON_RIGHT :
RightMouseDown = true ;
break ;
}
}
else if ( evt . type = = SDL . SDL_EventType . SDL_MOUSEBUTTONUP )
{
switch ( ( uint ) evt . button . button )
{
case SDL . SDL_BUTTON_LEFT :
LeftMouseDown = false ;
break ;
case SDL . SDL_BUTTON_RIGHT :
RightMouseDown = false ;
break ;
}
}
2018-11-23 20:51:32 -05:00
else if ( evt . type = = SDL . SDL_EventType . SDL_KEYDOWN )
{
2018-11-29 18:20:38 -05:00
/ * NOTE : This absolutely trashes rendering for some reason . . .
if ( evt . key . keysym . mod . HasFlag ( SDL . SDL_Keymod . KMOD_RALT ) & & evt . key . keysym . scancode . HasFlag ( SDL . SDL_Scancode . SDL_SCANCODE_RETURN ) )
{
fullscreen = ! fullscreen ;
SDL . SDL_SetWindowFullscreen ( window , ( uint ) ( fullscreen ? SDL . SDL_WindowFlags . SDL_WINDOW_FULLSCREEN : 0 ) ) ;
}
2018-11-29 23:26:51 -05:00
else * /
if ( evt . key . keysym . sym = = SDL . SDL_Keycode . SDLK_BACKSPACE & & KeyPressCallback ! = null )
2018-11-23 20:51:32 -05:00
KeyPressCallback ( '\b' ) ;
}
else if ( evt . type = = SDL . SDL_EventType . SDL_TEXTINPUT )
{
KeyPressCallback ? . Invoke ( Marshal . PtrToStringAnsi ( ( IntPtr ) evt . text . text ) [ 0 ] ) ;
continue ;
}
2018-11-22 18:46:24 -05:00
else if ( evt . type = = SDL . SDL_EventType . SDL_QUIT )
2018-11-22 00:56:36 -05:00
{
2018-11-22 18:46:24 -05:00
IsRunning = false ;
2018-11-22 00:56:36 -05:00
continue ;
}
2018-11-22 00:18:42 -05:00
}
}
2018-11-22 16:22:39 -05:00
public void Draw ( ISprite sprite , Point location )
{
sprite . Location = location ;
Draw ( sprite ) ;
}
2018-11-22 00:18:42 -05:00
2018-11-23 21:56:30 -05:00
public void Draw ( ISprite sprite , int frame , Point location )
{
sprite . Location = location ;
sprite . Frame = frame ;
Draw ( sprite ) ;
}
2018-11-22 14:30:37 -05:00
public void Draw ( ISprite sprite , int frame )
{
sprite . Frame = frame ;
Draw ( sprite ) ;
}
2018-11-22 00:18:42 -05:00
public void Draw ( ISprite sprite )
{
var spr = sprite as SDL2Sprite ;
2018-11-24 17:54:15 -05:00
if ( spr . texture = = IntPtr . Zero )
return ;
2018-11-22 00:18:42 -05:00
var loc = spr . GetRenderPoint ( ) ;
var destRect = new SDL . SDL_Rect
{
x = loc . X ,
y = loc . Y ,
w = spr . FrameSize . Width ,
h = spr . FrameSize . Height
} ;
2018-11-23 15:22:35 -05:00
SDL . SDL_RenderCopy ( renderer , spr . texture , IntPtr . Zero , ref destRect ) ;
2018-11-22 00:18:42 -05:00
}
2018-11-22 12:35:21 -05:00
public void Draw ( ISprite sprite , int xSegments , int ySegments , int offset )
{
var spr = sprite as SDL2Sprite ;
var segSize = xSegments * ySegments ;
for ( var y = 0 ; y < ySegments ; y + + )
{
for ( var x = 0 ; x < xSegments ; x + + )
{
var textureIndex = x + ( y * xSegments ) + ( offset * xSegments * ySegments ) ;
2018-11-23 15:22:35 -05:00
spr . Frame = Math . Min ( spr . TotalFrames - 1 , Math . Max ( 0 , textureIndex ) ) ;
2018-11-22 12:35:21 -05:00
var destRect = new SDL . SDL_Rect
{
x = sprite . Location . X + ( x * 256 ) ,
y = sprite . Location . Y + ( y * 256 ) - ( int ) ( spr . FrameSize . Height - spr . source . Frames [ textureIndex ] . Height ) ,
w = spr . FrameSize . Width ,
h = spr . FrameSize . Height
} ;
2018-11-23 15:22:35 -05:00
SDL . SDL_RenderCopy ( renderer , spr . texture , IntPtr . Zero , ref destRect ) ;
2018-11-22 12:35:21 -05:00
}
}
}
2018-11-22 14:30:37 -05:00
public ISprite LoadSprite ( string resourcePath , string palette ) = > LoadSprite ( resourcePath , palette , Point . Empty ) ;
public ISprite LoadSprite ( string resourcePath , string palette , Point location )
{
2018-11-22 22:53:05 -05:00
var result = new SDL2Sprite ( resourceManager . GetImageSet ( resourcePath ) , renderer )
2018-11-22 16:22:39 -05:00
{
CurrentPalette = paletteProvider . PaletteTable [ palette ] ,
Location = location
} ;
return result ;
}
public IFont LoadFont ( string resourcePath , string palette )
{
2018-11-22 22:53:05 -05:00
var result = new SDL2Font ( resourceManager . GetMPQFont ( resourcePath ) , renderer )
2018-11-22 16:22:39 -05:00
{
CurrentPalette = paletteProvider . PaletteTable [ palette ]
} ;
return result ;
}
public ILabel CreateLabel ( IFont font )
{
var result = new SDL2Label ( font , renderer ) ;
return result ;
}
public ILabel CreateLabel ( IFont font , string text )
{
var result = CreateLabel ( font ) ;
result . Text = text ;
return result ;
}
public ILabel CreateLabel ( IFont font , Point position , string text )
{
var result = new SDL2Label ( font , renderer )
{
Text = text ,
2018-11-22 18:06:15 -05:00
Location = position
2018-11-22 16:22:39 -05:00
} ;
2018-11-22 14:30:37 -05:00
return result ;
}
2018-11-22 16:22:39 -05:00
public void Draw ( ILabel label )
{
var lbl = label as SDL2Label ;
2018-11-22 18:06:15 -05:00
var loc = lbl . Location ;
2018-11-22 16:22:39 -05:00
var destRect = new SDL . SDL_Rect
{
x = loc . X ,
y = loc . Y ,
w = lbl . textureSize . Width ,
h = lbl . textureSize . Height
} ;
2018-11-22 18:06:15 -05:00
2018-11-22 16:22:39 -05:00
SDL . SDL_RenderCopy ( renderer , lbl . texture , IntPtr . Zero , ref destRect ) ;
}
2018-11-24 10:54:02 -05:00
2018-11-27 23:09:10 -05:00
public unsafe MapCellInfo CacheMapCell ( MPQDT1Tile mapCell )
2018-11-24 23:49:56 -05:00
{
2018-11-27 23:09:10 -05:00
var minX = mapCell . Blocks . Min ( x = > x . PositionX ) ;
var minY = mapCell . Blocks . Min ( x = > x . PositionY ) ;
var maxX = mapCell . Blocks . Max ( x = > x . PositionX + 32 ) ;
var maxY = mapCell . Blocks . Max ( x = > x . PositionY + 32 ) ;
2018-11-25 18:37:53 -05:00
var diffX = maxX - minX ;
var diffY = maxY - minY ;
var offX = - minX ;
2018-11-28 19:28:41 -05:00
var offY = - minY ;
2018-11-25 18:37:53 -05:00
var frameSize = new Size ( diffX , Math . Abs ( diffY ) ) ;
var srcRect = new SDL . SDL_Rect { x = 0 , y = 0 , w = frameSize . Width , h = Math . Abs ( frameSize . Height ) } ;
var frameSizeMax = diffX * Math . Abs ( diffY ) ;
var texId = SDL . SDL_CreateTexture ( renderer , SDL . SDL_PIXELFORMAT_ARGB8888 , ( int ) SDL . SDL_TextureAccess . SDL_TEXTUREACCESS_STREAMING , frameSize . Width , frameSize . Height ) ;
SDL . SDL_SetTextureBlendMode ( texId , SDL . SDL_BlendMode . SDL_BLENDMODE_BLEND ) ;
if ( SDL . SDL_LockTexture ( texId , IntPtr . Zero , out IntPtr pixels , out int pitch ) ! = 0 )
2018-11-27 23:09:10 -05:00
throw new ApplicationException ( "Could not lock texture for map rendering" ) ;
2018-11-24 23:49:56 -05:00
try
{
UInt32 * data = ( UInt32 * ) pixels ;
var pitchChange = ( pitch / 4 ) ;
2018-11-27 00:56:54 -05:00
2018-11-25 18:37:53 -05:00
for ( var i = 0 ; i < frameSize . Height * pitchChange ; i + + )
data [ i ] = 0x0 ;
2018-11-27 00:56:54 -05:00
2018-11-24 23:49:56 -05:00
2018-11-27 23:09:10 -05:00
foreach ( var block in mapCell . Blocks )
2018-11-24 23:49:56 -05:00
{
2018-11-28 19:28:41 -05:00
var index = block . PositionX + offX + ( ( block . PositionY + offY ) * pitchChange ) ;
2018-11-25 09:42:39 -05:00
var xx = 0 ;
2018-11-25 14:15:13 -05:00
var yy = 0 ;
2018-11-25 09:42:39 -05:00
foreach ( var colorIndex in block . PixelData )
2018-11-24 23:49:56 -05:00
{
2018-11-25 09:42:39 -05:00
try
2018-11-24 23:49:56 -05:00
{
2018-11-25 14:15:13 -05:00
if ( colorIndex = = 0 )
continue ;
2018-11-28 19:28:41 -05:00
var color = getGameState ( ) . CurrentPalette . Colors [ colorIndex ] ;
2018-11-27 00:56:54 -05:00
2018-11-25 18:37:53 -05:00
if ( color > 0 )
2018-11-24 23:49:56 -05:00
data [ index ] = color ;
2018-11-25 14:15:13 -05:00
}
finally
2018-11-25 09:42:39 -05:00
{
index + + ;
xx + + ;
if ( xx = = 32 )
{
index - = 32 ;
index + = pitchChange ;
xx = 0 ;
2018-11-25 14:15:13 -05:00
yy + + ;
2018-11-25 09:42:39 -05:00
}
2018-11-24 23:49:56 -05:00
}
}
}
}
finally
{
2018-11-25 18:37:53 -05:00
SDL . SDL_UnlockTexture ( texId ) ;
2018-11-24 23:49:56 -05:00
}
2018-11-27 23:09:10 -05:00
return new MapCellInfo
2018-11-25 18:37:53 -05:00
{
2018-11-28 19:28:41 -05:00
Tile = mapCell ,
2018-11-25 18:37:53 -05:00
FrameHeight = frameSize . Height ,
FrameWidth = frameSize . Width ,
OffX = offX ,
2018-11-28 19:28:41 -05:00
OffY = offY ,
2018-11-27 00:56:54 -05:00
Rect = srcRect . ToRectangle ( ) ,
Texture = new SDL2Texture { Pointer = texId }
2018-11-25 18:37:53 -05:00
} ;
2018-11-27 23:09:10 -05:00
}
2018-11-25 18:37:53 -05:00
2018-11-27 23:09:10 -05:00
public void DrawMapCell ( MapCellInfo mapCellInfo , int xPixel , int yPixel )
{
var srcRect = new SDL . SDL_Rect { x = 0 , y = 0 , w = mapCellInfo . FrameWidth , h = Math . Abs ( mapCellInfo . FrameHeight ) } ;
2018-11-28 19:28:41 -05:00
var destRect = new SDL . SDL_Rect { x = xPixel - mapCellInfo . OffX , y = yPixel - mapCellInfo . OffY , w = mapCellInfo . FrameWidth , h = mapCellInfo . FrameHeight } ;
2018-11-27 23:09:10 -05:00
SDL . SDL_RenderCopy ( renderer , ( mapCellInfo . Texture as SDL2Texture ) . Pointer , ref srcRect , ref destRect ) ;
2018-11-24 23:49:56 -05:00
}
2018-11-27 20:02:18 -05:00
public unsafe IMouseCursor LoadCursor ( ISprite sprite , int frame , Point hotspot )
{
2018-11-29 23:26:51 -05:00
if ( globalConfig . MouseMode = = eMouseMode . Software )
{
sprite . Frame = frame ;
var texId = SDL . SDL_CreateTexture ( renderer , SDL . SDL_PIXELFORMAT_ARGB8888 ,
( int ) SDL . SDL_TextureAccess . SDL_TEXTUREACCESS_TARGET , sprite . LocalFrameSize . Width , sprite . LocalFrameSize . Height ) ;
SDL . SDL_SetTextureBlendMode ( texId , SDL . SDL_BlendMode . SDL_BLENDMODE_BLEND ) ;
SDL . SDL_SetRenderTarget ( renderer , texId ) ;
SDL . SDL_RenderCopy ( renderer , ( sprite as SDL2Sprite ) . texture , IntPtr . Zero , IntPtr . Zero ) ;
SDL . SDL_SetRenderTarget ( renderer , IntPtr . Zero ) ;
return new SDL2MouseCursor
{
Hotspot = hotspot ,
ImageSize = sprite . LocalFrameSize ,
SWTexture = texId
} ;
}
2018-11-27 20:02:18 -05:00
var multiple = globalConfig . HardwareMouseScale ;
var spr = sprite as SDL2Sprite ;
2018-11-29 23:26:51 -05:00
var surface = SDL . SDL_CreateRGBSurface ( 0 , spr . LocalFrameSize . Width * multiple , spr . LocalFrameSize . Height * multiple , 32 , 0xFF0000 , 0xFF00 , 0xFF , 0xFF000000 ) ;
2018-12-02 16:34:00 -05:00
var yOffset = 0 ; //(spr.FrameSize.Height - spr.LocalFrameSize.Height);
var XOffset = 0 ; //(spr.FrameSize.Width - spr.LocalFrameSize.Width);
2018-11-27 20:02:18 -05:00
var pixels = ( UInt32 * ) ( ( SDL . SDL_Surface * ) surface ) - > pixels ;
2018-11-29 23:26:51 -05:00
for ( var y = 0 ; y < ( spr . LocalFrameSize . Height * multiple ) - 1 ; y + + )
for ( var x = 0 ; x < ( spr . LocalFrameSize . Width * multiple ) - 1 ; x + + )
2018-11-27 20:02:18 -05:00
{
2018-11-29 23:26:51 -05:00
pixels [ x + XOffset + ( ( y + yOffset ) * spr . LocalFrameSize . Width * multiple ) ] = spr . source . Frames [ frame ] . GetColor ( x / multiple , y / multiple , sprite . CurrentPalette ) ;
2018-11-27 20:02:18 -05:00
}
2018-11-29 23:26:51 -05:00
var cursor = SDL . SDL_CreateColorCursor ( surface , hotspot . X * multiple , hotspot . Y * multiple ) ;
2018-11-27 20:02:18 -05:00
if ( cursor = = IntPtr . Zero )
throw new ApplicationException ( $"Unable to set the cursor cursor: {SDL.SDL_GetError()}" ) ; // TODO: Is this supported everywhere? May need to still support software cursors.
2018-11-29 23:26:51 -05:00
return new SDL2MouseCursor { HWSurface = cursor } ;
2018-11-27 20:02:18 -05:00
}
2018-11-29 23:26:51 -05:00
private void SetCursor ( IMouseCursor mouseCursor )
2018-11-27 20:02:18 -05:00
{
2018-11-29 23:26:51 -05:00
this . mouseCursor = mouseCursor ;
2018-11-27 20:02:18 -05:00
if ( globalConfig . MouseMode ! = eMouseMode . Hardware )
2018-11-29 23:26:51 -05:00
return ;
2018-11-27 20:02:18 -05:00
2018-11-29 23:26:51 -05:00
SDL . SDL_SetCursor ( ( mouseCursor as SDL2MouseCursor ) . HWSurface ) ;
2018-11-27 20:02:18 -05:00
}
2018-11-29 17:58:56 -05:00
public uint GetTicks ( ) = > SDL . SDL_GetTicks ( ) ;
2018-11-29 23:26:51 -05:00
2018-12-07 18:45:54 -05:00
public ICharacterRenderer CreateCharacterRenderer ( )
= > new SDL2CharacterRenderer ( this . renderer , resourceManager , paletteProvider ) ;
2018-11-22 00:18:42 -05:00
}
}