edivc/dlls/src/graphics/map_ops.c
2005-01-30 18:27:05 +00:00

605 lines
14 KiB
C

/*! \file map_ops.c
* \brief Funciones de operaciones con mapas
*
* Este fichero contiene las funciones para las operaciones con mapas
* (modificación, obtención de información, bliteos, etc).
*
* \todo Falta respetar el centro del gráfico, y soporte para FLAGS 1 y 2
*/
#include <SDL/SDL.h>
#include "export.h"
#include "graphics.h"
/*! \brief Copia un trozo de mapa y lo pega en otro mapa
*
* Esta función sólo permite operaciones en el mismo FPG.
* \todo ¿sobrecargar para permitir operaciones entre FPG's?
* @param f FPG donde se encuentran los dos mapas
* @param g2 Gráfico de destino
* @param x2 Coordenada X destino
* @param y2 Coordenada Y destino
* @param g1 Gráfico de origen
* @param x1 Coordenada X origen
* @param y1 Coordenada Y origen
* @param w Anchura del bloque a copiar
* @param h Altura del bloque a copiar
* @return 1
* @see eDIV_MAP_PUT(), eDIV_MAP_XPUT()
*/
int eDIV_MAP_BLOCK_COPY(FUNCTION_PARAMS)
{
int f , g2 , x2 , y2 , g1 , x1 , y1 , w , h ;
SDL_Rect srcrect , dstrect ;
h = getparm() ;
w = getparm() ;
y1 = getparm() ;
x1 = getparm() ;
g1 = getparm() ;
y2 = getparm() ;
x2 = getparm() ;
g2 = getparm() ;
f = getparm() ;
srcrect.x = x1 ;
srcrect.y = y1 ;
srcrect.w = w ;
srcrect.h = h ;
dstrect.x = x2 ;
dstrect.y = y2 ;
dstrect.w = srcrect.w ;
dstrect.h = srcrect.h ;
if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe )
return -1 ;
SDL_BlitSurface( files[f].mapa[g1].Surface , &srcrect , files[f].mapa[g2].Surface , &dstrect ) ;
return 1 ;
}
/*! \brief Obtiene el color del pixel, en las coordenadas (x,y), de un mapa.
* @param f Fichero (FPG) donde se encuentra el mapa
* @param g Código del gráfico dentro del FPG.
* @param x Coordenada X del pixel
* @param y Coordenada Y del pixel
* @return El color del píxel.
* @see eDIV_MAP_PUT_PIXEL(), eDIV_PUT_PIXEL(), eDIV_GET_PIXEL()
*/
int eDIV_MAP_GET_PIXEL(FUNCTION_PARAMS)
{
int f , g , x , y , bpp ;
Uint8 *p ;
y = getparm() ;
x = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 )
return -2 ;
bpp = files[f].mapa[g].Surface->format->BytesPerPixel;
p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
return p[0] << 16 | p[1] << 8 | p[2];
}else
{
return p[0] | p[1] << 8 | p[2] << 16;
}
case 4:
return *(Uint32 *)p;
}
return 0;
}
/*! \brief Blitea un mapa dentro de otro mapa
*
* Esta función sólo permite operaciones en el mismo FPG.
* \todo ¿sobrecargar para permitir operaciones entre FPG's?
* @param f Fichero (FPG) donde se encuentran los dos mapas.
* @param g2 Gráfico de destino
* @param g1 Gráfico de origen
* @param x Coordenada X
* @param y Coordenada Y
* @return 1
* @see eDIV_MAP_BLOCK_COPY(), eDIV_XPUT()
*/
int eDIV_MAP_PUT(FUNCTION_PARAMS)
{
int f , g2 , g1 , x , y ;
SDL_Rect dstrect ;
y = getparm() ;
x = getparm() ;
g1 = getparm() ;
g2 = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g1].existe || !files[f].mapa[g2].existe )
return -1 ;
dstrect.x = x ;
dstrect.y = y ;
dstrect.w = 0 ; /* Se ignora */
dstrect.h = 0 ; /* Se ignora */
SDL_BlitSurface( files[f].mapa[g1].Surface , NULL , files[f].mapa[g2].Surface , &dstrect ) ;
return 1 ;
}
/*! \brief Cambia el color de un píxel determinado de un mapa
* @param fichero Fichero (FPG) donde se encuentra el mapa
* @param grafico Código del mapa dentro del FPG
* @param x Coordenada X del píxel
* @param y Coordenada y del píxel
* @param color Color
* @return 1
* @see eDIV_MAP_GET_PIXEL(), eDIV_PUT_PIXEL(), eDIV_GET_PIXEL()
*/
int eDIV_MAP_PUT_PIXEL(FUNCTION_PARAMS)
{
int f , g , x , y , c , bpp ;
Uint8 *p ;
c = getparm() ;
y = getparm() ;
x = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[0].mapa[g].existe )
return -1 ;
if ( x > files[f].mapa[g].Surface->w || y > files[f].mapa[g].Surface->h || x < 0 || y < 0 )
return -2 ;
if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) {
if ( SDL_LockSurface( files[f].mapa[g].Surface ) < 0 ) {
return -3;
}
}
bpp = files[f].mapa[g].Surface->format->BytesPerPixel ;
p = (Uint8 *)files[f].mapa[g].Surface->pixels + y * files[f].mapa[g].Surface->pitch + x * bpp ;
switch(bpp) {
case 1:
*p = c;
break;
case 2:
*(Uint16 *)p = c;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (c >> 16) & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = c & 0xff;
} else {
p[0] = c & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = (c >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = c;
break;
}
if ( SDL_MUSTLOCK( files[f].mapa[g].Surface ) ) {
SDL_UnlockSurface( files[f].mapa[g].Surface );
}
return 1 ;
}
/*! \brief Blitea un mapa sobre el buffer del fondo
* @param fichero Fichero (FPG) donde se encuentra el gráfico
* @param grafico Código del mapa dentro del FPG
* @param x Coordenada X destino
* @param y Coordenada Y destino
* @return 1
* @see eDIV_MAP_PUT(), eDIV_XPUT()
*/
int eDIV_PUT(FUNCTION_PARAMS)
{
int f , g , x , y ;
SDL_Rect dstrect ;
y = getparm() ;
x = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
dstrect.x = x - files[f].mapa[g].cpoint[0].x ;
dstrect.y = y - files[f].mapa[g].cpoint[0].y ;
dstrect.w = 0 ; /* Se ignora */
dstrect.h = 0 ; /* Se ignora */
SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , &dstrect ) ;
return 1 ;
}
/*! \brief Como eDIV_PUT() pero permitiendo indicar ángulo, tamaño y flags.
* \todo Falta soporte para flags. Revisar y añadir fp->Runtime_Error()
* @param fichero Fichero (FPG) donde se encuentra el gráfico
* @param grafico Código del mapa dentro del FPG
* @param x Coordenada X destino
* @param y Coordenada Y destino
* @param angle Ángulo (en milésimas de grado)
* @param zoom Tamaño (en porcentaje)
* @return 1 si se ha colocado correctamente, -1 si el mapa no existe.
* @see eDIV_PUT(), eDIV_MAP_XPUT(), eDIV_MAP_PUT()
*/
int eDIV_XPUT(FUNCTION_PARAMS)
{
int f , g , x , y ;
double zoom,angle;
SDL_Surface *map;
SDL_Rect dstrect ;
zoom = getparm();
angle = getparm();
y = getparm() ;
x = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
dstrect.x = x - files[f].mapa[g].cpoint[0].x ;
dstrect.y = y - files[f].mapa[g].cpoint[0].y ;
dstrect.w = 0 ; /* Se ignora */
dstrect.h = 0 ; /* Se ignora */
map=xput(files[f].mapa[g].Surface,zoom,angle);
SDL_BlitSurface(map , NULL , fondo , &dstrect ) ;
SDL_FreeSurface (map);
return 1 ;
}
/*! \brief Blitea un mapa sobre el buffer del fondo en la ESQUINA SUPERIOR IZQUIERDA de la pantalla
* @param fichero Fichero (FPG) donde se encuentra el gráfico
* @param grafico Código del mapa dentro del FPG
* @return 1
* @see eDIV_PUT(), eDIV_LOAD_SCREEN()
*/
int eDIV_PUT_SCREEN(FUNCTION_PARAMS)
{
int f , g ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
SDL_BlitSurface( files[f].mapa[g].Surface , NULL , fondo , NULL ) ;
return 1 ;
}
/*! \brief Cambia el color del pixel, en las coordenadas (x,y), del fondo.
* @param x Coordenada X del pixel
* @param y Coordenada Y del pixel
* @param color Color
* @return 1
* @see eDIV_MAP_PUT_PIXEL(), eDIV_GET_PIXEL()
*/
int eDIV_PUT_PIXEL(FUNCTION_PARAMS)
{
int x , y , c , bpp ;
Uint8 *p ;
c = getparm() ;
y = getparm() ;
x = getparm() ;
if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 )
return -1 ;
if ( SDL_MUSTLOCK(fondo) ) {
if ( SDL_LockSurface(fondo) < 0 ) {
return -2;
}
}
bpp = fondo->format->BytesPerPixel ;
p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp ;
switch(bpp) {
case 1:
*p = c;
break;
case 2:
*(Uint16 *)p = c;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (c >> 16) & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = c & 0xff;
} else {
p[0] = c & 0xff;
p[1] = (c >> 8) & 0xff;
p[2] = (c >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = c;
break;
}
if ( SDL_MUSTLOCK(fondo) ) {
SDL_UnlockSurface(fondo);
}
return 1 ;
}
/*! \brief Rellena el buffer del fondo con el color 0.
* @return 1
*/
int eDIV_CLEAR_SCREEN(FUNCTION_PARAMS)
{
SDL_FillRect( fondo , NULL , 0 ) ;
return 1;
}
/*! \brief Obtiene el color del pixel, en las coordenadas (x,y), del buffer del fondo.
* @param x Coordenada X del pixel
* @param y Coordenada Y del pixel
* @return El color del píxel.
* @see eDIV_PUT_PIXEL(), eDIV_MAP_GET_PIXEL()
*/
int eDIV_GET_PIXEL(FUNCTION_PARAMS)
{
int x , y , bpp;
Uint8 *p ;
y = getparm() ;
x = getparm() ;
if ( x > fondo->w || y > fondo->h || x < 0 || y < 0 )
return -1 ;
bpp = fondo->format->BytesPerPixel;
p = (Uint8 *)fondo->pixels + y * fondo->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
return p[0] << 16 | p[1] << 8 | p[2];
}else
{
return p[0] | p[1] << 8 | p[2] << 16;
}
case 4:
return *(Uint32 *)p;
}
return 0;
}
/*! \brief Crea un nuevo mapa con las características indicadas.
*
* El nuevo mapa se creará en el fichero 0, como si se hubiera cargado con
* \link eDIV_LOAD_MAP() load_map() \endlink.
* @param w Anchura del mapa
* @param h Altura del mapa
* @param cx Coordenada X del centro del mapa
* @param cy Coordenada Y del centro del mapa
* @param c Color con el que se rellenará el nuevo mapa
* @return El código del nuevo gráfico, o -1 si ocurrió un error
* @see eDIV_LOAD_MAP(), eDIV_UNLOAD_MAP()
*/
int eDIV_NEW_MAP(FUNCTION_PARAMS)
{
int i ;
int w , h , cx , cy , c ;
c = getparm() ;
cy = getparm() ;
cx = getparm() ;
h = getparm() ;
w = getparm() ;
for ( i = 1000 ; i < files[0].num ; i++ )
{
if ( !files[0].mapa[i].existe )
{
files[0].mapa[i].Surface = SDL_CreateRGBSurface( SDL_HWSURFACE , w , h , screen->format->BitsPerPixel , screen->format->Rmask , screen->format->Gmask ,screen->format->Bmask ,screen->format->Amask ) ;
if(fp->graphics->bpp==8)
PaletteCopy(files[0].mapa[i].Surface,screen);
files[0].mapa[i].existe = 1 ;
files[0].mapa[i]. cpoint[0].x = cx ;
files[0].mapa[i].cpoint[0].y = cy ;
SDL_FillRect( files[0].mapa[i].Surface , NULL , c ) ;
SDL_SetColorKey( files[0].mapa[i].Surface , SDL_SRCCOLORKEY | SDL_RLEACCEL , color_transparente ) ;
if ( i > last_map[0] )
last_map[0] = i ;
return i ;
}
}
return -1 ;
}
/*! \brief Copia una región de la pantalla en un mapa
* \todo La región copiada debe ESTIRARSE para adaptarse a la región destino
* @param r Región de la pantalla
* @param f Fichero del mapa destino
* @param g Gráfico destino
* @param x Coordenada X destino
* @param y Coordenada Y destino
* @param w Ancho de la región destino dentro del mapa
* @param h Alto de la región destino dentro del mapa
* @return 1
* @see eDIV_DEFINE_REGION(), eDIV_MAP_BLOCK_COPY()
*/
int eDIV_SCREEN_COPY(FUNCTION_PARAMS)
{
SDL_Rect srcrect , dstrect ;
int r, f, g , x, y , w , h ;
h = getparm() ;
w = getparm() ;
y = getparm() ;
x = getparm() ;
g = getparm() ;
f = getparm() ;
r = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
srcrect.x = 0 ;
srcrect.y = 0 ;
srcrect.w = w ;
srcrect.h = h ;
dstrect.x = x ;
dstrect.y = y ;
dstrect.w = 0 ;
dstrect.h = 0 ;
SDL_BlitSurface( screen, &srcrect , files[f].mapa[g].Surface , &dstrect ) ;
return 1 ;
}
/*! \brief Obtiene las coordenadas de un punto de control de un mapa
* @param f Fichero en el que se encuentra el mapa
* @param g Código del mapa dentro del FPG
* @param n Número del punto de control
* @param offset_x Offset de la variable donde guardar la coordenada X
* @param offset_y Offset de la variable donde guardar la coordenada Y
* @return 0 si todo va bien, -1 si el mapa no existe
* @see eDIV_GET_REAL_POINT()
*/
int eDIV_GET_POINT(FUNCTION_PARAMS)
{
int f , g , n , dx , dy ;
dy = getparm() ;
dx = getparm() ;
n = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
if(dx) fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x ;
if(dy) fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y ;
return 0 ;
}
/*! \brief Obtiene las coordenadas en pantalla de un punto de control del proceso actual
* \todo Tener en cuenta angle, size, etc
* @param n Número del punto de control
* @param offset_x Offset de la variable donde guardar la coordenada X
* @param offset_y Offset de la variable donde guardar la coordenada Y
* @return 0 si todo va bien, -1 si el mapa no existe
* @see eDIV_GET_POINT()
*/
int eDIV_GET_REAL_POINT(FUNCTION_PARAMS)
{
int f , g , n , dx , dy , x , y , id;
dy = getparm() ;
dx = getparm() ;
n = getparm() ;
id = fp->procs_s[ fp->proc_orden[ *fp->proceso_actual ] ].id;
f = local("file",id) ;
g = local("graph",id) ;
x = local("x",id) ;
y = local("y",id) ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
if(dx) fp->mem[ dx ] = files[f].mapa[g].cpoint[n].x - files[f].mapa[g].cpoint[0].x + x ;
if(dy) fp->mem[ dy ] = files[f].mapa[g].cpoint[n].y - files[f].mapa[g].cpoint[0].y + y ;
return 0 ;
}
/*! \brief Obtiene información sobre un mapa
* @param f Fichero donde se encuentra el mapa
* @param g Código del gráfico dentro del FPG
* @param i Indica qué información quiere extraerse del mapa, puede ser uno de:
* \a g_wide (0), \a g_height (1), \a g_x_center (2) ó \a g_y_center (3).
* @return La información solicitada, o -1 si hubo un error.
* @see eDIV_GET_POINT()
*/
int eDIV_GRAPHIC_INFO(FUNCTION_PARAMS)
{
int f , g , i ;
i = getparm() ;
g = getparm() ;
f = getparm() ;
if ( !files[f].existe || !files[f].mapa[g].existe )
return -1 ;
switch (i)
{
case 0:
return files[f].mapa[g].Surface->w ;
case 1:
return files[f].mapa[g].Surface->h ;
case 2:
return files[f].mapa[g].cpoint[0].x ;
case 3:
return files[f].mapa[g].cpoint[0].y ;
}
return -1;
}