From 6d3a042add78e53d9b6632025e0c3e23af75edee Mon Sep 17 00:00:00 2001 From: mateuszb Date: Tue, 21 Aug 2007 13:48:18 +0000 Subject: [PATCH] * graphical cursors are now posiible, however the code is a bit ugly and eats significant amount of resources (up to 15% of my CPU power) --- CCursorHandler.cpp | 237 +++++++++++++++++++++++++++++++++++++++++++++ CCursorHandler.h | 30 ++++++ CGameInfo.h | 4 + CGameInterface.cpp | 9 +- CMT.cpp | 16 ++- CPreGame.cpp | Bin 115486 -> 115936 bytes CScreenHandler.cpp | 43 ++++++++ CScreenHandler.h | 17 ++++ SDL_Extensions.cpp | 3 +- 9 files changed, 354 insertions(+), 5 deletions(-) create mode 100644 CCursorHandler.cpp create mode 100644 CCursorHandler.h create mode 100644 CScreenHandler.cpp create mode 100644 CScreenHandler.h diff --git a/CCursorHandler.cpp b/CCursorHandler.cpp new file mode 100644 index 000000000..01e18c44d --- /dev/null +++ b/CCursorHandler.cpp @@ -0,0 +1,237 @@ +#include "stdafx.h" +#include "CCursorHandler.h" +#include "SDL.h" +#include "SDL_thread.h" +#include "CGameInfo.h" +#include "SDL_framerate.h" + +extern SDL_Surface * screen; + +/* Creates a new mouse cursor from an XPM */ + + +/* XPM */ +static const char *arrow[] = { //no cursor mode + /* width height num_colors chars_per_pixel */ + " 32 32 3 1", + /* colors */ + "X c #000000", + ". c #ffffff", + " c None", + /* pixels */ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "0,0" +}; + +/* XPM */ +static const char *arrow2[] = { //normal cursor + /* width height num_colors chars_per_pixel */ + " 32 32 3 1", + /* colors */ + "X c #000000", + ". c #ffffff", + " c None", + /* pixels */ + "X ", + "XX ", + "X.X ", + "X..X ", + "X...X ", + "X....X ", + "X.....X ", + "X......X ", + "X.......X ", + "X........X ", + "X.....XXXXX ", + "X..X..X ", + "X.X X..X ", + "XX X..X ", + "X X..X ", + " X..X ", + " X..X ", + " X..X ", + " XX ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + "0,0" +}; + +static SDL_Cursor *init_system_cursor(const char *image[]) +{ + int i, row, col; + Uint8 data[4*32]; + Uint8 mask[4*32]; + int hot_x, hot_y; + + i = -1; + for ( row=0; row<32; ++row ) { + for ( col=0; col<32; ++col ) { + if ( col % 8 ) { + data[i] <<= 1; + mask[i] <<= 1; + } else { + ++i; + data[i] = mask[i] = 0; + } + switch (image[4+row][col]) { + case 'X': + data[i] |= 0x01; + //k[i] |= 0x01; + break; + case '.': + mask[i] |= 0x01; + break; + case ' ': + break; + } + } + } + sscanf(image[4+row], "%d,%d", &hot_x, &hot_y); + return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y); +} + +//int cursorHandlerFunc(void * cursorHandler) +//{ +// FPSmanager * cursorFramerateKeeper = new FPSmanager; +// SDL_initFramerate(cursorFramerateKeeper); +// SDL_setFramerate(cursorFramerateKeeper, 200); +// +// CCursorHandler * ch = (CCursorHandler *) cursorHandler; +// while(true) +// { +// if(ch->xbef!=-1 && ch->ybef!=-1) //restore surface under cursor +// { +// blitAtWR(ch->behindCur, ch->xbef, ch->ybef); +// } +// ch->xbef = ch->xpos; +// ch->ybef = ch->ypos; +// //prepare part of surface to restore +// SDL_BlitSurface(screen, &genRect(32, 32, ch->xpos, ch->ypos), ch->behindCur, NULL); +// CSDL_Ext::update(ch->behindCur); +// +// //blit cursor +// if(ch->curVisible) +// { +// switch(ch->mode) +// { +// case 0: +// { +// break; +// } +// case 1: +// { +// break; +// } +// case 2: +// { +// blitAtWR(ch->deflt->ourImages[ch->number].bitmap, ch->xpos, ch->ypos); +// break; +// } +// } +// } +// SDL_framerateDelay(cursorFramerateKeeper); +// //SDL_Delay(5); //to avoid great usage of CPU +// } +// return 0; +//} + +void CCursorHandler::initCursor() +{ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + int rmask = 0xff000000; + int gmask = 0x00ff0000; + int bmask = 0x0000ff00; + int amask = 0x000000ff; +#else + int rmask = 0x000000ff; + int gmask = 0x0000ff00; + int bmask = 0x00ff0000; + int amask = 0xff000000; +#endif + curVisible = true; + xpos = ypos = 0; + behindCur = SDL_CreateRGBSurface(SDL_SWSURFACE, 32, 32, 32, rmask, gmask, bmask, amask); + xbef = ybef = 0; + std::vector pom = CGI->spriteh->entries.vectorize(); + adventure = CGI->spriteh->giveDef("CRADVNTR.DEF"); + combat = CGI->spriteh->giveDef("CRCOMBAT.DEF"); + deflt = CGI->spriteh->giveDef("CRDEFLT.DEF"); + spell = CGI->spriteh->giveDef("CRSPELL.DEF"); + //SDL_SetCursor(init_system_cursor(arrow)); + //SDL_Thread * myth = SDL_CreateThread(&cursorHandlerFunc, this); +} + +void CCursorHandler::changeGraphic(int type, int no) +{ + mode = type; + number = no; +} + +void CCursorHandler::cursorMove(int x, int y) +{ + xbef = xpos; + ybef = ypos; + xpos = x; + ypos = y; +} + +void CCursorHandler::hardwareCursor() +{ + curVisible = false; + SDL_SetCursor(init_system_cursor(arrow2)); +} + +void CCursorHandler::hideCursor() +{ + curVisible = false; + SDL_SetCursor(init_system_cursor(arrow)); +} + +void CCursorHandler::showGraphicCursor() +{ + curVisible = true; + SDL_SetCursor(init_system_cursor(arrow)); + changeGraphic(0, 0); +} \ No newline at end of file diff --git a/CCursorHandler.h b/CCursorHandler.h new file mode 100644 index 000000000..f15ed574a --- /dev/null +++ b/CCursorHandler.h @@ -0,0 +1,30 @@ +#ifndef CCURSORHANDLER_H +#define CCURSORHANDLER_H + +struct SDL_Thread; +struct CDefHandler; +struct SDL_Surface; + +class CCursorHandler //handles cursor +{ +public: + SDL_Thread * myThread; //thread that updates cursor + bool curVisible; //true if cursor is visible + int mode, number; + SDL_Surface * behindCur; + int xbef, ybef; //position of cursor after last move (to restore background) + + CDefHandler * adventure, * combat, * deflt, * spell; //read - only + int xpos, ypos; //position of cursor - read only + void initCursor(); //inits cursorHandler + void showGraphicCursor(); //shows default graphic cursor + void cursorMove(int x, int y); //change cursor's positions to (x, y) + void changeGraphic(int type, int no); //changes cursor graphic for type type (0 - adventure, 1 - combat, 2 - default, 3 - spellbook) and frame no (not used for type 3) + void hideCursor(); //no cursor will be visible + void hardwareCursor(); // returns to hardware cursor mode + friend int cursorHandlerFunc(void * cursorHandler); +}; + + + +#endif //CCURSORHANDLER_H \ No newline at end of file diff --git a/CGameInfo.h b/CGameInfo.h index 15764a3d0..76950379f 100644 --- a/CGameInfo.h +++ b/CGameInfo.h @@ -22,6 +22,8 @@ #include "mapHandler.h" #include "CConsoleHandler.h" #include "CPathfinder.h" +#include "CCursorHandler.h" +#include "CScreenHandler.h" #include "SDL.h" #include @@ -55,6 +57,8 @@ public: CGeneralTextHandler * generaltexth; CConsoleHandler * consoleh; CPathfinder * pathf; + CCursorHandler * curh; + CScreenHandler * screenh; int localPlayer; std::vector playerint; std::vector playerColors; diff --git a/CGameInterface.cpp b/CGameInterface.cpp index 06e0b8af1..988c348c6 100644 --- a/CGameInterface.cpp +++ b/CGameInterface.cpp @@ -100,7 +100,8 @@ void CPlayerInterface::yourTurn() //framerate keeper initialized for(;;) // main loop { - + CGI->screenh->updateScreen(); + LOCPLINT->adventureInt->updateScreen = false; if(SDL_PollEvent(&sEvent)) //wait for event... { @@ -163,6 +164,12 @@ void CPlayerInterface::yourTurn() void CPlayerInterface::handleEvent(SDL_Event *sEvent) { current = sEvent; + + if(sEvent->type == SDL_MOUSEMOTION) + { + CGI->curh->cursorMove(sEvent->motion.x, sEvent->motion.y); + } + if(sEvent->type==SDL_QUIT) exit(0); else if (sEvent->type==SDL_KEYDOWN) diff --git a/CMT.cpp b/CMT.cpp index ede237388..e0236035a 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -38,6 +38,8 @@ #include "CPreGame.h" #include "CGeneralTextHandler.h" #include "CConsoleHandler.h" +#include "CCursorHandler.h" +#include "CScreenHandler.h" #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) # include @@ -56,7 +58,7 @@ const char * NAME = "VCMI 0.3"; level is supplied, Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match, or Z_ERRNO if there is an error reading or writing the files. */ -SDL_Surface * ekran; +SDL_Surface * ekran, * screen, * screen2; TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX; int _tmain(int argc, _TCHAR* argv[]) @@ -70,7 +72,7 @@ int _tmain(int argc, _TCHAR* argv[]) int xx=0, yy=0, zz=0; SDL_Event sEvent; srand ( time(NULL) ); - SDL_Surface *screen, *temp; + SDL_Surface *temp; std::vector Sprites; float i; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO/*|SDL_INIT_EVENTTHREAD*/)==0) @@ -98,7 +100,8 @@ int _tmain(int argc, _TCHAR* argv[]) // well, there's no music, but most games don't break without music... }*/ - screen = SDL_SetVideoMode(800,600,24,SDL_SWSURFACE|SDL_DOUBLEBUF/*|SDL_FULLSCREEN*/); + screen2 = SDL_SetVideoMode(800,600,24,SDL_SWSURFACE|SDL_DOUBLEBUF/*|SDL_FULLSCREEN*/); + screen = SDL_ConvertSurface(screen2, screen2->format, SDL_SWSURFACE); ekran = screen; SDL_WM_SetCaption(NAME,""); //set window title @@ -107,6 +110,7 @@ int _tmain(int argc, _TCHAR* argv[]) cgi->consoleh = new CConsoleHandler; cgi->consoleh->runConsole(); cgi->mush = mush; + cgi->curh = new CCursorHandler; THC std::cout<<"Initializing screen, fonts and sound handling: "<spriteh = new CLodHandler; @@ -114,6 +118,12 @@ int _tmain(int argc, _TCHAR* argv[]) cgi->bitmaph = new CLodHandler; cgi->bitmaph->init(std::string("Data\\H3bitmap.lod")); + cgi->curh->initCursor(); + cgi->curh->showGraphicCursor(); + + cgi->screenh = new CScreenHandler; + cgi->screenh->initScreen(); + //colors initialization SDL_Color p; p.unused = 0; diff --git a/CPreGame.cpp b/CPreGame.cpp index eb7673999845b00b004d9da9efcb1390e255f49c..5d03335246b33b370b3c26b7277bb8e4cc2956d4 100644 GIT binary patch delta 312 zcmbQ&#{Qs_yvkDnc@mV4aE(RK11T-L(ArESNDMJB63PU182~aE;NmheFlfinsb_3&M4)PqP zY0aR(pbvy;V5ciEqyueE1lpFtkO{OWks${tp9_>LozB?HC_H_^6h@Beah;5O)Bj~L Q3QYesmr-jwkbA%q08e*Jm;e9( delta 29 lcmaFR$v&@*ycurh->mode) + { + case 0: + { + blitAt(CGI->curh->adventure->ourImages[CGI->curh->number].bitmap, CGI->curh->xpos, CGI->curh->ypos, screen2); + break; + } + case 1: + { + blitAt(CGI->curh->combat->ourImages[CGI->curh->number].bitmap, CGI->curh->xpos, CGI->curh->ypos, screen2); + break; + } + case 2: + { + blitAt(CGI->curh->deflt->ourImages[CGI->curh->number].bitmap, CGI->curh->xpos, CGI->curh->ypos, screen2); + break; + } + case 3: + { + blitAt(CGI->curh->spell->ourImages[CGI->curh->number].bitmap, CGI->curh->xpos, CGI->curh->ypos, screen2); + break; + } + } + CSDL_Ext::update(screen2); +} \ No newline at end of file diff --git a/CScreenHandler.h b/CScreenHandler.h new file mode 100644 index 000000000..cb1ad1e54 --- /dev/null +++ b/CScreenHandler.h @@ -0,0 +1,17 @@ +#ifndef CSCREENHANDLER_H +#define CSCREENHANDLER_H + +struct SDL_Thread; + +class CScreenHandler +{ +private: + SDL_Thread * myth; +public: + void initScreen(); + void updateScreen(); +}; + + + +#endif //CSCREENHANDLER_H \ No newline at end of file diff --git a/SDL_Extensions.cpp b/SDL_Extensions.cpp index ecfc22488..755628b5d 100644 --- a/SDL_Extensions.cpp +++ b/SDL_Extensions.cpp @@ -449,7 +449,8 @@ Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color) void CSDL_Ext::update(SDL_Surface * what) { - SDL_UpdateRect(what, 0, 0, what->w, what->h); + if(what) + SDL_UpdateRect(what, 0, 0, what->w, what->h); } void CSDL_Ext::blueToPlayers(SDL_Surface * sur, int player)