Moved cursor.c into src/video.

This commit is contained in:
johns 2000-05-21 20:47:03 +00:00
parent f9a54f86ae
commit 29bc346903
2 changed files with 1 additions and 554 deletions
src/stratagus

View file

@ -23,8 +23,7 @@ MODULE = clone
OBJS = clone.$(OE) unit.$(OE) unit_draw.$(OE) unitcache.$(OE) \
unit_find.$(OE) missile.$(OE) construct.$(OE)\
player.$(OE) pud.$(OE) cursor.$(OE) \
ccl.$(OE) interface.$(OE) iolib.$(OE) \
player.$(OE) pud.$(OE) ccl.$(OE) interface.$(OE) iolib.$(OE) \
mainloop.$(OE) goal.$(OE) selection.$(OE) groups.$(OE)
include $(TOPDIR)/Common.mk

View file

@ -1,552 +0,0 @@
// ___________ _________ _____ __
// \_ _____/______ ____ ____ \_ ___ \____________ _/ ____\/ |_
// | __) \_ __ \_/ __ \_/ __ \/ \ \/\_ __ \__ \\ __\\ __\
// | \ | | \/\ ___/\ ___/\ \____| | \// __ \| | | |
// \___ / |__| \___ >\___ >\______ /|__| (____ /__| |__|
// \/ \/ \/ \/ \/
// ______________________ ______________________
// T H E W A R B E G I N S
// FreeCraft - A free fantasy real time strategy game engine
//
/**@name cursor.c - The cursors. */
/*
** (c) Copyright 1998,2000 by Lutz Sammer
**
** $Id$
*/
//@{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freecraft.h"
#include "video.h"
#include "sound_id.h"
#include "unitsound.h"
#include "unittype.h"
#include "player.h"
#include "unit.h"
#include "cursor.h"
#include "tileset.h"
#include "map.h"
#include "interface.h"
#include "ui.h"
/*============================================================================
== CURSOR
============================================================================*/
/**
** Define cursor-types.
*/
global CursorType Cursors[CursorMax] = {
{ { "human gauntlet.png"
,"orcish claw.png" }
, 3, 2, 28,32 },
{ { "magnifying glass.png"
,NULL }
,11,11, 34,35 },
{ { "small green cross.png"
,NULL }
, 8, 8, 18,18 },
{ { "yellow eagle.png"
,"yellow crosshairs.png" }
,15,15, 32,32 },
{ { "green eagle.png"
,"green crosshairs.png" }
,15,15, 32,32 },
{ { "red eagle.png"
,"red crosshairs.png" }
,15,15, 32,32 },
{ { "cross.png"
,NULL }
,15,15, 32,32 },
{ { "arrow E.png"
,NULL }
,22,10, 32,24 },
{ { "arrow N.png"
,NULL }
,12, 2, 32,24 },
{ { "arrow NE.png"
,NULL }
,20, 2, 32,24 },
{ { "arrow NW.png"
,NULL }
, 2, 2, 32,24 },
{ { "arrow S.png"
,NULL }
,12,22, 32,24 },
{ { "arrow SE.png"
,NULL }
,20,18, 32,24 },
{ { "arrow SW.png"
,NULL }
, 2,18, 32,24 },
{ { "arrow W.png"
,NULL }
, 4,10, 32,24 },
};
global enum CursorState_e CursorState; // cursor state
global int CursorAction; // action for selection
global UnitType* CursorBuilding; // building cursor
global CursorType* GameCursor; // cursor type
global int CursorX; // cursor position
global int CursorY;
global int CursorStartX; // rectangle started
global int CursorStartY;
global int OldCursorX;
global int OldCursorY;
global int OldCursorW;
global int OldCursorH;
global int OldCursorSize;
global void* OldCursorImage;
/**
** Load all cursor sprites.
*/
global void LoadCursors(unsigned int race)
{
int i;
const char* file;
static int last_race = -1;
if (race == last_race) // same race? already loaded!
return;
if (last_race != -1) { // free previous sprites for different race
for( i=0; i<sizeof(Cursors)/sizeof(*Cursors); ++i ) {
if (Cursors[i].RleSprite) {
FreeRleSprite(Cursors[i].RleSprite);
Cursors[i].RleSprite = NULL;
}
}
}
last_race = race;
for( i=0; i<sizeof(Cursors)/sizeof(*Cursors); ++i ) {
if( !(file=Cursors[i].File[race]) ) {
file=Cursors[i].File[0]; // default one, no race specific
}
// FIXME: size and hot-point extra!
if( file ) {
char* buf;
buf=alloca(strlen(file)+9+1);
file=strcat(strcpy(buf,"graphic/"),file);
ShowLoadProgress("\tCursor %s\n",file);
Cursors[i].RleSprite=LoadRleSprite(file
,0,0);
// FIXME: this is hack!!
//,Cursors[i].Width,Cursors[i].Height);
}
}
}
/**
** Save image behind cursor.
*/
local void SaveCursor(void)
{
int w,h,i;
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;
}
// FIXME: use function pointer
switch( VideoDepth ) {
case 8:
i=w*h*sizeof(VMemType8);
break;
case 15:
case 16:
i=w*h*sizeof(VMemType16);
break;
case 24:
case 32:
default:
i=w*h*sizeof(VMemType32);
break;
}
if( OldCursorSize<i ) {
if( OldCursorImage ) {
OldCursorImage=realloc(OldCursorImage,i);
} else {
OldCursorImage=malloc(i);
}
DebugLevel3("Cursor memory %d\n",i);
OldCursorSize=i;
}
// FIXME: use function pointer
switch( VideoDepth ) {
case 8:
{ VMemType8 *dp;
VMemType8 *sp;
dp=OldCursorImage;
sp=VideoMemory8+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType8));
dp+=w;
sp+=VideoWidth;
}
break; }
case 15:
case 16:
{ VMemType16 *dp;
VMemType16 *sp;
dp=OldCursorImage;
sp=VideoMemory16+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType16));
dp+=w;
sp+=VideoWidth;
}
break; }
case 24:
case 32:
{ VMemType32 *dp;
VMemType32 *sp;
dp=OldCursorImage;
sp=VideoMemory32+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType32));
dp+=w;
sp+=VideoWidth;
}
break; }
}
}
/**
** Restore image behind cursor.
*/
local void RestoreCursor(void)
{
void *dp;
void *sp;
int w;
int h;
int x;
int y;
if( !(sp=OldCursorImage) ) { // no cursor saved
return;
}
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;
}
switch( VideoDepth ) {
case 8:
dp=VideoMemory8+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType8));
((VMemType8*)sp)+=w;
((VMemType8*)dp)+=VideoWidth;
}
break;
case 15:
case 16:
dp=VideoMemory16+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType16));
((VMemType16*)sp)+=w;
((VMemType16*)dp)+=VideoWidth;
}
break;
case 24:
case 32:
dp=VideoMemory32+y*VideoWidth+x;
while( h-- ) {
memcpy(dp,sp,w*sizeof(VMemType32));
((VMemType32*)sp)+=w;
((VMemType32*)dp)+=VideoWidth;
}
break;
}
}
/**
** Draw cursor.
*/
global void DrawCursor(CursorType* type,int x,int y,int frame)
{
OldCursorX=x-=type->HotX;
OldCursorY=y-=type->HotY;
OldCursorW=type->RleSprite->Width;
OldCursorH=type->RleSprite->Height;
SaveCursor();
DrawRleSpriteClipped(type->RleSprite,frame,x,y);
}
/**
** Hide cursor.
*/
global void HideCursor(void)
{
RestoreCursor();
}
/*----------------------------------------------------------------------------
-- DRAW CURSOR
----------------------------------------------------------------------------*/
local int RectangleCursor; /// Flag: last cursor was rectangle
local int BuildingCursor; /// Flag: last cursor was building
/**
** Draw cursor for selecting building position.
*/
local void DrawBuildingCursor(void)
{
int x;
int y;
int x1;
int y1;
int mx;
int my;
int color;
int f;
int w;
int w0;
int h;
int mask;
x=((CursorX-TheUI.MapX)/TileSizeX)*TileSizeX+TheUI.MapX; // Align to grid
y=((CursorY-TheUI.MapY)/TileSizeY)*TileSizeY+TheUI.MapY;
mx=Screen2MapX(x);
my=Screen2MapY(y);
//
// Draw building
//
PlayerPixels(ThisPlayer);
SetClipping(TheUI.MapX,TheUI.MapY
,TheUI.MapWidth,TheUI.MapHeight);
DrawUnitType(CursorBuilding,0,x,y);
// FIXME: This is dangerous here
SetClipping(0,0,VideoWidth,VideoHeight);
//
// Draw the allow overlay
//
f=CanBuildHere(CursorBuilding,mx,my);
// FIXME: Should be moved into unittype structure, and allow more types.
if( CursorBuilding->ShoreBuilding ) {
mask=MapFieldLandUnit
| MapFieldSeaUnit
| MapFieldBuilding // already occuppied
| MapFieldWall
| MapFieldRocks
| MapFieldForest // wall,rock,forest not 100% clear?
| MapFieldLandAllowed // can't build on this
//| MapFieldUnpassable // FIXME: I think shouldn't be used
| MapFieldNoBuilding;
} else switch( CursorBuilding->UnitType ) {
case UnitTypeLand:
mask=MapFieldLandUnit
| MapFieldBuilding // already occuppied
| MapFieldWall
| MapFieldRocks
| MapFieldForest // wall,rock,forest not 100% clear?
| MapFieldCoastAllowed
| MapFieldWaterAllowed // can't build on this
| MapFieldUnpassable // FIXME: I think shouldn't be used
| MapFieldNoBuilding;
break;
case UnitTypeNaval:
mask=MapFieldSeaUnit
| MapFieldBuilding // already occuppied
| MapFieldCoastAllowed
| MapFieldLandAllowed // can't build on this
| MapFieldUnpassable // FIXME: I think shouldn't be used
| MapFieldNoBuilding;
break;
case UnitTypeFly:
default:
DebugLevel1(__FUNCTION__": Were moves this unit?\n");
return;
}
h=CursorBuilding->TileHeight;
if( my+h>MapY+MapHeight ) { // reduce to view limits
h=MapY+MapHeight-my;
}
w0=CursorBuilding->TileWidth; // reduce to view limits
if( mx+w0>MapX+MapWidth ) {
w0=MapX+MapWidth-mx;
}
while( h-- ) {
w=w0;
while( w-- ) {
if( f && (CanBuildOn(mx+w,my+h,mask) ||
(Selected[0]->X==mx+w && Selected[0]->Y==my+h))
&& IsMapFieldExplored(mx+w,my+h) ) {
color=ColorGreen;
} else {
color=ColorRed;
}
// FIXME: I could do this faster+better
for( y1=0; y1<TileSizeY; ++y1 ) {
for( x1=y1&1; x1<TileSizeX; x1+=2 ) {
VideoDrawPixel(color,x+w*TileSizeX+x1,y+h*TileSizeY+y1);
}
}
}
}
}
/**
** 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.MapWidth ) {
x1=TheUI.MapWidth-1;
}
y1=CursorY;
if( y1<TheUI.MapY ) {
y1=TheUI.MapY;
} else if( y1>=TheUI.MapHeight ) {
y1=TheUI.MapHeight-1;
}
x=CursorStartX;
if( x>x1 ) {
x=x1;
w=CursorStartX-x;
} else {
w=x1-x;
}
y=CursorStartY;
if( y>y1 ) {
y=y1;
h=CursorStartY-y;
} else {
h=y1-y;
}
VideoDrawRectangle(ColorGreen,x,y,w,h);
}
/**
** Draw the cursor
*/
global void DrawAnyCursor(void)
{
RectangleCursor=BuildingCursor=0;
//
// Selecting rectangle
//
if( CursorState==CursorStateRectangle
&& (CursorStartX!=CursorX || CursorStartY!=CursorY) ) {
DrawRectangleCursor();
RectangleCursor=1;
} else
//
// Selecting position for building
//
if( CursorBuilding && CursorOn==CursorOnMap ) {
DrawBuildingCursor();
BuildingCursor=1;
}
//
// Normal cursor.
//
DrawCursor(GameCursor,CursorX,CursorY,0);
}
/**
** Remove old cursor from display.
*/
global int HideAnyCursor(void)
{
if( RectangleCursor || BuildingCursor ) {
MustRedraw|=RedrawMap;
}
//
// Cursor complete on map and map must be redrawn, no restore.
//
if( OldCursorX>=TheUI.MapX
&& OldCursorX+OldCursorW<TheUI.MapWidth
&& OldCursorY>=TheUI.MapY
&& OldCursorY+OldCursorH<TheUI.MapHeight
&& (MustRedraw&RedrawMap)
&& (InterfaceState != IfaceStateMenu) ) {
return 0;
}
HideCursor();
return 1;
}
//@}