From 823e1e39388ef2c3b65e73ad538a3bd362d98954 Mon Sep 17 00:00:00 2001 From: stephanr <> Date: Thu, 5 Jul 2001 23:48:28 +0000 Subject: [PATCH] Let sprite and rectangle cursor be handled independently from other sources --- Rules.make | 269 +++------------- src/include/cursor.h | 21 +- src/include/video.h | 2 + src/stratagus/mainloop.cpp | 73 ++--- src/ui/menus.cpp | 15 +- src/video/cursor.cpp | 633 ++++++++++++++++++++----------------- src/video/graphic.cpp | 52 +-- src/video/intern_video.h | 123 +++++++ src/video/linedraw.cpp | 43 +-- src/video/video.cpp | 3 +- 10 files changed, 570 insertions(+), 664 deletions(-) create mode 100644 src/video/intern_video.h diff --git a/Rules.make b/Rules.make index 6110e261d..14f0e363c 100644 --- a/Rules.make +++ b/Rules.make @@ -1,6 +1,6 @@ ## ___________ _________ _____ __ ## \_ _____/______ ____ ____ \_ ___ \____________ _/ ____\/ |_ -## | __) \_ __ \_/ __ \_/ __ \/ \ \/\_ __ \__ \\ __\\ __\ +## | __) \_ __ \_/ __ \_/ __ \/ \ \/\_ __ \__ \ __\ __\ ## | \ | | \/\ ___/\ ___/\ \____| | \// __ \| | | | ## \___ / |__| \___ >\___ >\______ /|__| (____ /__| |__| ## \/ \/ \/ \/ \/ @@ -8,241 +8,70 @@ ## T H E W A R B E G I N S ## FreeCraft - A free fantasy real time strategy game engine ## -## Rules.make - Make RULES (GNU MAKE) (included from Makefile). -## -## (c) Copyright 1998-2001 by Lutz Sammer -## -## FreeCraft 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 2 of the License, -## or (at your option) any later version. -## -## FreeCraft 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. -## -## $Id$ -## -############################################################################ -# Configurable: -# Choose what you want to include and the correct -# version. Minimal is now the default. -############################################################################ - -#------------------------------------------------------------------------------ -# Uncomment next to add threaded sound support -# You should have a thread safe X11 (libc6 or glibc) -# Any modern linux distribution are thread safe. -# Don't enable, if you use SDL sound support. - -#THREAD = -D_REENTRANT -DUSE_THREAD -#THREADLIB = -lpthread - -#------------------------------------------------------------------------------ -# Video driver part -#------------------------------------------------------------------------------ - -#------------------------------------------------------------------------------ -# SDL - Simple DirectMedia Layer configuration (any >=1.0.0) - -SDL_CFLAGS = $(shell sdl-config --cflags) -SDLLIB = $(shell sdl-config --static-libs) -#SDLLIB = $(shell sdl-config --libs) - -# Without SDL Sound (only not win32) -#SDL = -DUSE_SDL $(SDL_CFLAGS) -# With SDL Sound -SDL = -DUSE_SDL -DUSE_SDLA $(SDL_CFLAGS) - -#------------------------------------------------------------------------------ -# Uncomment the next for the normal X11 support. - -VIDEO = -DUSE_X11 -VIDEOLIB = -lXext -lX11 -ldl - -#------------------------------------------------------------------------------ -# Uncomment th next to get svgalib support. - -#VIDEO = -DUSE_SVGALIB -#VIDEOLIB = -lvga -lm -ldl - -#------------------------------------------------------------------------------ -# Uncomment one of the next for the SDL support. - -# Uncomment the next for the generic SDL support. - -#VIDEO = $(SDL) -#VIDEOLIB = $(SDLLIB) - -# Uncomment the next for the SDL X11/SVGALIB support. -# (sdl-config --static-libs didn't work correct.) - -VIDEO = $(SDL) -VIDEOLIB = $(SDLLIB) -lXext -lX11 -lXxf86dga -lXxf86vm -lvga -lvgagl -ldl -lesd -lm -lslang -lgpm - -# Uncomment the next for the win32/cygwin support. (not working?) - -#VIDEO = -DUSE_WIN32 $(SDL) -#VIDEOLIB = $(SDLLIB) - -# Uncomment the next for the win32/mingw32 support. - -#VIDEO = -DUSE_WIN32 $(SDL) -#VIDEOLIB = $(SDLLIB) -lwsock32 -Wl,--stack,33554432 - -# Uncomment the next for the BeOS SDL support. - -#VIDEO = -DUSE_BEOS $(SDL) -#VIDEOLIB = $(SDLLIB) - -#------------------------------------------------------------------------------ -# Sound driver part -#------------------------------------------------------------------------------ - -# See above the USE_SDLA option. - -# Comment next if you want to remove sound support. - -DSOUND = -DWITH_SOUND - -#------------------------------------------------------------------------------ -# File I/O part -#------------------------------------------------------------------------------ - -# Choose which compress you like -# The win32 port didn't support BZ2LIB - -# None -#ZDEFS = -#ZLIBS = -# GZ compression -ZDEFS = -DUSE_ZLIB -ZLIBS = -lz -# BZ2 compression -#ZDEFS = -DUSE_BZ2LIB -#ZLIBS = -lbz2 -# GZ + BZ2 compression -ZDEFS = -DUSE_ZLIB -DUSE_BZ2LIB -ZLIBS = -lz -lbz2 - -#------------------------------------------------------------------------------ - -# May be required on some distributions for libpng and libz! -# extra linker flags and include directory -# -L/usr/lib - -XLDFLAGS = -L/usr/X11R6/lib -L/usr/local/lib \ - -L$(TOPDIR)/libpng-1.0.5 -L$(TOPDIR)/zlib-1.1.3 -XIFLAGS = -I/usr/X11R6/include -I/usr/local/include \ - -I$(TOPDIR)/libpng-1.0.5 -I$(TOPDIR)/zlib-1.1.3 - -#------------------------------------------------------------------------------ -# Support for SIOD (scheme interpreter) -# C C L - Craft Configuration Language - -CCL = -DUSE_CCL -CCLLIB = -lm - -#------------------------------------------------------------------------------ - -# Uncomment next to profile -#PROFILE= -pg - -# Compile Version -VERSION= '-DVERSION="1.17pre1-build14"' - -############################################################################ -# below this, nothing should be changed! - -# Libraries needed to build tools -TOOLLIBS=$(XLDFLAGS) -lpng -lz -lm $(THREADLIB) - -# Libraries needed to build freecraft -CLONELIBS=$(XLDFLAGS) -lpng -lz -lm \ - $(THREADLIB) $(CCLLIB) $(VIDEOLIB) $(ZLIBS) - -DISTLIST=$(TOPDIR)/distlist -TAGS=$(TOPDIR)/src/tags - -# LINUX -OUTFILE=$(TOPDIR)/freecraft -ARCH=linux -OE=o -EXE= - -# WIN32 -#OUTFILE=$(TOPDIR)/freecraft$(EXE) -#ARCH=win32 -#OE=o -#EXE=.exe - -## architecture-dependant objects -#ARCHOBJS=stdmman.$(OE) svgalib.$(OE) unix_lib.$(OE) bitm_lnx.$(OE) - -## include flags -IFLAGS= -I$(TOPDIR)/src/include $(XIFLAGS) -## define flags -DEBUG= -DDEBUG -DREFS_DEBUG # -DFLAG_DEBUG -## -## There are some still not well tested code parts or branches. -## UNITS_ON_MAP: Faster lookup of units -## NEW_MAPDRAW: Stephans new map draw code -## NEW_AI: New better improved AI code -## This aren't working: -## NEW_FOW: New fog of war code, should work correct -## NEW_SHIPS: New correct ship movement. -## NEW_NETMENUS: Include new network menues. -DFLAGS= $(THREAD) $(CCL) $(VERSION) $(VIDEO) $(ZDEFS) $(DSOUND) $(DEBUG) \ - -DHAVE_EXPANSION -DUNIT_ON_MAP -DNEW_AI -D_NEW_NETMENUS -DBPP8_IRGB # -DNEW_MAPDRAW=1 -DNEW_FOW -DNEW_SHIPS - -## choose optimise level -#CFLAGS=-g -O0 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS) -#CFLAGS=-g -O1 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS) -CFLAGS=-g -O2 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS) -#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -Wall -Werror $(IFLAGS) $(DFLAGS) -#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -Wall $(IFLAGS) $(DFLAGS) -#CFLAGS=-g -O6 -pipe -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS) -#-- Production -#CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS) -#CFLAGS=-O6 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS) -static - -# GCC 3.0 -#CFLAGS=-g -O3 $(PROFILE) -pipe -Wcast-align -W -Wredundant-decls -Wno-sign-compare -Wall -Wno-comment $(IFLAGS) $(DFLAGS) -#CC=gcc-3.0 - -CC=cc -#CC=gcc272 +# Compile commands +CC=gcc RM=rm -f MAKE=make -# TAGS 5.0 -CTAGSFLAGS=--c-types=defmpstuvx -a -f -#CTAGSFLAGS=-i defmpstuvFS -a -f -#CTAGSFLAGS=-i defptvS -a -f +# Use SIOD support +CCL = -DUSE_CCL +CCLLIB = -lm -# -# Locks versions with symbolic name -# +# Video support +VIDEO = -DUSE_X11 +VIDEOLIB = -lXext -lX11 -ldl + +# Sound support +DSOUND = -DWITH_SOUND + +# Compression support +ZDEFS = -DUSE_ZLIB -DUSE_BZ2LIB +ZLIBS = -lz -lbz2 + +XLDFLAGS = -L/usr/X11R6/lib -L/usr/local/lib +XIFLAGS = -I/usr/X11R6/include -I/usr/local/include + +##################################################################### +# Don't change anything below here unless you know what you're doing! + +VERSION= '-DVERSION="1.17pre1-build14"' +PROFILE= + +TOOLLIBS=$(XLDFLAGS) -lpng -lz -lm $(THREADLIB) +CLONELIBS=$(XLDFLAGS) -lpng -lz -lm \ + $(THREADLIB) $(CCLLIB) $(VIDEOLIB) $(ZLIBS) +DISTLIST=$(TOPDIR)/distlist +TAGS=$(TOPDIR)/src/tags + +# Linux +EXE= +OUTFILE=$(TOPDIR)/freecraft +ARCH=linux +OE=o + +#ARCHOBJS=stdmman.$(OE) svgalib.$(OE) unix_lib.$(OE) bitm_lnx.$(OE) +IFLAGS= -I$(TOPDIR)/src/include $(XIFLAGS) +DFLAGS= $(THREAD) $(CCL) $(VERSION) \ + $(VIDEO) $(ZDEFS) $(DSOUND) \ + $(DEBUG) +CFLAGS=-O2 -pipe -fomit-frame-pointer -fconserve-space -fexpensive-optimizations -ffast-math $(IFLAGS) $(DFLAGS) -DUNIT_ON_MAP -DNEW_AI +CFLAGS=-g -pipe -fconserve-space $(IFLAGS) $(DFLAGS) -DUNIT_ON_MAP -DNEW_AI +CTAGSFLAGS=-i defptvS -a -f + +# Locks versions with a symbolic name LOCKVER= rcs -q -n$(NAME) %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ @ar cru $(TOPDIR)/src/libclone.a $@ -#------------ -# Source code documentation -# +# Source code documentation DOXYGEN= doxygen DOCIFY= docify DOCPP= doc++ -# Still didn't work -#DOCIFY= /root/doc++-3.4.2/src/docify -#DOCPP= /root/doc++-3.4.2/src/doc++ %.doc: %.c @$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-c.doc 2>/dev/null - %.doc: %.h @$(TOPDIR)/tools/aledoc $< | $(DOCIFY) > $*-h.doc 2>/dev/null diff --git a/src/include/cursor.h b/src/include/cursor.h index eacb49b9e..d05fbd978 100644 --- a/src/include/cursor.h +++ b/src/include/cursor.h @@ -168,11 +168,6 @@ extern int CursorY; /// cursor position on screen Y extern int CursorStartX; /// rectangle started on screen X extern int CursorStartY; /// rectangle started on screen Y -extern int OldCursorX; /// saved cursor position on screen X -extern int OldCursorY; /// saved cursor position on screen Y -extern int OldCursorW; /// saved cursor width in pixel -extern int OldCursorH; /// saved cursor height in pixel - /*---------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------*/ @@ -183,20 +178,14 @@ extern void LoadCursors(const char* racename); /// Cursor-type by identifier extern CursorType* CursorTypeByIdent(const char* ident); - /// Draw cursor on screen in position x,y -extern void DrawCursor(const CursorType* type,int x,int y,int frame); - - /// Destroy the cursor background (for menu use!) -extern void DestroyCursorBackground(void); - - /// Hide the cursor -extern void HideCursor(void); - /// Draw any cursor extern void DrawAnyCursor(void); - /// Hide any cursor -extern int HideAnyCursor(void); +extern void HideAnyCursor(void); + /// Invalidate given area and check if cursor won't need any +extern void InvalidateAreaAndCheckCursor( int x, int y, int w, int h ); + /// Invalidate (remaining) cursor areas +extern void InvalidateCursorAreas(void); /// Initialize the cursor module extern void InitCursors(void); diff --git a/src/include/video.h b/src/include/video.h index 58d01e26d..016266b8d 100644 --- a/src/include/video.h +++ b/src/include/video.h @@ -985,6 +985,7 @@ extern void VideoDrawTransRectangleClip(SysColors color,int x,int y /// Does ColorCycling.. extern void (*ColorCycle)(void); + /*---------------------------------------------------------------------------- -- Macros ----------------------------------------------------------------------------*/ @@ -1054,6 +1055,7 @@ extern void (*ColorCycle)(void); #define VideoSaveFree(o) \ do { if( (o) ) ((o)->Type->Free)((o)); } while( 0 ) + /*---------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------*/ diff --git a/src/stratagus/mainloop.cpp b/src/stratagus/mainloop.cpp index eff6bb337..25884c4cf 100644 --- a/src/stratagus/mainloop.cpp +++ b/src/stratagus/mainloop.cpp @@ -203,14 +203,13 @@ global void DebugTestDisplay(void) */ global void UpdateDisplay(void) { - int update_old_cursor; + if (!MustRedraw) { + return; + } VideoLockScreen(); // prepare video write - if (MustRedraw) { - update_old_cursor=HideAnyCursor(); // remove cursor - } else { - update_old_cursor = 0; - } + + HideAnyCursor(); // remove cursor (when available) if( MustRedraw&RedrawMap ) { if (InterfaceState == IfaceStateNormal) { @@ -311,84 +310,72 @@ global void UpdateDisplay(void) DrawMenu(CurrentMenu); } - // FIXME: this could be written better, less drawing - if( update_old_cursor && MustRedraw!=-1 ) { - // Draw restored area only if not same. - if( OldCursorX!=(CursorX-GameCursor->HotX) - || OldCursorY!=(CursorY-GameCursor->HotY) - || OldCursorW!=VideoGraphicWidth(GameCursor->Sprite) - || OldCursorH!=VideoGraphicHeight(GameCursor->Sprite) ) { - InvalidateArea(OldCursorX,OldCursorY,OldCursorW,OldCursorH); - } - } - - if (!MustRedraw) { - VideoUnlockScreen(); // End write access - return; - } - DrawAnyCursor(); + VideoUnlockScreen(); // End write access // // Update changes to X11. // if( MustRedraw==-1 ) { - Invalidate(); + // refresh entire screen, so no further invalidate needed + InvalidateAreaAndCheckCursor(0,0,VideoWidth,VideoHeight); } else { if( MustRedraw&RedrawMap ) { // FIXME: split into small parts see RedrawTile and RedrawRow - InvalidateArea(TheUI.MapX,TheUI.MapY + InvalidateAreaAndCheckCursor( + TheUI.MapX,TheUI.MapY ,TheUI.MapEndX-TheUI.MapX+1,TheUI.MapEndY-TheUI.MapY+1); } if( (MustRedraw&RedrawFiller1) && TheUI.Filler1.Graphic ) { - InvalidateArea(TheUI.Filler1X,TheUI.Filler1Y + InvalidateAreaAndCheckCursor( + TheUI.Filler1X,TheUI.Filler1Y ,TheUI.Filler1.Graphic->Width ,TheUI.Filler1.Graphic->Height); } - if( MustRedraw&RedrawMenuButton ) { - InvalidateArea(TheUI.MenuButtonX,TheUI.MenuButtonY + if(MustRedraw&RedrawMenuButton ) { + InvalidateAreaAndCheckCursor( + TheUI.MenuButtonX,TheUI.MenuButtonY ,TheUI.MenuButton.Graphic->Width ,TheUI.MenuButton.Graphic->Height); } if( MustRedraw&RedrawMinimapBorder ) { - InvalidateArea(TheUI.MinimapX,TheUI.MinimapY + InvalidateAreaAndCheckCursor( + TheUI.MinimapX,TheUI.MinimapY ,TheUI.Minimap.Graphic->Width,TheUI.Minimap.Graphic->Height); } else if( (MustRedraw&RedrawMinimap) || (MustRedraw&RedrawMinimapCursor) ) { // FIXME: Redraws too much of the minimap - InvalidateArea(TheUI.MinimapX+24,TheUI.MinimapY+2 + InvalidateAreaAndCheckCursor( + TheUI.MinimapX+24,TheUI.MinimapY+2 ,MINIMAP_W,MINIMAP_H); } if( MustRedraw&RedrawInfoPanel ) { - InvalidateArea(TheUI.InfoPanelX,TheUI.InfoPanelY + InvalidateAreaAndCheckCursor( + TheUI.InfoPanelX,TheUI.InfoPanelY ,TheUI.InfoPanelW,TheUI.InfoPanelH); } if( MustRedraw&RedrawButtonPanel ) { - InvalidateArea(TheUI.ButtonPanelX,TheUI.ButtonPanelY + InvalidateAreaAndCheckCursor( + TheUI.ButtonPanelX,TheUI.ButtonPanelY ,TheUI.ButtonPanel.Graphic->Width ,TheUI.ButtonPanel.Graphic->Height); } if( MustRedraw&RedrawResources ) { - InvalidateArea(TheUI.ResourceX,TheUI.ResourceY + InvalidateAreaAndCheckCursor( + TheUI.ResourceX,TheUI.ResourceY ,TheUI.Resource.Graphic->Width ,TheUI.Resource.Graphic->Height); } if( MustRedraw&RedrawStatusLine || MustRedraw&RedrawCosts ) { - InvalidateArea(TheUI.StatusLineX,TheUI.StatusLineY + InvalidateAreaAndCheckCursor( + TheUI.StatusLineX,TheUI.StatusLineY ,TheUI.StatusLine.Graphic->Width ,TheUI.StatusLine.Graphic->Height); } - /* if (MustRedraw) */ { - // FIXME: JOHNS: That didn't work: if (MustRedraw&RedrawCursor) - DebugLevel3Fn("%d,%d,%d,%d\n",CursorX-GameCursor->HotX - ,CursorY-GameCursor->HotY - ,VideoGraphicWidth(GameCursor->Sprite) - ,VideoGraphicHeight(GameCursor->Sprite)); - InvalidateArea(CursorX-GameCursor->HotX,CursorY-GameCursor->HotY - ,VideoGraphicWidth(GameCursor->Sprite) - ,VideoGraphicHeight(GameCursor->Sprite)); - } + + // And now as very last.. checking if the cursor needs a refresh + InvalidateCursorAreas(); } } diff --git a/src/ui/menus.cpp b/src/ui/menus.cpp index 7cc0eaba3..33de1aa8b 100644 --- a/src/ui/menus.cpp +++ b/src/ui/menus.cpp @@ -1160,8 +1160,9 @@ global void DrawMenu(int MenuId) */ local void StartMenusSetBackground(Menuitem *mi __attribute__((unused))) { - HideCursor(); - DestroyCursorBackground(); + //Doesn't seem to be needed + //HideAnyCursor(); + // FIXME: make this configurable from CCL. DisplayPicture("graphics/ui/Menu background without title.png"); } @@ -1256,7 +1257,6 @@ local void MultiScenSelectMenu(void) local void SinglePlayerGameMenu(void) { - DestroyCursorBackground(); GuiGameStarted = 0; ProcessMenu(MENU_CUSTOM_GAME_SETUP, 1); if (GuiGameStarted) { @@ -1312,7 +1312,6 @@ local void JoinNetGameMenu(void) EnterServerIPMenuItems[1].d.input.maxch = 24; EnterServerIPMenuItems[2].flags |= MenuButtonDisabled; ProcessMenu(MENU_NET_ENTER_SERVER_IP, 1); - DestroyCursorBackground(); StartMenusSetBackground(NULL); if (EnterServerIPMenuItems[1].d.input.nch == 0) { return; @@ -1330,7 +1329,6 @@ local void JoinNetGameMenu(void) local void NetConnectingCancel(void) { - DestroyCursorBackground(); StartMenusSetBackground(NULL); NetworkExitClientConnect(); NetLocalState = ccs_unreachable; // Trigger TerminateNetConnect() to call us again and end the menu @@ -1345,7 +1343,6 @@ local void TerminateNetConnect(void) } DebugLevel1Fn("NetLocalState %d\n", NetLocalState); NetConnectRunning = 2; - DestroyCursorBackground(); GuiGameStarted = 0; ProcessMenu(MENU_NET_MULTI_CLIENT, 1); if (GuiGameStarted) { @@ -1357,7 +1354,6 @@ local void TerminateNetConnect(void) local void CreateNetGameMenu(void) { - DestroyCursorBackground(); GuiGameStarted = 0; ProcessMenu(MENU_NET_MULTI_SETUP, 1); if (GuiGameStarted) { @@ -1377,7 +1373,6 @@ local void MultiPlayerGameMenu(void) EnterNameMenuItems[1].d.input.maxch = 15; EnterNameMenuItems[2].flags &= ~MenuButtonDisabled; ProcessMenu(MENU_ENTER_NAME, 1); - DestroyCursorBackground(); StartMenusSetBackground(NULL); if (EnterNameMenuItems[1].d.input.nch == 0) { return; @@ -1735,7 +1730,6 @@ local void ScenSelectCancel(void) local void GameCancel(void) { - DestroyCursorBackground(); StartMenusSetBackground(NULL); FreeMapInfo(ScenSelectPudInfo); ScenSelectPudInfo = NULL; @@ -2750,8 +2744,7 @@ global void ProcessMenu(int MenuId, int Loop) } InterfaceState = IfaceStateMenu; - HideCursor(); - DestroyCursorBackground(); + HideAnyCursor(); MustRedraw |= RedrawCursor; CursorState = CursorStatePoint; GameCursor = TheUI.Point.Cursor; diff --git a/src/video/cursor.cpp b/src/video/cursor.cpp index 1ef266b0c..42ad282bb 100644 --- a/src/video/cursor.cpp +++ b/src/video/cursor.cpp @@ -45,10 +45,17 @@ #include "interface.h" #include "ui.h" +#include "intern_video.h" + /*---------------------------------------------------------------------------- -- Variables ----------------------------------------------------------------------------*/ +/** +** Number of bytes needed for current video-mode +*/ +local int memsize; + /** ** Cursor-type type definition */ @@ -64,31 +71,82 @@ global CursorType* Cursors; global CursorStates CursorState;/// current cursor state (point,...) global int CursorAction; /// action for selection global int CursorValue; /// value for CursorAction (spell type f.e.) -global UnitType* CursorBuilding;/// building cursor -global CursorType* GameCursor; /// current shown cursor-type + //Event changed mouse position, can alter at any moment global int CursorX; /// cursor position on screen X global int CursorY; /// cursor position on screen Y + global int CursorStartX; /// rectangle started on screen X global int CursorStartY; /// rectangle started on screen Y -global int OldCursorX; /// saved cursor position on screen X -global int OldCursorY; /// saved cursor position on screen Y -global int OldCursorW; /// saved cursor width in pixel -global int OldCursorH; /// saved cursor height in pixel -local int OldCursorSize; /// size of saved cursor image -local void* OldCursorImage; /// background saved behind cursor -local int OldCursorRectangleX; /// saved cursor position on screen X -local int OldCursorRectangleY; /// saved cursor position on screen Y -local int OldCursorRectangleW; /// saved cursor width in pixel -local int OldCursorRectangleH; /// saved cursor height in pixel -local void* OldCursorRectangle; /// background saved behind rectangle +/*--- DRAW BUILDING CURSOR ------------------------------------------------*/ +local int BuildingCursor=0; /// Flag (0/1): last cursor was building + +// area of tiles covered by building cursor (SX,SY;EX,EY) +local int BuildingCursorSX; /// FIXME: docu +local int BuildingCursorSY; /// FIXME: docu +local int BuildingCursorEX; /// FIXME: docu +local int BuildingCursorEY; /// FIXME: docu + +global UnitType* CursorBuilding;/// building cursor + + +/*--- DRAW SPRITE CURSOR ---------------------------------------------------*/ + // Saved area after draw cursor, needed later to hide it again + // (OldCursorW!=0 denotes it's defined) +local int OldCursorInvalidate=0;/// flag (0/1): if cursor need invalidate +local int OldCursorX; /// saved cursor position on screen X +local int OldCursorY; /// saved cursor position on screen Y +local int OldCursorW=0; /// saved cursor width in pixel +local int OldCursorH; /// saved cursor height in pixel +global CursorType* GameCursor; /// current shown cursor-type + + // Area which is already hidden, but needed for invalidate + // (HiddenCursorW!=0 denotes it's defined) +local int HiddenCursorX; /// saved cursor position on screen X +local int HiddenCursorY; /// saved cursor position on screen Y +local int HiddenCursorW=0; /// saved cursor width in pixel +local int HiddenCursorH; /// saved cursor height in pixel + + /// Memory re-use, so can be defined although no save present! +local unsigned int OldCursorSize; /// size of saved cursor image +local void* OldCursorImage; /// background saved behind cursor /// Function pointer: Save background behind cursor -local void (*SaveCursorBackground)(int,int,int,int); +/** +** Function pointer: Save 2D image behind sprite cursor +** +** @param x Screen X pixels coordinate for left-top corner. +** @param y Screen Y pixels coordinate for left-top corner. +** @param w Width in pixels for image starting at left-top. +** @param h Height in pixels for image starting at left-top. +** +** @note the complete image should be in Screen (no clipping) and +** non-empty +** ( x>=0,y>=0,w>0,h>0,(x+w-1)<=VideoWidth,(y+h-1)<=VideoHeight ) +*/ +local void (*SaveCursorBackground)(int x,int y,int w,int h); /// Function pointer: Load background behind cursor -local void (*LoadCursorBackground)(int,int,int,int); +local void (*LoadCursorBackground)(int x,int y,int w,int h); + + +/*--- DRAW RECTANGLE CURSOR ------------------------------------------------*/ + // Saved area after draw rectangle, needed later to hide it again + // (OldCursorRectangleW!=0 denotes it's defined) +local int OldCursorRectangleInvalidate=0;/// flag (0/1): ..need invalidate +local int OldCursorRectangleX; /// saved cursor position on screen X +local int OldCursorRectangleY; /// saved cursor position on screen Y +local int OldCursorRectangleW=0; /// saved cursor width in pixel +local int OldCursorRectangleH; /// saved cursor height in pixel +local void* OldCursorRectangle; /// background saved behind rectangle + + // Area which is already hidden, but needed for invalidate + // (HiddenCursorRectangleW!=0 denotes it's defined) +local int HiddenCursorRectangleX; /// saved cursor position on screen X +local int HiddenCursorRectangleY; /// saved cursor position on screen Y +local int HiddenCursorRectangleW=0; /// saved cursor width in pixel +local int HiddenCursorRectangleH; /// saved cursor height in pixel /** ** Function pointer: Save rectangle behind cursor @@ -119,7 +177,6 @@ local void (*LoadCursorRectangle)(int x,int y,int w,int h); /*---------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------*/ - /** ** Load all cursor sprites. ** @@ -188,11 +245,11 @@ global CursorType* CursorTypeByIdent(const char* ident) } /*---------------------------------------------------------------------------- --- Internal Functions +-- DRAW RECTANGLE CURSOR ----------------------------------------------------------------------------*/ - /** -** FIXME: docu missing, better use an inline function. +** Puts stored 'image' from SAVECURSORRECTANGLE back on the screen. +** Note w and h are both > 0 ** ** FIXME: this kind of macros are hard to single step with gdb. ** FIXME: inline functions should have the same speed and are debugable. @@ -216,7 +273,9 @@ global CursorType* CursorTypeByIdent(const char* ident) } /** -** FIXME: docu missing, better use an inline function. +** Saves 'image' of screen overlapped by rectangle cursor, to be able to +** restore it later using LOADCURSORRECTANGLE. +** Note w and h > 0 ** ** FIXME: this kind of macros are hard to single step with gdb. ** FIXME: inline functions should have the same speed and are debugable. @@ -244,9 +303,7 @@ global CursorType* CursorTypeByIdent(const char* ident) */ local void LoadCursorRectangle8(int x,int y,int w,int h) { - if( w && h ) { LOADCURSORRECTANGLE(VideoMemory8,VMemType8,x,y,w,h); - } } /** Restore cursor rectangle for 16bpp frame buffer. @@ -255,9 +312,7 @@ local void LoadCursorRectangle8(int x,int y,int w,int h) */ local void LoadCursorRectangle16(int x,int y,int w,int h) { - if( w && h ) { LOADCURSORRECTANGLE(VideoMemory16,VMemType16,x,y,w,h); - } } /** Restore cursor rectangle for 24bpp frame buffer. @@ -266,9 +321,7 @@ local void LoadCursorRectangle16(int x,int y,int w,int h) */ local void LoadCursorRectangle24(int x,int y,int w,int h) { - if( w && h ) { LOADCURSORRECTANGLE(VideoMemory24,VMemType24,x,y,w,h); - } } /** Restore cursor rectangle for 32bpp frame buffer. @@ -277,9 +330,7 @@ local void LoadCursorRectangle24(int x,int y,int w,int h) */ local void LoadCursorRectangle32(int x,int y,int w,int h) { - if( w && h ) { LOADCURSORRECTANGLE(VideoMemory32,VMemType32,x,y,w,h); - } } /** Save cursor rectangle for 8bpp frame buffer. @@ -288,9 +339,7 @@ local void LoadCursorRectangle32(int x,int y,int w,int h) */ local void SaveCursorRectangle8(int x,int y,int w,int h) { - if( w && h ) { SAVECURSORRECTANGLE(VideoMemory8,VMemType8,x,y,w,h); - } } /** Save cursor rectangle for 16bpp frame buffer. @@ -299,9 +348,7 @@ local void SaveCursorRectangle8(int x,int y,int w,int h) */ local void SaveCursorRectangle16(int x,int y,int w,int h) { - if( w && h ) { SAVECURSORRECTANGLE(VideoMemory16,VMemType16,x,y,w,h); - } } /** Save cursor rectangle for 24bpp frame buffer. @@ -310,9 +357,7 @@ local void SaveCursorRectangle16(int x,int y,int w,int h) */ local void SaveCursorRectangle24(int x,int y,int w,int h) { - if( w && h ) { SAVECURSORRECTANGLE(VideoMemory24,VMemType24,x,y,w,h); - } } /** Save cursor rectangle for 32bpp frame buffer. @@ -321,11 +366,60 @@ local void SaveCursorRectangle24(int x,int y,int w,int h) */ local void SaveCursorRectangle32(int x,int y,int w,int h) { - if( w && h ) { SAVECURSORRECTANGLE(VideoMemory32,VMemType32,x,y,w,h); +} + +/** +** Draw rectangle cursor when visible, defined by +** OldCursorRectangleW (!=0),.. +** Pre: for this to work OldCursorRectangleW should be 0 upfront +*/ +local void DrawVisibleRectangleCursor(int x,int y,int x1,int y1) +{ + int w; + int h; + + // + // Clip to map window. + // FIXME: should re-use CLIP_RECTANGLE in some way from linedraw.c ? + // + if( x1<TheUI.MapX ) { + x1=TheUI.MapX; + } else if( x1>TheUI.MapEndX ) { + x1=TheUI.MapEndX; + } + if( y1<TheUI.MapY ) { + y1=TheUI.MapY; + } else if( y1>TheUI.MapEndY ) { + y1=TheUI.MapEndY; + } + + if( x>x1 ) { + x=x1; + w=CursorStartX-x+1; + } else { + w=x1-x+1; + } + if( y>y1 ) { + y=y1; + h=CursorStartY-y+1; + } else { + h=y1-y+1; + } + + if ( w && h ) + { + SaveCursorRectangle(OldCursorRectangleX=x,OldCursorRectangleY=y, + OldCursorRectangleW=w,OldCursorRectangleH=h); + VideoDrawRectangleClip(ColorGreen,x,y,w,h); + OldCursorRectangleInvalidate=1; } } + +/*---------------------------------------------------------------------------- +-- DRAW SPRITE CURSOR +----------------------------------------------------------------------------*/ /** ** Restore cursor background for 8bpp frame buffer. ** @@ -424,19 +518,9 @@ local void LoadCursorBackground32(int x,int y,int w,int h) */ local void SaveCursorBackground8(int x,int y,int w,int h) { - int i; VMemType8* dp; VMemType8* sp; - i=w*h*sizeof(VMemType8); - if( OldCursorSize<i ) { - if( OldCursorImage ) { - OldCursorImage=realloc(OldCursorImage,i); - } else { - OldCursorImage=malloc(i); - } - OldCursorSize=i; - } dp=OldCursorImage; sp=VideoMemory8+y*VideoWidth+x; while( h-- ) { @@ -456,19 +540,9 @@ local void SaveCursorBackground8(int x,int y,int w,int h) */ local void SaveCursorBackground16(int x,int y,int w,int h) { - int i; VMemType16* dp; const VMemType16* sp; - i=w*h*sizeof(VMemType16); - if( OldCursorSize<i ) { - if( OldCursorImage ) { - OldCursorImage=realloc(OldCursorImage,i); - } else { - OldCursorImage=malloc(i); - } - OldCursorSize=i; - } dp=OldCursorImage; sp=VideoMemory16+y*VideoWidth+x; while( h-- ) { @@ -488,19 +562,9 @@ local void SaveCursorBackground16(int x,int y,int w,int h) */ local void SaveCursorBackground24(int x,int y,int w,int h) { - int i; VMemType24* dp; const VMemType24* sp; - i=w*h*sizeof(VMemType24); - if( OldCursorSize<i ) { - if( OldCursorImage ) { - OldCursorImage=realloc(OldCursorImage,i); - } else { - OldCursorImage=malloc(i); - } - OldCursorSize=i; - } dp=OldCursorImage; sp=VideoMemory24+y*VideoWidth+x; while( h-- ) { @@ -520,19 +584,9 @@ local void SaveCursorBackground24(int x,int y,int w,int h) */ local void SaveCursorBackground32(int x,int y,int w,int h) { - int i; VMemType32* dp; const VMemType32* sp; - i=w*h*sizeof(VMemType32); - if( OldCursorSize<i ) { - if( OldCursorImage ) { - OldCursorImage=realloc(OldCursorImage,i); - } else { - OldCursorImage=malloc(i); - } - OldCursorSize=i; - } dp=OldCursorImage; sp=VideoMemory32+y*VideoWidth+x; while( h-- ) { @@ -542,49 +596,10 @@ local void SaveCursorBackground32(int x,int y,int w,int h) } } -/** -** Save image behind cursor. -*/ -local void SaveCursor(void) -{ - int w; - int h; - int x; - int y; - - x=OldCursorX; - w=OldCursorW; - if( x<0 ) { - w-=x; - x=0; - } - if( w>VideoWidth-x) { // normalize width - w=VideoWidth-x; - } - if( !w ) { - return; - } - - y=OldCursorY; - h=OldCursorH; - if( y<0 ) { - w-=y; - y=0; - } - if( h>VideoHeight-y ) { // normalize height - h=VideoHeight-y; - } - if( !h ) { - return; - } - - SaveCursorBackground(x,y,w,h); -} - /** ** Destroy image behind cursor. */ -global void DestroyCursorBackground(void) +local void DestroyCursorBackground(void) { if (OldCursorImage) { free(OldCursorImage); @@ -594,94 +609,51 @@ global void DestroyCursorBackground(void) } /** -** Restore image behind cursor. -*/ -local void RestoreCursor(void) -{ - int w; - int h; - int x; - int y; - - if( !OldCursorImage ) { // no cursor saved - return; - } - - // FIXME: I should better store the correct values on save. - x=OldCursorX; - w=OldCursorW; - if( x<0 ) { - w-=x; - x=0; - } - if( w>VideoWidth-x) { // normalize width - w=VideoWidth-x; - } - if( !w ) { - return; - } - - y=OldCursorY; - h=OldCursorH; - if( y<0 ) { - w-=y; - y=0; - } - if( h>VideoHeight-y ) { // normalize height - h=VideoHeight-y; - } - if( !h ) { - return; - } - - LoadCursorBackground(x,y,w,h); -} - -/** -** Draw cursor. +** Draw (sprite) cursor when visible, defined by +** OldCursorW (!=0),.. +** Pre: for this to work OldCursorW should be 0 upfront ** ** @param type Cursor-type of the cursor to draw. ** @param x Screen x pixel position. ** @param y Screen y pixel position. ** @param frame Animation frame # of the cursor. */ -global void DrawCursor(const CursorType* type,int x,int y,int frame) +local void DrawCursor(const CursorType* type,int x,int y,int frame) { + unsigned int size,w,h; + int spritex,spritey; + // // Save cursor position and size, for faster cursor redraw. // - OldCursorX=x-=type->HotX; - OldCursorY=y-=type->HotY; - OldCursorW=VideoGraphicWidth(type->Sprite); - OldCursorH=VideoGraphicHeight(type->Sprite); + spritex=(x-=type->HotX); + spritey=(y-=type->HotY); + w=VideoGraphicWidth(type->Sprite); + h=VideoGraphicHeight(type->Sprite); -/* FIXME: SaveCusor done before rectangle - SaveCursor(); -*/ - VideoDrawClip(type->Sprite,frame,x,y); -} + //Reserve enough memory for background of sprite (also for future calls) + size=(unsigned int)w*(unsigned int)h*memsize; + if( OldCursorSize<size ) { + if( OldCursorImage ) { + OldCursorImage=realloc(OldCursorImage,size); + } else { + OldCursorImage=malloc(size); + } + OldCursorSize=size; + } -/** -** Hide cursor. -*/ -global void HideCursor(void) -{ - RestoreCursor(); + //Save (seen) area behind sprite + CLIP_RECTANGLE(x,y,w,h); + SaveCursorBackground(OldCursorX=x,OldCursorY=y,OldCursorW=w,OldCursorH=h); + + //Draw sprite (using its own clipping) FIXME: prevent clipping twice + VideoDrawClip(type->Sprite,frame,spritex,spritey); + OldCursorInvalidate=1; } /*---------------------------------------------------------------------------- --- DRAW CURSOR +-- DRAW BUILDING CURSOR ----------------------------------------------------------------------------*/ - -local int RectangleCursor; /// Flag: last cursor was rectangle -local int BuildingCursor; /// Flag: last cursor was building - -// area of tiles covered by building cursor (SX,SY;EX,EY) -local int BuildingCursorSX; /// FIXME: docu -local int BuildingCursorSY; /// FIXME: docu -local int BuildingCursorEX; /// FIXME: docu -local int BuildingCursorEY; /// FIXME: docu - /** ** Draw cursor for selecting building position. */ @@ -787,131 +759,224 @@ local void DrawBuildingCursor(void) } } + +/*---------------------------------------------------------------------------- +-- DRAW/HIDE CURSOR (interface for the outside world) +----------------------------------------------------------------------------*/ /** -** Draw rectangle cursor. -*/ -global void DrawRectangleCursor(void) -{ - int x; - int y; - int w; - int h; - int x1; - int y1; - - // - // Clip to map window. - // - x1=CursorX; - if( x1<TheUI.MapX ) { - x1=TheUI.MapX; - } else if( x1>TheUI.MapEndX ) { - x1=TheUI.MapEndX; - } - y1=CursorY; - if( y1<TheUI.MapY ) { - y1=TheUI.MapY; - } else if( y1>TheUI.MapEndY ) { - y1=TheUI.MapEndY; - } - - x=CursorStartX; - if( x>x1 ) { - x=x1; - w=CursorStartX-x+1; - } else { - w=x1-x+1; - } - y=CursorStartY; - if( y>y1 ) { - y=y1; - h=CursorStartY-y+1; - } else { - h=y1-y+1; - } - -#ifdef NEW_MAPDRAW - SaveCursorRectangle(OldCursorRectangleX=x,OldCursorRectangleY=y, - OldCursorRectangleW=w,OldCursorRectangleH=h); - VideoDrawHLine(ColorGreen,x,y,w); - VideoDrawVLine(ColorGreen,x,y+1,--h); - VideoDrawHLine(ColorGreen,x+1,y+h,--w); - VideoDrawVLine(ColorGreen,x+w,y,h); -#else - //FIXME VideoDrawRectangleClip uses different definition for w and h - VideoDrawRectangleClip(ColorGreen,x,y,w-1,h-1); -#endif -} - -/** -** Draw the cursor +** Draw the cursor and prepare tobe restored by HideAnyCursor again. +** Note: This function can be called, without calling HideAnyCursor first, +** which means that this function should re-use/free memory of the +** last call. +** When calling multiple times, the old cursor is expected to be +** overdrawn by something else (else HideAnyCursor is needed!) +** Also the cursors are not invalidated (refresh on real screen) +** here, but this is done by InvalidateCursorAreas. +** +** FIXME: event handler should be temporary stopped while copying +** CursorX,CursorY,.. because between two copy commands another +** event can occure, which let invalid mouse position be delivered. */ global void DrawAnyCursor(void) { - RectangleCursor=BuildingCursor=0; - -/*FIXME: temporary, as SaveCursor must happen before rectangle -*/ - OldCursorX=CursorX-GameCursor->HotX; - OldCursorY=CursorY-GameCursor->HotY; - OldCursorW=VideoGraphicWidth(GameCursor->Sprite); - OldCursorH=VideoGraphicHeight(GameCursor->Sprite); - SaveCursor(); + // Disable any previous drawn cursor + OldCursorInvalidate=OldCursorW= + OldCursorRectangleInvalidate=OldCursorRectangleW= + BuildingCursor=0; // - // Selecting rectangle + // First, Selecting rectangle // if( CursorState==CursorStateRectangle && (CursorStartX!=CursorX || CursorStartY!=CursorY) ) { - DrawRectangleCursor(); - RectangleCursor=1; - } else - + DrawVisibleRectangleCursor(CursorStartX,CursorStartY,CursorX,CursorY); + } // - // Selecting position for building + // Or Selecting position for building // - if( CursorBuilding && CursorOn==CursorOnMap ) { + else if( CursorBuilding && CursorOn==CursorOnMap ) { DrawBuildingCursor(); BuildingCursor=1; } // - // Normal cursor. + // Last, Normal cursor. + // This will also save (part of) drawn rectangle cursor, but that's ok. // DrawCursor(GameCursor,CursorX,CursorY,0); } /** ** Remove old cursor from display. +** (in the opposite direction of DrawAnyCursor) +** Note: this function can be called, without calling DrawAnyCursor first, +** which means that cursors shouldn't be restored twice. +** As cursors are, like DrawAnyCursor, not invalidated here, it +** still needs to be done by InvalidateCursorAreas. */ -global int HideAnyCursor(void) +global void HideAnyCursor(void) { - if( RectangleCursor ) { - LoadCursorRectangle(OldCursorRectangleX,OldCursorRectangleY, - OldCursorRectangleW,OldCursorRectangleH); - } - if( BuildingCursor ) { - //NOTE: this will restore tiles themselves later in next video update - MarkDrawAreaMap(BuildingCursorSX,BuildingCursorSY, - BuildingCursorEX,BuildingCursorEY); + // + // First, Normal cursor (might restore part of rectangle cursor also). + // + if( OldCursorW ) { + // restore area of visible cursor + LoadCursorBackground(OldCursorX,OldCursorY,OldCursorW,OldCursorH); + + // save hidden area to be invalidated + HiddenCursorX=OldCursorX; + HiddenCursorY=OldCursorY; + HiddenCursorW=OldCursorW; + HiddenCursorH=OldCursorH; + + // Denote cursor no longer visible + OldCursorW=0; } // - // Cursor complete on map and map must be redrawn, no restore. - //StephanR: but prevented when not entire map is redrawn ;) + // Last, Selecting rectangle // -#ifndef NEW_MAPDRAW - if( OldCursorX>=TheUI.MapX - && OldCursorX+OldCursorW-1<=TheUI.MapEndX - && OldCursorY>=TheUI.MapY - && OldCursorY+OldCursorH-1<=TheUI.MapEndY - && (MustRedraw&RedrawMap) - && (InterfaceState != IfaceStateMenu) ) { - return 0; + if( OldCursorRectangleW ) { + // restore area of visible cursor + LoadCursorRectangle(OldCursorRectangleX,OldCursorRectangleY, + OldCursorRectangleW,OldCursorRectangleH); + + // save hidden area to be invalidated + HiddenCursorRectangleX=OldCursorRectangleX; + HiddenCursorRectangleY=OldCursorRectangleY; + HiddenCursorRectangleW=OldCursorRectangleW; + HiddenCursorRectangleH=OldCursorRectangleH; + + // Denote cursor no longer visible + OldCursorRectangleW=0; } -#endif - HideCursor(); - return 1; + // + // Or Selecting position for building + // + else if( BuildingCursor ) { + //NOTE: this will restore tiles themselves later in next video update + MarkDrawAreaMap(BuildingCursorSX,BuildingCursorSY, + BuildingCursorEX,BuildingCursorEY); + BuildingCursor=0; + } +} + +/** +** Let an area be invalidated, but remembering if cursor is automaticly +** invalidated with this area. +** Note: building-cursor is already invalidated by redraw-map +** +** @param x left-top x-position of area on screen +** @param y left-top y-position of area on screen +** @param w width of area on screen +** @param h height of area on screen +*/ +global void InvalidateAreaAndCheckCursor( int x, int y, int w, int h ) +{ + int dx,dy; + + //Invalidate area + InvalidateArea(x,y,w,h); + + //Now check if cursor sprite is inside it, then no need for invalidate + if ( OldCursorInvalidate ) + { + dx = OldCursorX-x; + dy = OldCursorY-y; + if ( dx >= 0 && dy >= 0 && (w-dx) >= OldCursorW && (h-dy) >= OldCursorH ) + OldCursorInvalidate = 0; + } + + //Now check if previously hidden cursor sprite is inside it.. + if ( HiddenCursorW ) + { + dx = HiddenCursorX-x; + dy = HiddenCursorY-y; + if ( dx >= 0 && dy >= 0 && + (w-dx) >= HiddenCursorW && (h-dy) >= HiddenCursorH ) + HiddenCursorW = 0; + } + + //Now check if cursor rectangle is inside it.. + if ( OldCursorRectangleInvalidate ) + { + dx = OldCursorRectangleX-x; + dy = OldCursorRectangleY-y; + if ( dx >= 0 && dy >= 0 && + (w-dx) >= OldCursorRectangleW && (h-dy) >= OldCursorRectangleH ) + OldCursorRectangleInvalidate = 0; + } + + //Now check if previously hidden cursor rectangle is inside it.. + if ( HiddenCursorRectangleW ) + { + dx = HiddenCursorRectangleX-x; + dy = HiddenCursorRectangleY-y; + if ( dx >= 0 && dy >= 0 && + (w-dx) >= HiddenCursorRectangleW && (h-dy) >= HiddenCursorRectangleH ) + HiddenCursorRectangleW = 0; + } +} + +/** +** Invalidate only the sides of a given rectangle (not its contents) +** +** @param x left-top x-position of rectangle on screen +** @param y left-top y-position of rectangle on screen +** @param w width of rectangle on screen +** @param h height of rectangle on screen +*/ +local void InvalidateRectangle(int x, int y, int w, int h) +{ + InvalidateArea(x,y,w,1); // top side + if ( --h > 0 ) + { + InvalidateArea(x,y+h,w,1); // bottom side + if ( --h > 0 ) + { + InvalidateArea(x,++y,1,h); // left side + if ( --w > 0 ) + InvalidateArea(x+w,y,1,h); // right side + } + } +} + +/** +** Let the (remaining) areas taken by the cursors, as determined by +** DrawAnyCursor and InvalidateAreaAndCheckcursor, be invalidated. +** Note: building-cursor is already invalidated by redraw-map +*/ +global void InvalidateCursorAreas(void) +{ + //Invalidate cursor sprite + if ( OldCursorInvalidate ) + { + InvalidateArea(OldCursorX,OldCursorY,OldCursorW,OldCursorH); + OldCursorInvalidate=0; + } + + //Invalidate hidden cursor sprite + if ( HiddenCursorW ) + { + InvalidateArea(HiddenCursorX,HiddenCursorY,HiddenCursorW,HiddenCursorH); + HiddenCursorW=0; + } + + //Invalidate cursor rectangle + if ( OldCursorRectangleInvalidate ) + { + InvalidateRectangle(OldCursorRectangleX,OldCursorRectangleY, + OldCursorRectangleW,OldCursorRectangleH); + OldCursorRectangleInvalidate=0; + } + + //Invalidate hidden cursor rectangle + if ( HiddenCursorRectangleW ) + { + InvalidateRectangle(HiddenCursorRectangleX,HiddenCursorRectangleY, + HiddenCursorRectangleW,HiddenCursorRectangleH); + HiddenCursorRectangleW=0; + } } /** @@ -922,8 +987,6 @@ global int HideAnyCursor(void) */ global void InitCursors(void) { - int memsize; - if( OldCursorRectangle ) { // memory of possible previous video-setting? free( OldCursorRectangle ); } diff --git a/src/video/graphic.cpp b/src/video/graphic.cpp index 829295257..f8c0ffd15 100644 --- a/src/video/graphic.cpp +++ b/src/video/graphic.cpp @@ -36,6 +36,7 @@ #include "freecraft.h" #include "video.h" #include "iolib.h" +#include "intern_video.h" /*---------------------------------------------------------------------------- -- Declarations @@ -241,49 +242,6 @@ local void VideoDrawSub8to32( } } -/** -** Clip to clipping rectangle. -** -** @param w width to display -** @param h height to display -** @param x X screen position -** @param y Y screen position -*/ -#define DO_CLIPPING(w,h,x,y) \ - do { \ - int f; \ - \ - if( x<ClipX1 ) { \ - f=ClipX1-x; \ - x=ClipX1; \ - if( w<f ) { /* outside */ \ - return; \ - } \ - w-=f; \ - } \ - if( (x+w)>ClipX2 ) { \ - if( w<ClipX2-x ) { /* outside */ \ - return; \ - } \ - w=ClipX2-x; \ - } \ - \ - if( y<ClipY1 ) { \ - f=ClipY1-y; \ - y=ClipY1; \ - if( h<f ) { /* outside */ \ - return; \ - } \ - h-=f; \ - } \ - if( (y+h)>ClipY2 ) { \ - if( h<ClipY2-y ) { /* outside */ \ - return; \ - } \ - h=ClipY2-y; \ - } \ - } while( 0 ) - /** ** Video draw part of 8bit graphic clipped into 8 bit framebuffer. ** @@ -299,7 +257,7 @@ local void VideoDrawSub8to8Clip( const Graphic* graphic,int gx,int gy,unsigned w,unsigned h, int x,int y) { - DO_CLIPPING(w,h,x,y); + CLIP_RECTANGLE(x,y,w,h); VideoDrawSub8to8(graphic,gx,gy,w,h,x,y); } @@ -318,7 +276,7 @@ local void VideoDrawSub8to16Clip( const Graphic* graphic,int gx,int gy,unsigned w,unsigned h, int x,int y) { - DO_CLIPPING(w,h,x,y); + CLIP_RECTANGLE(x,y,w,h); VideoDrawSub8to16(graphic,gx,gy,w,h,x,y); } @@ -337,7 +295,7 @@ local void VideoDrawSub8to24Clip( const Graphic* graphic,int gx,int gy,unsigned w,unsigned h, int x,int y) { - DO_CLIPPING(w,h,x,y); + CLIP_RECTANGLE(x,y,w,h); VideoDrawSub8to24(graphic,gx,gy,w,h,x,y); } @@ -356,7 +314,7 @@ local void VideoDrawSub8to32Clip( const Graphic* graphic,int gx,int gy,unsigned w,unsigned h, int x,int y) { - DO_CLIPPING(w,h,x,y); + CLIP_RECTANGLE(x,y,w,h); VideoDrawSub8to32(graphic,gx,gy,w,h,x,y); } diff --git a/src/video/intern_video.h b/src/video/intern_video.h new file mode 100644 index 000000000..ff29e1eb3 --- /dev/null +++ b/src/video/intern_video.h @@ -0,0 +1,123 @@ +// ___________ _________ _____ __ +// \_ _____/______ ____ ____ \_ ___ \____________ _/ ____\/ |_ +// | __) \_ __ \_/ __ \_/ __ \/ \ \/\_ __ \__ \\ __\\ __\ +// | \ | | \/\ ___/\ ___/\ \____| | \// __ \| | | | +// \___ / |__| \___ >\___ >\______ /|__| (____ /__| |__| +// \/ \/ \/ \/ \/ +// ______________________ ______________________ +// T H E W A R B E G I N S +// FreeCraft - A free fantasy real time strategy game engine +// +/**@name intern_video.h - The video headerfile for video sources only. */ +// +// (c) Copyright 1999-2001 by Lutz Sammer +// +// FreeCraft 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 2 of the License, +// or (at your option) any later version. +// +// FreeCraft 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. +// +// $Id$ + +#ifndef __INTERN_VIDEO_H__ +#define __INTERN_VIDEO_H__ + +//@{ + + +/*---------------------------------------------------------------------------- +-- Documentation +----------------------------------------------------------------------------*/ +/** +** THIS HEADER FILE SHOULD ONLY BE INCLUDED BY SOURCE-FILES IN VIDEO !!! +** +** This delivers an interface to basic video operations in video.c, while +** keeping these detailed operations out of the main include-file video.h +** +** FIXME: Currently some interfaces listed in video.h should be moved in +** here, this includes possible "extern" declarations in source-files +** themselves. +** +*/ + +/*---------------------------------------------------------------------------- +-- Includes +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +-- Declarations +----------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------- +-- Variables +----------------------------------------------------------------------------*/ + /// Direct acces to clipping rectangle for macro CLIP_RECTANGLE +extern int ClipX1; /// current clipping top left +extern int ClipY1; /// current clipping top left +extern int ClipX2; /// current clipping bottom right +extern int ClipY2; /// current clipping bottom right + + +/*---------------------------------------------------------------------------- +-- Macros +----------------------------------------------------------------------------*/ +/** +** Clip to clipping rectangle. +** FIXME: not easy to debug, but making it a function needs: +** - pointers to be able to alter given arguments +** - special return value to denote 'outside' clipping region +** (which is now handled by a simple return in caller function) +** +** @param w unsigned int width to display +** @param h unsigned int height to display +** @param x int X screen position +** @param y int Y screen position +*/ +#define CLIP_RECTANGLE(x,y,width,height) { \ + unsigned int f; \ + if( x<ClipX1 ) { \ + f=ClipX1-x; \ + if( width<=f ) { \ + return; \ + } \ + width-=f; \ + x=ClipX1; \ + } \ + if( (x+width)>ClipX2+1 ) { \ + if( x>ClipX2 ) { \ + return; \ + } \ + width=ClipX2-x+1; \ + } \ + if( y<ClipY1 ) { \ + f=ClipY1-y; \ + if( height<=f ) { \ + return; \ + } \ + height-=f; \ + y=ClipY1; \ + } \ + if( (y+height)>ClipY2+1 ) { \ + if( y>ClipY2 ) { \ + return; \ + } \ + height=ClipY2-y+1; \ + } \ +} + + +/*---------------------------------------------------------------------------- +-- Functions +----------------------------------------------------------------------------*/ + + +//@} + +#endif // !__INTERN_VIDEO_H__ diff --git a/src/video/linedraw.cpp b/src/video/linedraw.cpp index b8d451caa..ce3e72932 100644 --- a/src/video/linedraw.cpp +++ b/src/video/linedraw.cpp @@ -36,6 +36,8 @@ #include "freecraft.h" #include "video.h" +#include "intern_video.h" + /*---------------------------------------------------------------------------- -- Declarations ----------------------------------------------------------------------------*/ @@ -51,15 +53,6 @@ typedef enum { ClipCodeRight = 8 } ClipCode; -/*---------------------------------------------------------------------------- --- Externals -----------------------------------------------------------------------------*/ - -extern int ClipX1; /// current clipping top left -extern int ClipY1; /// current clipping top left -extern int ClipX2; /// current clipping bottom right -extern int ClipY2; /// current clipping bottom right - /*---------------------------------------------------------------------------- -- Variables ----------------------------------------------------------------------------*/ @@ -4513,38 +4506,6 @@ local void DrawTransRectangle32(SysColors color,int x,int y } } -#define CLIP_RECTANGLE(x,y,width,height) { \ - unsigned f; \ - if( x<ClipX1 ) { \ - f=ClipX1-x; \ - if( width<=f ) { \ - return; \ - } \ - width-=f; \ - x=ClipX1; \ - } \ - if( (x+width)>ClipX2+1 ) { \ - if( x>ClipX2 ) { \ - return; \ - } \ - width=ClipX2-x+1; \ - } \ - if( y<ClipY1 ) { \ - f=ClipY1-y; \ - if( height<=f ) { \ - return; \ - } \ - height-=f; \ - y=ClipY1; \ - } \ - if( (y+height)>ClipY2+1 ) { \ - if( y>ClipY2 ) { \ - return; \ - } \ - height=ClipY2-y+1; \ - } \ -} - /** ** Draw rectangle clipped. ** diff --git a/src/video/video.cpp b/src/video/video.cpp index caa7d3ca5..1b2cc21eb 100644 --- a/src/video/video.cpp +++ b/src/video/video.cpp @@ -35,12 +35,13 @@ #include "freecraft.h" #include "video.h" - #include "map.h" #include "ui.h" #include "cursor.h" #include "iolib.h" +#include "intern_video.h" + #ifdef USE_SDL #include <SDL/SDL.h> #endif