2009-04-15 17:03:31 +03:00
/*
* SDL_Extensions . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
2009-04-16 14:14:13 +03:00
*/
2014-05-23 13:51:38 +03:00
# pragma once
# include <SDL_version.h>
# ifndef VCMI_SDL1
# include <SDL_render.h>
# endif
# include <SDL_video.h>
2014-07-15 10:14:49 +03:00
# include <SDL_events.h>
2014-05-23 13:51:38 +03:00
# include "../../lib/int3.h"
2014-07-15 10:14:49 +03:00
//#include "../Graphics.h"
2014-05-23 13:51:38 +03:00
# include "Geometries.h"
2014-07-15 10:14:49 +03:00
# include "../../lib/GameConstants.h"
2014-05-23 13:51:38 +03:00
2009-04-16 14:14:13 +03:00
2010-08-12 08:22:48 +03:00
//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
# ifdef _MSC_VER
# define STRONG_INLINE __forceinline
2011-02-06 19:26:27 +02:00
# elif __GNUC__
2012-05-15 11:47:11 +03:00
# define STRONG_INLINE inline __attribute__((always_inline))
2010-08-12 08:22:48 +03:00
# else
# define STRONG_INLINE inline
# endif
2011-11-17 03:24:27 +03:00
# if SDL_VERSION_ATLEAST(1,3,0)
# define SDL_GetKeyState SDL_GetKeyboardState
# endif
2014-05-23 13:51:38 +03:00
//SDL2 support
# if (SDL_MAJOR_VERSION == 2)
2014-05-21 19:04:34 +03:00
extern SDL_Window * mainWindow ;
extern SDL_Renderer * mainRenderer ;
extern SDL_Texture * screenTexture ;
inline void SDL_SetColors ( SDL_Surface * surface , SDL_Color * colors , int firstcolor , int ncolors )
{
SDL_SetPaletteColors ( surface - > format - > palette , colors , firstcolor , ncolors ) ;
}
inline void SDL_WarpMouse ( int x , int y )
{
SDL_WarpMouseInWindow ( mainWindow , x , y ) ;
}
2014-06-01 18:31:37 +03:00
void SDL_UpdateRect ( SDL_Surface * surface , int x , int y , int w , int h ) ;
2014-05-23 13:51:38 +03:00
# endif
2014-05-21 19:04:34 +03:00
2014-05-21 22:14:05 +03:00
inline bool isCtrlKeyDown ( )
{
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2014-05-21 22:14:05 +03:00
return SDL_GetKeyState ( nullptr ) [ SDLK_LCTRL ] | | SDL_GetKeyState ( nullptr ) [ SDLK_RCTRL ] ;
# else
return SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_LCTRL ] | | SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_RCTRL ] ;
2014-05-23 13:51:38 +03:00
# endif
2014-05-21 22:14:05 +03:00
}
inline bool isAltKeyDown ( )
{
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2014-05-21 22:14:05 +03:00
return SDL_GetKeyState ( nullptr ) [ SDLK_LALT ] | | SDL_GetKeyState ( nullptr ) [ SDLK_RALT ] ;
# else
return SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_LALT ] | | SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_RALT ] ;
2014-05-23 13:51:38 +03:00
# endif
2014-05-21 22:14:05 +03:00
}
inline bool isShiftKeyDown ( )
{
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2014-05-21 22:14:05 +03:00
return SDL_GetKeyState ( nullptr ) [ SDLK_LSHIFT ] | | SDL_GetKeyState ( nullptr ) [ SDLK_RSHIFT ] ;
# else
return SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_LSHIFT ] | | SDL_GetKeyboardState ( nullptr ) [ SDL_SCANCODE_RSHIFT ] ;
2014-05-23 13:51:38 +03:00
# endif
}
namespace CSDL_Ext
{
STRONG_INLINE void colorSetAlpha ( SDL_Color & color , Uint8 alpha )
{
2015-02-18 16:31:55 +02:00
# ifdef VCMI_SDL1
2014-05-23 13:51:38 +03:00
color . unused = alpha ;
2015-02-18 16:31:55 +02:00
# else
2014-05-23 13:51:38 +03:00
color . a = alpha ;
2015-02-18 16:31:55 +02:00
# endif
2014-05-23 13:51:38 +03:00
}
//todo: should this better be assignment operator?
STRONG_INLINE void colorAssign ( SDL_Color & dest , const SDL_Color & source )
{
2015-02-18 16:31:55 +02:00
dest . r = source . r ;
2014-05-23 13:51:38 +03:00
dest . g = source . g ;
2015-02-18 16:31:55 +02:00
dest . b = source . b ;
# ifdef VCMI_SDL1
2014-05-23 13:51:38 +03:00
dest . unused = source . unused ;
2015-02-18 16:31:55 +02:00
# else
2014-05-23 13:51:38 +03:00
dest . a = source . a ;
2015-02-18 16:31:55 +02:00
# endif
}
inline void setAlpha ( SDL_Surface * bg , int value )
{
# ifdef VCMI_SDL1
SDL_SetAlpha ( bg , SDL_SRCALPHA , value ) ;
# else
SDL_SetSurfaceAlphaMod ( bg , value ) ;
# endif
2014-05-23 13:51:38 +03:00
}
2014-05-21 22:14:05 +03:00
}
2010-08-05 14:02:18 +03:00
struct Rect ;
2009-05-25 02:21:55 +03:00
extern SDL_Surface * screen , * screen2 , * screenBuf ;
2009-04-16 14:14:13 +03:00
void blitAt ( SDL_Surface * src , int x , int y , SDL_Surface * dst = screen ) ;
2009-06-17 12:38:03 +03:00
void blitAt ( SDL_Surface * src , const SDL_Rect & pos , SDL_Surface * dst = screen ) ;
2009-04-16 14:14:13 +03:00
bool isItIn ( const SDL_Rect * rect , int x , int y ) ;
2009-04-17 17:01:22 +03:00
2012-11-11 15:23:31 +03:00
/**
* The colors class defines color constants of type SDL_Color .
*/
class Colors
2011-12-22 16:05:19 +03:00
{
2012-11-11 15:23:31 +03:00
public :
/** the h3 yellow color, typically used for headlines */
static const SDL_Color YELLOW ;
/** the standard h3 white color */
static const SDL_Color WHITE ;
2012-11-20 20:53:45 +03:00
/** the metallic gold color used mostly as a border around buttons */
static const SDL_Color METALLIC_GOLD ;
2012-12-19 20:24:53 +03:00
/** green color used for in-game console */
static const SDL_Color GREEN ;
2014-07-02 21:20:54 +03:00
/** default key color for all 8 & 24 bit graphics */
static const SDL_Color DEFAULT_KEY_COLOR ;
2012-11-11 15:23:31 +03:00
} ;
2011-12-22 16:05:19 +03:00
2012-07-21 00:42:25 +03:00
//MSVC gives an error when calling abs with ui64 -> we add template that will match calls with unsigned arg and return it
template < typename T >
typename boost : : enable_if_c < boost : : is_unsigned < T > : : type , T > : : type abs ( T arg )
{
return arg ;
}
2009-06-26 18:41:19 +03:00
template < typename IntType >
2014-07-04 12:48:09 +03:00
std : : string makeNumberShort ( IntType number , IntType maxLength = 3 ) //the output is a string containing at most 5 characters [4 if positive] (eg. intead 10000 it gives 10k)
2009-06-26 18:41:19 +03:00
{
2014-07-04 12:48:09 +03:00
IntType max = pow ( 10 , maxLength ) ;
if ( abs ( number ) < max )
2012-07-19 21:52:44 +03:00
return boost : : lexical_cast < std : : string > ( number ) ;
2009-06-26 18:41:19 +03:00
2014-07-04 12:48:09 +03:00
std : : string symbols = " kMGTPE " ;
2012-07-19 21:52:44 +03:00
auto iter = symbols . begin ( ) ;
2009-06-26 18:41:19 +03:00
2014-07-04 12:48:09 +03:00
while ( number > = max )
2009-06-26 18:41:19 +03:00
{
2012-07-19 21:52:44 +03:00
number / = 1000 ;
iter + + ;
2009-06-26 18:41:19 +03:00
2012-07-19 21:52:44 +03:00
assert ( iter ! = symbols . end ( ) ) ; //should be enough even for int64
}
return boost : : lexical_cast < std : : string > ( number ) + * iter ;
2009-06-26 18:41:19 +03:00
}
2010-08-05 14:02:18 +03:00
typedef void ( * TColorPutter ) ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B ) ;
2010-08-12 08:22:48 +03:00
typedef void ( * TColorPutterAlpha ) ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B , const Uint8 & A ) ;
2010-08-05 14:02:18 +03:00
2009-04-16 14:14:13 +03:00
inline SDL_Rect genRect ( const int & hh , const int & ww , const int & xx , const int & yy )
{
SDL_Rect ret ;
ret . h = hh ;
ret . w = ww ;
ret . x = xx ;
ret . y = yy ;
return ret ;
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
template < int bpp , int incrementPtr >
struct ColorPutter
{
static STRONG_INLINE void PutColor ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B ) ;
static STRONG_INLINE void PutColor ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B , const Uint8 & A ) ;
static STRONG_INLINE void PutColorAlphaSwitch ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B , const Uint8 & A ) ;
static STRONG_INLINE void PutColor ( Uint8 * & ptr , const SDL_Color & Color ) ;
static STRONG_INLINE void PutColorAlpha ( Uint8 * & ptr , const SDL_Color & Color ) ;
2011-02-20 11:24:53 +02:00
static STRONG_INLINE void PutColorRow ( Uint8 * & ptr , const SDL_Color & Color , size_t count ) ;
2010-08-12 08:22:48 +03:00
} ;
2010-08-05 14:02:18 +03:00
typedef void ( * BlitterWithRotationVal ) ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ;
2009-04-16 14:14:13 +03:00
namespace CSDL_Ext
{
2012-07-21 23:16:54 +03:00
/// helper that will safely set and un-set ClipRect for SDL_Surface
class CClipRectGuard
{
SDL_Surface * surf ;
SDL_Rect oldRect ;
public :
CClipRectGuard ( SDL_Surface * surface , const SDL_Rect & rect ) :
2012-11-11 15:23:31 +03:00
surf ( surface )
2012-07-21 23:16:54 +03:00
{
SDL_GetClipRect ( surf , & oldRect ) ;
SDL_SetClipRect ( surf , & rect ) ;
}
~ CClipRectGuard ( )
{
SDL_SetClipRect ( surf , & oldRect ) ;
}
} ;
2010-08-23 18:16:40 +03:00
void blitSurface ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect ) ;
2010-08-23 19:13:30 +03:00
void fillRect ( SDL_Surface * dst , SDL_Rect * dstrect , Uint32 color ) ;
2014-07-05 00:46:55 +03:00
void fillRectBlack ( SDL_Surface * dst , SDL_Rect * dstrect ) ;
2012-07-21 23:16:54 +03:00
//fill dest image with source texture.
void fillTexture ( SDL_Surface * dst , SDL_Surface * sourceTexture ) ;
2009-04-16 14:14:13 +03:00
2010-08-05 14:02:18 +03:00
void SDL_PutPixelWithoutRefresh ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A = 255 ) ;
void SDL_PutPixelWithoutRefreshIfInSurf ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A = 255 ) ;
2009-04-16 14:14:13 +03:00
2013-11-06 16:42:58 +03:00
SDL_Surface * verticalFlip ( SDL_Surface * toRot ) ; //vertical flip
SDL_Surface * horizontalFlip ( SDL_Surface * toRot ) ; //horizontal flip
2009-04-16 14:14:13 +03:00
Uint32 SDL_GetPixel ( SDL_Surface * surface , const int & x , const int & y , bool colorByte = false ) ;
2009-06-07 01:47:23 +03:00
void alphaTransform ( SDL_Surface * src ) ; //adds transparency and shadows (partial handling only; see examples of using for details)
2010-02-18 14:44:59 +02:00
bool isTransparent ( SDL_Surface * srf , int x , int y ) ; //checks if surface is transparent at given position
2009-12-22 23:53:50 +02:00
2012-05-19 19:22:34 +03:00
Uint8 * getPxPtr ( const SDL_Surface * const & srf , const int x , const int y ) ;
2012-05-28 22:29:32 +03:00
TColorPutter getPutterFor ( SDL_Surface * const & dest , int incrementing ) ; //incrementing: -1, 0, 1
TColorPutterAlpha getPutterAlphaFor ( SDL_Surface * const & dest , int incrementing ) ; //incrementing: -1, 0, 1
2010-08-05 14:02:18 +03:00
BlitterWithRotationVal getBlitterWithRotation ( SDL_Surface * dest ) ;
BlitterWithRotationVal getBlitterWithRotationAndAlpha ( SDL_Surface * dest ) ;
template < int bpp > void blitWithRotateClip ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipVal ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipWithAlpha ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipValWithAlpha ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotate1 ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
template < int bpp > void blitWithRotate2 ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
template < int bpp > void blitWithRotate3 ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
template < int bpp > void blitWithRotate1WithAlpha ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
template < int bpp > void blitWithRotate2WithAlpha ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
template < int bpp > void blitWithRotate3WithAlpha ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , const SDL_Rect * dstRect ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests
2009-12-22 23:53:50 +02:00
2010-08-12 08:22:48 +03:00
template < int bpp >
int blit8bppAlphaTo24bppT ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect ) ; //blits 8 bpp surface with alpha channel to 24 bpp surface
2009-05-28 05:58:29 +03:00
int blit8bppAlphaTo24bpp ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect ) ; //blits 8 bpp surface with alpha channel to 24 bpp surface
2009-04-16 14:14:13 +03:00
Uint32 colorToUint32 ( const SDL_Color * color ) ; //little endian only
2013-07-07 11:27:27 +03:00
SDL_Color makeColor ( ui8 r , ui8 g , ui8 b , ui8 a ) ;
2009-08-17 11:50:31 +03:00
2009-04-16 14:14:13 +03:00
void update ( SDL_Surface * what = screen ) ; //updates whole surface (default - main screen)
2009-09-20 15:47:40 +03:00
void drawBorder ( SDL_Surface * sur , int x , int y , int w , int h , const int3 & color ) ;
void drawBorder ( SDL_Surface * sur , const SDL_Rect & r , const int3 & color ) ;
2011-12-22 16:05:19 +03:00
void drawDashedBorder ( SDL_Surface * sur , const Rect & r , const int3 & color ) ;
2013-03-03 20:06:03 +03:00
void setPlayerColor ( SDL_Surface * sur , PlayerColor player ) ; //sets correct color of flags; -1 for neutral
2009-04-16 14:14:13 +03:00
std : : string processStr ( std : : string str , std : : vector < std : : string > & tor ) ; //replaces %s in string
SDL_Surface * newSurface ( int w , int h , SDL_Surface * mod = screen ) ; //creates new surface, with flags/format same as in surface given
SDL_Surface * copySurface ( SDL_Surface * mod ) ; //returns copy of given surface
2012-05-18 20:35:46 +03:00
template < int bpp >
SDL_Surface * createSurfaceWithBpp ( int width , int height ) ; //create surface with give bits per pixels value
2010-07-15 20:13:17 +03:00
void VflipSurf ( SDL_Surface * surf ) ; //fluipis given surface by vertical axis
2012-05-17 13:44:48 +03:00
2012-06-15 20:08:19 +03:00
//scale surface to required size.
//nearest neighbour algorithm
SDL_Surface * scaleSurfaceFast ( SDL_Surface * surf , int width , int height ) ;
// bilinear filtering. Uses fallback to scaleSurfaceFast in case of indexed surfaces
2012-05-20 00:38:01 +03:00
SDL_Surface * scaleSurface ( SDL_Surface * surf , int width , int height ) ;
2012-05-17 13:44:48 +03:00
template < int bpp >
void applyEffectBpp ( SDL_Surface * surf , const SDL_Rect * rect , int mode ) ;
2010-08-17 15:48:34 +03:00
void applyEffect ( SDL_Surface * surf , const SDL_Rect * rect , int mode ) ; //mode: 0 - sepia, 1 - grayscale
2014-07-02 18:41:30 +03:00
void startTextInput ( SDL_Rect * where ) ;
void stopTextInput ( ) ;
2014-07-02 21:20:54 +03:00
void setColorKey ( SDL_Surface * surface , SDL_Color color ) ;
///set key-color to 0,255,255
void setDefaultColorKey ( SDL_Surface * surface ) ;
///set key-color to 0,255,255 only if it exactly mapped
void setDefaultColorKeyPresize ( SDL_Surface * surface ) ;
2012-09-15 22:16:16 +03:00
}