parent
7ec27d9fc5
commit
58f282c0cc
@ -0,0 +1,82 @@
|
|||||||
|
/* $Id: menu.h,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* GUI for menuhandling
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MENU_H_
|
||||||
|
#define _MENU_H_
|
||||||
|
|
||||||
|
#define MENU_TITLELEN 64
|
||||||
|
#define MENU_ENTRYNAME 64
|
||||||
|
#define MENU_BG_SHADE_DARK -64
|
||||||
|
#define MENU_BG_SHADE_BRIGHT 64
|
||||||
|
#define MENU_DATASIZE 256
|
||||||
|
#define MENU_MAXENTRYS 64
|
||||||
|
#define MENU_BUTTON_FONTSIZE 0
|
||||||
|
#define MENU_FOCUSVIS_BLINKTO 0.25f
|
||||||
|
#define MENU_DATAENTRYLEN 128
|
||||||
|
#define MENUOFFSET_X menu.oldscreenpos.x + menu.images[0]->w
|
||||||
|
#define MENUOFFSET_Y menu.oldscreenpos.y + menu.images[0]->h
|
||||||
|
|
||||||
|
enum _menu_type {
|
||||||
|
MENU_label = 0,
|
||||||
|
MENU_button,
|
||||||
|
MENU_entrytext,
|
||||||
|
MENU_entryint,
|
||||||
|
MENU_entryfloat,
|
||||||
|
MENU_bool,
|
||||||
|
MENU_list
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct __menuitem {
|
||||||
|
SDL_Rect pos;
|
||||||
|
int type;
|
||||||
|
int len;
|
||||||
|
int id;
|
||||||
|
|
||||||
|
char label[MENU_TITLELEN];
|
||||||
|
_keybinput keybi;
|
||||||
|
int state;
|
||||||
|
char *ptrdata; // pointer to some data
|
||||||
|
_charlist *list;
|
||||||
|
|
||||||
|
struct __menuitem *next;
|
||||||
|
} typedef _menuitem;
|
||||||
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char title[MENU_TITLELEN];
|
||||||
|
_menuitem *items;
|
||||||
|
_menuitem *focus;
|
||||||
|
SDL_Surface *oldscreen; // hold old screendata
|
||||||
|
SDL_Rect oldscreenpos;
|
||||||
|
SDL_Surface *images[9]; // holds the gfx
|
||||||
|
SDL_Surface *listimages[2][9]; // holds the gfx for the lists
|
||||||
|
SDL_Surface *buttonimages[3][3]; // holds the images for the buttons
|
||||||
|
SDL_Surface *entryimages[2][3]; // [PRESSED][Left|Center|Right]
|
||||||
|
float focusto;
|
||||||
|
int focusvis;
|
||||||
|
} typedef _menu;
|
||||||
|
|
||||||
|
extern _menu menu;
|
||||||
|
|
||||||
|
extern int menu_getlastitem (_menuitem *first);
|
||||||
|
extern void menu_new (char *title, int x, int y);
|
||||||
|
extern void menu_delete ();
|
||||||
|
extern void menu_create_list (char *name, int x, int y, int w, int h, _charlist *data, _charlist **selected, int id);
|
||||||
|
extern void menu_create_entry (char *name, int x, int y, int w, void *data, int len, int typ, int id);
|
||||||
|
extern void menu_create_label (char *name, int x, int y, int fontsize);
|
||||||
|
extern void menu_create_button (char *name, int x, int y, int w, int id);
|
||||||
|
extern void menu_create_bool (char *name, int x, int y, int w, int *data, int id);
|
||||||
|
extern int menu_loop ();
|
||||||
|
extern void menu_draw_border ();
|
||||||
|
extern void menu_draw_background (SDL_Rect *dest);
|
||||||
|
extern inline void menu_draw_menuitem (_menuitem *m);
|
||||||
|
extern void menu_focus_next ();
|
||||||
|
extern void menu_focus_prev ();
|
||||||
|
extern void menu_focus_id (int id);
|
||||||
|
extern void menu_change_focus (_menuitem *newfocus);
|
||||||
|
extern _menuitem *menu_get_lastid ();
|
||||||
|
extern _menuitem *menu_get_firstid ();
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,36 @@
|
|||||||
|
/* $Id: menugui.h,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* Menuhandling: gui elements */
|
||||||
|
|
||||||
|
#ifndef _MENUGUI_H_
|
||||||
|
#define _MENUGUI_H_
|
||||||
|
|
||||||
|
extern _menuitem menuitems[MENU_MAXENTRYS];
|
||||||
|
extern _menu menu;
|
||||||
|
|
||||||
|
/* buttons */
|
||||||
|
extern void menu_draw_button (_menuitem *mi);
|
||||||
|
extern int menu_event_button (_menuitem *mi, SDL_Event *event);
|
||||||
|
|
||||||
|
/* labels */
|
||||||
|
extern void menu_draw_label (_menuitem *mi);
|
||||||
|
|
||||||
|
/* bools */
|
||||||
|
#define menu_draw_bool menu_draw_button
|
||||||
|
extern int menu_event_bool (_menuitem *mi, SDL_Event *event);
|
||||||
|
|
||||||
|
/* entrytext and entryint */
|
||||||
|
extern void menu_draw_entry (_menuitem *mi);
|
||||||
|
extern int menu_event_entry (_menuitem *mi, SDL_Event *event);
|
||||||
|
extern void menu_entry_save (_menuitem *mi);
|
||||||
|
extern void menu_entry_restore (_menuitem *mi);
|
||||||
|
#define menu_entry_lose_focus menu_entry_save
|
||||||
|
|
||||||
|
extern void menu_draw_list (_menuitem *mi);
|
||||||
|
extern int menu_event_list (_menuitem *mi, SDL_Event *event);
|
||||||
|
extern int menu_list_getcount (_menuitem *mi);
|
||||||
|
extern int menu_list_getselected (_menuitem *mi);
|
||||||
|
extern void menu_draw_listtext (_menuitem *mi);
|
||||||
|
extern int menu_list_select (_menuitem *mi, int element);
|
||||||
|
extern void menu_list_select_prev (_menuitem *mi);
|
||||||
|
extern void menu_list_select_next (_menuitem *mi);
|
||||||
|
#endif
|
@ -0,0 +1,43 @@
|
|||||||
|
/* $Id: ogcache-client.h,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* include file for the opengamesrv.c file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OGCACHE_CLIENT_H
|
||||||
|
#define _OGCACHE_CLIENT_H
|
||||||
|
|
||||||
|
#define MAX_OGC_ENTRYS 255
|
||||||
|
#define UDP_DEFAULTPORT "11111"
|
||||||
|
#define LEN_OGCHOST 64
|
||||||
|
#define LEN_OGCPORT 10
|
||||||
|
#define LEN_GAME 32
|
||||||
|
#define LEN_VERSION 12
|
||||||
|
#define LEN_STATUS 6
|
||||||
|
#define LEN_GAMENAME 32
|
||||||
|
#define BUF_SIZE 1024
|
||||||
|
|
||||||
|
struct game_entry {
|
||||||
|
int serial;
|
||||||
|
char host[LEN_OGCHOST];
|
||||||
|
char port[LEN_OGCPORT];
|
||||||
|
char game[LEN_GAME];
|
||||||
|
char version [LEN_VERSION];
|
||||||
|
char gamename[LEN_GAMENAME];
|
||||||
|
int curplayers;
|
||||||
|
int maxplayers;
|
||||||
|
signed char ai_family;
|
||||||
|
char status[LEN_STATUS];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct game_entry ogc_array[MAX_OGC_ENTRYS];
|
||||||
|
extern int ogc_browsing;
|
||||||
|
|
||||||
|
int ogc_init (char *localport, char *server, char *port, char *game, int ai_family);
|
||||||
|
void ogc_shutdown ();
|
||||||
|
int ogc_loop ();
|
||||||
|
int ogc_sendgamestatus (int sock, char *game, char *version, char *gamename,
|
||||||
|
int curplayers, int maxplayers, char *status);
|
||||||
|
int ogc_sendgamequit (int sock); /* send that the game quitted */
|
||||||
|
void ogc_browsestart ();
|
||||||
|
void ogc_browsestop ();
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,39 @@
|
|||||||
|
/* $Id: udp.h,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* UDP Network */
|
||||||
|
|
||||||
|
#ifndef _UDP_H
|
||||||
|
#define _UDP_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock.h>
|
||||||
|
#include <io.h>
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define _sockaddr sockaddr
|
||||||
|
#else
|
||||||
|
#define _sockaddr sockaddr_in6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern char *dns_net_getip (char *host);
|
||||||
|
extern int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, struct _sockaddr *sAddr);
|
||||||
|
extern int udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family);
|
||||||
|
extern int udp_server (char *port, int ai_family);
|
||||||
|
extern void udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family);
|
||||||
|
extern void udp_close (int sock);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,60 @@
|
|||||||
|
/* $Id: menubools.c,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* Menuhandling: bools */
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menugui.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* create a bool only in the menudatas.. darf all this only when menu_loop
|
||||||
|
* is called */
|
||||||
|
void menu_create_bool (char *name, int x, int y, int w, int *data, int id) {
|
||||||
|
int i = menu_getlastitem(menu.items);
|
||||||
|
|
||||||
|
if (i == -1) { /* first entry in the itemslist */
|
||||||
|
menu.items = &menuitems[0];
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
|
||||||
|
d_fatal ("menu_create_button: MENU_MAXENTRYS reached. Item Ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else { /* add new item to the list */
|
||||||
|
menuitems[i].next = &menuitems[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitems[i].type = MENU_bool;
|
||||||
|
menuitems[i].pos.w = (1 + (int)((w - menu.buttonimages[0][0]->w - menu.buttonimages[0][2]->w) / menu.buttonimages[0][1]->w)) * menu.buttonimages[0][1]->w + menu.buttonimages[0][0]->w + menu.buttonimages[0][2]->w;
|
||||||
|
if (x != -1)
|
||||||
|
menuitems[i].pos.x = x;
|
||||||
|
else
|
||||||
|
menuitems[i].pos.x = (menu.oldscreenpos.w - 2 * menu.images[0]->w - menuitems[i].pos.w) / 2;
|
||||||
|
menuitems[i].pos.y = y;
|
||||||
|
menuitems[i].state = 0;
|
||||||
|
menuitems[i].id = id;
|
||||||
|
menuitems[i].ptrdata = (char *)data;
|
||||||
|
strncpy (menuitems[i].label, name, MENU_TITLELEN);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* handle the event on the button
|
||||||
|
* Return: 1 - if the button was pressed (With Enter) */
|
||||||
|
int menu_event_bool (_menuitem *mi, SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case (SDL_KEYDOWN): /* key was pressed */
|
||||||
|
if (event->key.keysym.sym == SDLK_LEFT || event->key.keysym.sym == SDLK_UP)
|
||||||
|
menu_focus_prev ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RIGHT || event->key.keysym.sym == SDLK_DOWN)
|
||||||
|
menu_focus_next ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RETURN || event->key.keysym.sym == SDLK_LCTRL || event->key.keysym.sym == SDLK_RCTRL) {
|
||||||
|
*(int *)mi->ptrdata = !(*(int *)mi->ptrdata);
|
||||||
|
menu_draw_bool (mi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
@ -0,0 +1,114 @@
|
|||||||
|
/* $Id: menubuttons.c,v 1.1 2003/12/24 02:42:05 stpohle Exp $
|
||||||
|
* Menuhandling: buttons */
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menugui.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* create a button only in the menudatas.. darf all this only when menu_loop
|
||||||
|
* is called */
|
||||||
|
void menu_create_button (char *name, int x, int y, int w, int id) {
|
||||||
|
int i = menu_getlastitem(menu.items);
|
||||||
|
|
||||||
|
if (i == -1) { /* first entry in the itemslist */
|
||||||
|
menu.items = &menuitems[0];
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
|
||||||
|
d_fatal ("menu_create_button: MENU_MAXENTRYS reached. Item Ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else { /* add new item to the list */
|
||||||
|
menuitems[i].next = &menuitems[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitems[i].type = MENU_button;
|
||||||
|
menuitems[i].pos.w = (1 + (int)((w - menu.buttonimages[0][0]->w - menu.buttonimages[0][2]->w) / menu.buttonimages[0][1]->w)) * menu.buttonimages[0][1]->w + menu.buttonimages[0][0]->w + menu.buttonimages[0][2]->w;
|
||||||
|
if (x != -1)
|
||||||
|
menuitems[i].pos.x = x;
|
||||||
|
else
|
||||||
|
menuitems[i].pos.x = (menu.oldscreenpos.w - 2 * menu.images[0]->w - menuitems[i].pos.w) / 2;
|
||||||
|
menuitems[i].pos.y = y;
|
||||||
|
menuitems[i].state = 0;
|
||||||
|
menuitems[i].id = id;
|
||||||
|
strncpy (menuitems[i].label, name, MENU_TITLELEN);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* draw the menuitem button or bool
|
||||||
|
* menuitem->pos.[x|y|w] - Position and X-Size inside the menu
|
||||||
|
* label - Text of the Button/Bool
|
||||||
|
*/
|
||||||
|
void menu_draw_button (_menuitem *mi) {
|
||||||
|
int px, py, i;
|
||||||
|
SDL_Rect dest;
|
||||||
|
|
||||||
|
if (mi->type != MENU_button && mi->type != MENU_bool)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dest.x = mi->pos.x;
|
||||||
|
dest.y = mi->pos.y;
|
||||||
|
dest.w = mi->pos.w;
|
||||||
|
dest.h = menu.buttonimages[0][0]->h;
|
||||||
|
menu_draw_background (&dest);
|
||||||
|
|
||||||
|
/* check the focus of the button */
|
||||||
|
if (menu.focusvis && mi == menu.focus)
|
||||||
|
mi->state = 1;
|
||||||
|
else if (mi->type == MENU_bool && (*((int*) mi->ptrdata)) > 0)
|
||||||
|
mi->state = 2; // bool
|
||||||
|
else
|
||||||
|
mi->state = 0; // button or bool == FALSE
|
||||||
|
|
||||||
|
// draw the left side of the button
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.buttonimages[mi->state][0]->w;
|
||||||
|
dest.h = menu.buttonimages[mi->state][0]->h;
|
||||||
|
gfx_blit (menu.buttonimages[mi->state][0], NULL, gfx.screen, &dest, 10000);
|
||||||
|
// draw the center of the button
|
||||||
|
for (i = 0; i < ((mi->pos.w - (menu.buttonimages[mi->state][0]->w + menu.buttonimages[mi->state][2]->w)) / menu.buttonimages[mi->state][1]->w); i++) {
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + menu.buttonimages[mi->state][0]->w + (i * menu.buttonimages[mi->state][1]->w);
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.buttonimages[mi->state][1]->w;
|
||||||
|
dest.h = menu.buttonimages[mi->state][1]->h;
|
||||||
|
gfx_blit (menu.buttonimages[mi->state][1], NULL, gfx.screen, &dest, 10000);
|
||||||
|
}
|
||||||
|
// draw the right side of the button
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.buttonimages[mi->state][2]->w;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.buttonimages[mi->state][2]->w;
|
||||||
|
dest.h = menu.buttonimages[mi->state][2]->h;
|
||||||
|
gfx_blit (menu.buttonimages[mi->state][2], NULL, gfx.screen, &dest, 10000);
|
||||||
|
|
||||||
|
// calculate the center of the button
|
||||||
|
px = (mi->pos.w - (strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x)) / 2 + mi->pos.x;
|
||||||
|
py = (menu.buttonimages[mi->state][0]->h - font[MENU_BUTTON_FONTSIZE].size.y) / 2 + mi->pos.y;
|
||||||
|
|
||||||
|
if (mi->type == MENU_bool && mi->state == 2) // disabled bool == FALSE
|
||||||
|
font_gfxdraw (MENUOFFSET_X + px, MENUOFFSET_Y + py, mi->label, MENU_BUTTON_FONTSIZE, COLOR_black, 10000);
|
||||||
|
else
|
||||||
|
font_gfxdraw (MENUOFFSET_X + px, MENUOFFSET_Y + py, mi->label, MENU_BUTTON_FONTSIZE, COLOR_yellow, 10000);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* handle the event on the button
|
||||||
|
* Return: 1 - if the button was pressed (With Enter) */
|
||||||
|
int menu_event_button (_menuitem *mi, SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case (SDL_KEYDOWN): /* key was pressed */
|
||||||
|
if (event->key.keysym.sym == SDLK_LEFT || event->key.keysym.sym == SDLK_UP)
|
||||||
|
menu_focus_prev ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RIGHT || event->key.keysym.sym == SDLK_DOWN)
|
||||||
|
menu_focus_next ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RETURN || event->key.keysym.sym == SDLK_LCTRL || event->key.keysym.sym == SDLK_RCTRL)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
@ -0,0 +1,170 @@
|
|||||||
|
/* $Id: menuentrys.c,v 1.1 2003/12/24 02:42:06 stpohle Exp $
|
||||||
|
* Menuhandling: entry */
|
||||||
|
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menugui.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* save the data into the pointer */
|
||||||
|
void menu_entry_save (_menuitem *mi) {
|
||||||
|
switch (mi->type) {
|
||||||
|
case (MENU_entryint):
|
||||||
|
sscanf (mi->keybi.text, "%d", (int *) mi->ptrdata);
|
||||||
|
break;
|
||||||
|
case (MENU_entrytext):
|
||||||
|
strncpy (mi->ptrdata, mi->keybi.text, mi->len);
|
||||||
|
break;
|
||||||
|
case (MENU_entryfloat):
|
||||||
|
sscanf (mi->keybi.text, "%f", (float *) mi->ptrdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* restore the data into the pointer */
|
||||||
|
void menu_entry_restore (_menuitem *mi) {
|
||||||
|
switch (mi->type) {
|
||||||
|
case (MENU_entryint):
|
||||||
|
sprintf (mi->keybi.text, "%d", (int) *mi->ptrdata);
|
||||||
|
break;
|
||||||
|
case (MENU_entrytext):
|
||||||
|
sprintf (mi->keybi.text, "%s", (char*) mi->ptrdata);
|
||||||
|
break;
|
||||||
|
case (MENU_entryfloat):
|
||||||
|
sprintf (mi->keybi.text, "%f", (float) *mi->ptrdata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mi->keybi.curpos = strlen (mi->keybi.text);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* create a entryimages only in the menudatas.. darf all this only when menu_loop
|
||||||
|
* is called */
|
||||||
|
void menu_create_entry (char *name, int x, int y, int w, void *data, int len, int typ, int id) {
|
||||||
|
int i = menu_getlastitem(menu.items);
|
||||||
|
|
||||||
|
if (typ != MENU_entryint && typ != MENU_entryfloat && typ != MENU_entrytext) {
|
||||||
|
d_fatal ("menu_create_entry: wrong typ\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == -1) { /* first entry in the itemslist */
|
||||||
|
menu.items = &menuitems[0];
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
|
||||||
|
d_fatal ("menu_create_entry: MENU_MAXENTRYS reached. Item Ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else { /* add new item to the list */
|
||||||
|
menuitems[i].next = &menuitems[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitems[i].type = typ;
|
||||||
|
menuitems[i].pos.w = (1 + (int)((w - (strlen (name) * font[MENU_BUTTON_FONTSIZE].size.x) - 8 - menu.entryimages[0][0]->w - menu.entryimages[0][2]->w) / menu.entryimages[0][1]->w)) * menu.entryimages[0][1]->w + menu.entryimages[0][0]->w + menu.entryimages[0][2]->w + (strlen (name) * font[MENU_BUTTON_FONTSIZE].size.x) + 8;
|
||||||
|
|
||||||
|
if (x != -1)
|
||||||
|
menuitems[i].pos.x = x;
|
||||||
|
else
|
||||||
|
menuitems[i].pos.x = (menu.oldscreenpos.w - 2 * menu.images[0]->w - menuitems[i].pos.w) / 2;
|
||||||
|
menuitems[i].pos.y = y;
|
||||||
|
menuitems[i].len = len;
|
||||||
|
menuitems[i].ptrdata = (char *) data;
|
||||||
|
menuitems[i].id = id;
|
||||||
|
strncpy (menuitems[i].label, name, MENU_TITLELEN);
|
||||||
|
|
||||||
|
if (typ == MENU_entrytext)
|
||||||
|
keybinput_new (&menuitems[i].keybi, KEYBI_text, len);
|
||||||
|
else if (typ == MENU_entryint)
|
||||||
|
keybinput_new (&menuitems[i].keybi, KEYBI_int, 10);
|
||||||
|
else
|
||||||
|
keybinput_new (&menuitems[i].keybi, KEYBI_float, 10);
|
||||||
|
|
||||||
|
menu_entry_restore (&menuitems[i]);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* draw the menuitem button or bool
|
||||||
|
* menuitem->pos.[x|y|w] - Position and X-Size inside the menu
|
||||||
|
* label - Text of the Button/Bool
|
||||||
|
*/
|
||||||
|
void menu_draw_entry (_menuitem *mi) {
|
||||||
|
int px, py, i;
|
||||||
|
SDL_Rect dest;
|
||||||
|
|
||||||
|
if (mi->type != MENU_entrytext && mi->type != MENU_entryint && mi->type != MENU_entryfloat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dest.x = mi->pos.x;
|
||||||
|
dest.y = mi->pos.y;
|
||||||
|
dest.w = mi->pos.w;
|
||||||
|
dest.h = menu.entryimages[0][0]->h;
|
||||||
|
menu_draw_background (&dest);
|
||||||
|
|
||||||
|
/* check the focus of the button */
|
||||||
|
if (menu.focusvis && mi == menu.focus)
|
||||||
|
mi->state = 1;
|
||||||
|
else
|
||||||
|
mi->state = 0;
|
||||||
|
|
||||||
|
// draw the left side of the button
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + (strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x) + 8;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.entryimages[mi->state][0]->w;
|
||||||
|
dest.h = menu.entryimages[mi->state][0]->h;
|
||||||
|
gfx_blit (menu.entryimages[mi->state][0], NULL, gfx.screen, &dest, 10000);
|
||||||
|
// draw the center of the button
|
||||||
|
for (i = 0; i < ((mi->pos.w - ((strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x) + 8) - (menu.entryimages[mi->state][0]->w + menu.entryimages[mi->state][2]->w)) / menu.entryimages[mi->state][1]->w); i++) {
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + (strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x) + 8 + menu.entryimages[mi->state][0]->w + (i * menu.entryimages[mi->state][1]->w);
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.entryimages[mi->state][1]->w;
|
||||||
|
dest.h = menu.entryimages[mi->state][1]->h;
|
||||||
|
gfx_blit (menu.entryimages[mi->state][1], NULL, gfx.screen, &dest, 10000);
|
||||||
|
}
|
||||||
|
// draw the right side of the button
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.entryimages[mi->state][2]->w;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.entryimages[mi->state][2]->w;
|
||||||
|
dest.h = menu.entryimages[mi->state][2]->h;
|
||||||
|
gfx_blit (menu.entryimages[mi->state][2], NULL, gfx.screen, &dest, 10000);
|
||||||
|
|
||||||
|
// calculate the center of the button
|
||||||
|
px = (strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x) + 8 + (mi->pos.w - (strlen (mi->label) * font[MENU_BUTTON_FONTSIZE].size.x) - 8 - (strlen (mi->keybi.text) * font[MENU_BUTTON_FONTSIZE].size.x)) / 2 + mi->pos.x;
|
||||||
|
py = (menu.entryimages[mi->state][0]->h - font[MENU_BUTTON_FONTSIZE].size.y) / 2 + mi->pos.y;
|
||||||
|
font_gfxdraw (MENUOFFSET_X + px, MENUOFFSET_Y + py, mi->keybi.text, MENU_BUTTON_FONTSIZE, COLOR_yellow, 10000);
|
||||||
|
font_gfxdraw (MENUOFFSET_X + mi->pos.x, MENUOFFSET_Y + py, mi->label, MENU_BUTTON_FONTSIZE, COLOR_yellow, 10000);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* handle the event on the button
|
||||||
|
* on ESC - Reload Old Data
|
||||||
|
* on lose focus - Save Data
|
||||||
|
*/
|
||||||
|
int menu_event_entry (_menuitem *mi, SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case (SDL_KEYDOWN): /* key was pressed */
|
||||||
|
if (event->key.keysym.sym == SDLK_UP)
|
||||||
|
menu_focus_prev ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_DOWN)
|
||||||
|
menu_focus_next ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RETURN || event->key.keysym.sym == SDLK_RCTRL || event->key.keysym.sym == SDLK_RCTRL)
|
||||||
|
menu_entry_save (mi);
|
||||||
|
else if (event->key.keysym.sym == SDLK_ESCAPE)
|
||||||
|
menu_entry_restore (mi);
|
||||||
|
else {
|
||||||
|
keybinput_loop (&mi->keybi, event);
|
||||||
|
menu_draw_entry (mi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (SDL_KEYUP):
|
||||||
|
keybinput_loop (&mi->keybi, event);
|
||||||
|
menu_draw_entry (mi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
@ -0,0 +1,55 @@
|
|||||||
|
/* $Id: menulabels.c,v 1.1 2003/12/24 02:42:06 stpohle Exp $
|
||||||
|
* Menuhandling: labels */
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menugui.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* draw the menuitem label
|
||||||
|
* menuitem->pos.[x|y] - Position inside the menu
|
||||||
|
* pos.w - Fontsize
|
||||||
|
* label - Text of the label
|
||||||
|
*/
|
||||||
|
void menu_draw_label (_menuitem *mi) {
|
||||||
|
int dx, dy;
|
||||||
|
|
||||||
|
if (mi->type != MENU_label)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mi->pos.x == -1)
|
||||||
|
dx = (menu.oldscreenpos.w - (strlen (mi->label) * font[mi->pos.w].size.x)) / 2;
|
||||||
|
else
|
||||||
|
dx = mi->pos.x;
|
||||||
|
if (mi->pos.y == -1)
|
||||||
|
dy = (menu.oldscreenpos.h - font[mi->pos.w].size.y) / 2;
|
||||||
|
else
|
||||||
|
dy = mi->pos.y;
|
||||||
|
|
||||||
|
font_gfxdraw (menu.oldscreenpos.x + menu.images[0]->w + dx, menu.oldscreenpos.y + menu.images[0]->h + dy, mi->label, mi->pos.w, 5, 10000);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void menu_create_label (char *name, int x, int y, int fontsize) {
|
||||||
|
int i = menu_getlastitem(menu.items);
|
||||||
|
|
||||||
|
if (i == -1) { /* first entry in the itemslist */
|
||||||
|
menu.items = &menuitems[0];
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
|
||||||
|
d_fatal ("menu_create_label: MENU_MAXENTRYS reached. Item Ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else { /* add new item to the list */
|
||||||
|
menuitems[i].next = &menuitems[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitems[i].pos.x = x;
|
||||||
|
menuitems[i].pos.y = y;
|
||||||
|
menuitems[i].pos.w = fontsize;
|
||||||
|
menuitems[i].type = MENU_label;
|
||||||
|
strncpy (menuitems[i].label, name, MENU_TITLELEN);
|
||||||
|
};
|
@ -0,0 +1,310 @@
|
|||||||
|
/* $Id: menulists.c,v 1.1 2003/12/24 02:42:06 stpohle Exp $
|
||||||
|
* Menuhandling: lists */
|
||||||
|
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menugui.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* create a entryimages only in the menudatas.. darf all this only when menu_loop
|
||||||
|
* is called */
|
||||||
|
void menu_create_list (char *name, int x, int y, int w, int h, _charlist *data, _charlist **selected, int id) {
|
||||||
|
int i = menu_getlastitem(menu.items);
|
||||||
|
|
||||||
|
if (i == -1) { /* first entry in the itemslist */
|
||||||
|
menu.items = &menuitems[0];
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
else if (i >= MENU_MAXENTRYS) { /* max items reached, ignore new item */
|
||||||
|
d_fatal ("menu_create_entry: MENU_MAXENTRYS reached. Item Ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else { /* add new item to the list */
|
||||||
|
menuitems[i].next = &menuitems[i+1];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menuitems[i].type = MENU_list;
|
||||||
|
menuitems[i].pos.w = (1 + (int)
|
||||||
|
((w - menu.listimages[0][0]->w - menu.listimages[0][2]->w) / menu.listimages[0][1]->w))
|
||||||
|
* menu.listimages[0][1]->w + menu.listimages[0][0]->w + menu.listimages[0][2]->w;
|
||||||
|
menuitems[i].pos.h = (1 + (int)
|
||||||
|
((h - menu.listimages[0][0]->h - menu.listimages[0][6]->h) / menu.listimages[0][3]->h))
|
||||||
|
* menu.listimages[0][3]->h + menu.listimages[0][0]->h + menu.listimages[0][6]->h;
|
||||||
|
if (x != -1)
|
||||||
|
menuitems[i].pos.x = x;
|
||||||
|
else
|
||||||
|
menuitems[i].pos.x = (menu.oldscreenpos.w - 2 * menu.images[0]->w - menuitems[i].pos.w) / 2;
|
||||||
|
menuitems[i].pos.y = y;
|
||||||
|
menuitems[i].ptrdata = (char *) selected;
|
||||||
|
menuitems[i].list = data;
|
||||||
|
menuitems[i].id = id;
|
||||||
|
strncpy (menuitems[i].label, name, MENU_TITLELEN);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* draw only a part of the background */
|
||||||
|
void menu_draw_listbackground (_menuitem *mi, SDL_Rect *updaterect) {
|
||||||
|
int x,y, dx, dy;
|
||||||
|
SDL_Rect dest, cdest, src, csrc, window;
|
||||||
|
|
||||||
|
y = 0; // start at the updaterect. start pos
|
||||||
|
for (; y <= (mi->pos.h - 2*menu.listimages[0][0]->h - 1)/menu.listimages[0][4]->h; y++) {
|
||||||
|
x = 0; // start at the updaterect. start pos
|
||||||
|
for (; x <= (mi->pos.w - 2*menu.listimages[0][0]->w - 1)/menu.listimages[0][4]->w; x++) {
|
||||||
|
dest.x = x * menu.listimages[0][4]->w; // start pos
|
||||||
|
dest.y = y * menu.listimages[0][4]->h;
|
||||||
|
|
||||||
|
dx = (1+x) * menu.listimages[0][4]->w; // end pos
|
||||||
|
if (dx >= (mi->pos.w - 2*menu.listimages[0][0]->w))
|
||||||
|
dest.w = menu.listimages[0][4]->w - (dx - (mi->pos.w - 2*menu.listimages[0][0]->w));
|
||||||
|
else
|
||||||
|
dest.w = menu.listimages[0][4]->w;
|
||||||
|
|
||||||
|
dy = (1+y) * menu.listimages[0][4]->h;
|
||||||
|
if (dy >= (mi->pos.h - 2*menu.listimages[0][0]->h))
|
||||||
|
dest.h = menu.listimages[0][4]->h - (dy - (mi->pos.h - 2*menu.listimages[0][0]->h));
|
||||||
|
else
|
||||||
|
dest.h = menu.listimages[0][4]->h;
|
||||||
|
|
||||||
|
if (dest.w > 0 || dest.h > 0) {
|
||||||
|
dest.x += MENUOFFSET_X + mi->pos.x + menu.listimages[0][0]->w;
|
||||||
|
dest.y += MENUOFFSET_Y + mi->pos.y + menu.listimages[0][0]->h;
|
||||||
|
src.x = 0; src.y = 0; src.h = dest.h; src.w = dest.w;
|
||||||
|
|
||||||
|
if (updaterect == NULL)
|
||||||
|
gfx_blit (menu.listimages[0][4], &src, gfx.screen, &dest, 10000);
|
||||||
|
else {
|
||||||
|
window = *updaterect;
|
||||||
|
window.x += MENUOFFSET_X + mi->pos.x + menu.listimages[0][0]->w;
|
||||||
|
window.y += MENUOFFSET_Y + mi->pos.y + menu.listimages[0][0]->h;
|
||||||
|
rect_clipping (&src, &dest, &window, &csrc, &cdest);
|
||||||
|
if (csrc.w < UINT16_HALF && csrc.h < UINT16_HALF && cdest.w < UINT16_HALF && cdest.h < UINT16_HALF)
|
||||||
|
gfx_blit (menu.listimages[1][4], &csrc, gfx.screen, &cdest, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* gets the number of the selected item
|
||||||
|
* returns the elemennumber or -1 if none where selected */
|
||||||
|
int menu_list_getselected (_menuitem *mi) {
|
||||||
|
int res = -1, i;
|
||||||
|
_charlist *l;
|
||||||
|
|
||||||
|
if (mi == NULL || mi->ptrdata == NULL) return -1;
|
||||||
|
|
||||||
|
for (i = 0, l = mi->list; l != NULL && res == -1; l = l->next, i++)
|
||||||
|
if (l == *((_charlist **)mi->ptrdata))
|
||||||
|
res = i;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* gets the number of elements */
|
||||||
|
int menu_list_getcount (_menuitem *mi) {
|
||||||
|
int count = 0;
|
||||||
|
_charlist *l;
|
||||||
|
|
||||||
|
for (l = mi->list; l != NULL; l = l->next, count++);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* select the element, return 0 if it was not working else 1 */
|
||||||
|
int menu_list_select (_menuitem *mi, int element) {
|
||||||
|
_charlist *l = mi->list;
|
||||||
|
int i = element;
|
||||||
|
|
||||||
|
/* set the new element if there is any */
|
||||||
|
for (; i > 0 && l != NULL; l = l->next, i--);
|
||||||
|
|
||||||
|
// check element
|
||||||
|
if (l == NULL || i < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*(_charlist **)mi->ptrdata = l;
|
||||||
|
|
||||||
|
menu_draw_list (mi);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* select the previous element in the list */
|
||||||
|
void menu_list_select_prev (_menuitem *mi) {
|
||||||
|
int sel = menu_list_getselected(mi);
|
||||||
|
|
||||||
|
if (!menu_list_select (mi, sel - 1))
|
||||||
|
menu_list_select (mi, menu_list_getcount(mi) - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* select the next element in the list */
|
||||||
|
void menu_list_select_next (_menuitem *mi) {
|
||||||
|
int sel = menu_list_getselected (mi);
|
||||||
|
|
||||||
|
if (!menu_list_select (mi, sel + 1))
|
||||||
|
menu_list_select (mi, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* this part will draw the textelement in a list */
|
||||||
|
void menu_draw_listtext (_menuitem *mi) {
|
||||||
|
int count = menu_list_getcount (mi);
|
||||||
|
int selected = menu_list_getselected (mi);
|
||||||
|
int countvis = (mi->pos.h - menu.listimages[0][0]->h - menu.listimages[0][6]->h)
|
||||||
|
/ font[MENU_BUTTON_FONTSIZE].size.y; // number of visible elements
|
||||||
|
_charlist *list;
|
||||||
|
int maxx, // max chars in X
|
||||||
|
dy, // current y position
|
||||||
|
dx, // x position, to start drawing
|
||||||
|
start;// start with this element
|
||||||
|
SDL_Rect wnd; // needed for the selected field to redraw the background
|
||||||
|
char text[255];
|
||||||
|
|
||||||
|
/* start element */
|
||||||
|
if (selected == -1)
|
||||||
|
start = 0;
|
||||||
|
else {
|
||||||
|
if ((start = selected - countvis/2) < 0)
|
||||||
|
start = 0;
|
||||||
|
else if ((start + countvis > count) && (count - countvis >= 0))
|
||||||
|
start = count - countvis;
|
||||||
|
}
|
||||||
|
list = &mi->list[start];
|
||||||
|
|
||||||
|
/* calculate the max numbers of chars to draw */
|
||||||
|
maxx = (mi->pos.w - menu.listimages[0][0]->w - menu.listimages[0][2]->w) / font[MENU_BUTTON_FONTSIZE].size.x;
|
||||||
|
|
||||||
|
/* calculate start point (y) */
|
||||||
|
dy = MENUOFFSET_Y + mi->pos.y + ((mi->pos.h - countvis*font[MENU_BUTTON_FONTSIZE].size.y) / 2);
|
||||||
|
|
||||||
|
/* draw the elements */
|
||||||
|
for (;countvis > 0 && list != NULL; countvis--, list = list->next) {
|
||||||
|
|
||||||
|
/* calculate dx and print only the text which fixs in the list */
|
||||||
|
strncpy (text, list->text, maxx);
|
||||||
|
dx = MENUOFFSET_X + mi->pos.x + ((mi->pos.w - strlen (text)*font[MENU_BUTTON_FONTSIZE].size.x) / 2);
|
||||||
|
|
||||||
|
if (mi->ptrdata != NULL && list == *(_charlist **)mi->ptrdata) {
|
||||||
|
// this is the selected element
|
||||||
|
wnd.x = menu.listimages[0][0]->w;
|
||||||
|
wnd.y = dy;
|
||||||
|
wnd.w = mi->pos.w - menu.listimages[0][0]->w - menu.listimages[0][2]->w;
|
||||||
|
wnd.h = font[MENU_BUTTON_FONTSIZE].size.y;
|
||||||
|
menu_draw_listbackground (mi, &wnd);
|
||||||
|
font_gfxdraw (dx, dy, text, MENU_BUTTON_FONTSIZE, COLOR_black, 10000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
font_gfxdraw (dx, dy, text, MENU_BUTTON_FONTSIZE, COLOR_yellow, 10000);
|
||||||
|
|
||||||
|
dy += font[MENU_BUTTON_FONTSIZE].size.y;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* draw the menuitem button or bool
|
||||||
|
* menuitem->pos.[x|y|w] - Position and X-Size inside the menu
|
||||||
|
* label - Text of the Button/Bool
|
||||||
|
*/
|
||||||
|
void menu_draw_list (_menuitem *mi) {
|
||||||
|
int i, focus;
|
||||||
|
SDL_Rect dest;
|
||||||
|
|
||||||
|
if (mi->type != MENU_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dest.x = mi->pos.x;
|
||||||
|
dest.y = mi->pos.y;
|
||||||
|
dest.w = mi->pos.w;
|
||||||
|
dest.h = menu.listimages[0][0]->h;
|
||||||
|
menu_draw_background (&dest);
|
||||||
|
|
||||||
|
/* check the focus of the button */
|
||||||
|
if (menu.focusvis && mi == menu.focus)
|
||||||
|
focus = 1;
|
||||||
|
else
|
||||||
|
focus = 0;
|
||||||
|
|
||||||
|
// draw the top left and right of the list
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.listimages[focus][0]->w;
|
||||||
|
dest.h = menu.listimages[focus][0]->h;
|
||||||
|
gfx_blit (menu.listimages[focus][0], NULL, gfx.screen, &dest, 10000);
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.listimages[focus][2]->w;
|
||||||
|
gfx_blit (menu.listimages[focus][2], NULL, gfx.screen, &dest, 10000);
|
||||||
|
// draw the bottom left and right of the list
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y + mi->pos.h - menu.listimages[focus][8]->h;
|
||||||
|
gfx_blit (menu.listimages[focus][8], NULL, gfx.screen, &dest, 10000);
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x;
|
||||||
|
gfx_blit (menu.listimages[focus][6], NULL, gfx.screen, &dest, 10000);
|
||||||
|
|
||||||
|
// draw the top and blow center of the list
|
||||||
|
for (i = 0; i < ((mi->pos.w -
|
||||||
|
(menu.listimages[focus][0]->w + menu.listimages[focus][2]->w))
|
||||||
|
/ menu.listimages[focus][1]->w); i++) {
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + menu.listimages[focus][0]->w + (i * menu.listimages[focus][1]->w);
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y;
|
||||||
|
dest.w = menu.listimages[focus][1]->w;
|
||||||
|
dest.h = menu.listimages[focus][1]->h;
|
||||||
|
gfx_blit (menu.listimages[focus][1], NULL, gfx.screen, &dest, 10000);
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y + mi->pos.h - menu.listimages[focus][7]->h;
|
||||||
|
gfx_blit (menu.listimages[focus][7], NULL, gfx.screen, &dest, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the left and the right side of the list
|
||||||
|
for (i = 0; i < ((mi->pos.h -
|
||||||
|
(menu.listimages[focus][0]->h + menu.listimages[focus][6]->h))
|
||||||
|
/ menu.listimages[focus][3]->h); i++) {
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x;
|
||||||
|
dest.y = MENUOFFSET_Y + mi->pos.y + menu.listimages[focus][0]->h + (i * menu.listimages[focus][3]->h);
|
||||||
|
dest.w = menu.listimages[focus][3]->w;
|
||||||
|
dest.h = menu.listimages[focus][3]->h;
|
||||||
|
gfx_blit (menu.listimages[focus][3], NULL, gfx.screen, &dest, 10000);
|
||||||
|
dest.x = MENUOFFSET_X + mi->pos.x + mi->pos.w - menu.listimages[focus][5]->w;
|
||||||
|
gfx_blit (menu.listimages[focus][5], NULL, gfx.screen, &dest, 10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu_draw_listbackground (mi, NULL);
|
||||||
|
menu_draw_listtext (mi);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* handle the event on the button
|
||||||
|
* on ESC - Reload Old Data
|
||||||
|
* on lose focus - Save Data
|
||||||
|
*/
|
||||||
|
int menu_event_list (_menuitem *mi, SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case (SDL_KEYDOWN): /* key was pressed */
|
||||||
|
if (event->key.keysym.sym == SDLK_LEFT)
|
||||||
|
menu_focus_prev ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_RIGHT)
|
||||||
|
menu_focus_next ();
|
||||||
|
else if (event->key.keysym.sym == SDLK_UP)
|
||||||
|
menu_list_select_prev (mi);
|
||||||
|
else if (event->key.keysym.sym == SDLK_DOWN)
|
||||||
|
menu_list_select_next (mi);
|
||||||
|
else if (event->key.keysym.sym == SDLK_RETURN || event->key.keysym.sym == SDLK_RCTRL || event->key.keysym.sym == SDLK_RCTRL)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case (SDL_KEYUP):
|
||||||
|
keybinput_loop (&mi->keybi, event);
|
||||||
|
menu_draw_entry (mi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
@ -0,0 +1,106 @@
|
|||||||
|
/* $Id: netsrvlist.c,v 1.1 2003/12/24 02:42:06 stpohle Exp $
|
||||||
|
* netsrvlist.c - shows a list of possible servers.*/
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "ogcache-client.h"
|
||||||
|
|
||||||
|
_charlist srvlst_text[MAX_SRVLIST];
|
||||||
|
struct __srvlst_entry {
|
||||||
|
char host[LEN_SERVERNAME];
|
||||||
|
char port[LEN_PORT];
|
||||||
|
char gamename[LEN_GAMENAME];
|
||||||
|
int maxplayers;
|
||||||
|
int curplayers;
|
||||||
|
int ai_family;
|
||||||
|
} srvlst_dat[MAX_SRVLIST];
|
||||||
|
int srvlst_cnt = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* will build up our srvlst list with
|
||||||
|
* all servers we have in there */
|
||||||
|
void srvlist_rebuildlist () {
|
||||||
|
int ogclst, i;
|
||||||
|
char text[255];
|
||||||
|
|
||||||
|
d_printf ("srvlist_rebuildlist\n");
|
||||||
|
|
||||||
|
/* delete the whole list */
|
||||||
|
srvlst_cnt = 0;
|
||||||
|
srvlst_text[0].text[0] = 0;
|
||||||
|
srvlst_text[0].next = NULL;
|
||||||
|
|
||||||
|
/* add the OpenGameCache Entrys */
|
||||||
|
if (bman.notifygamemaster) {
|
||||||
|
for (ogclst = 0; ogclst < MAX_OGC_ENTRYS; ogclst++)
|
||||||
|
if (ogc_array[ogclst].serial != -1) {
|
||||||
|
srvlst_dat[srvlst_cnt].host[0] = 0;
|
||||||
|
srvlst_dat[srvlst_cnt].port[0] = 0;
|
||||||
|
srvlst_dat[srvlst_cnt].gamename[0] = 0;
|
||||||
|
|
||||||
|
strncpy (srvlst_dat[srvlst_cnt].host,ogc_array[ogclst].host, LEN_SERVERNAME);
|
||||||
|
strncpy (srvlst_dat[srvlst_cnt].port,ogc_array[ogclst].port, LEN_PORT);
|
||||||
|
strncpy (srvlst_dat[srvlst_cnt].gamename,ogc_array[ogclst].gamename, LEN_GAMENAME);
|
||||||
|
srvlst_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add local server list
|
||||||
|
* - this will have to be finished later -*/
|
||||||
|
|
||||||
|
|
||||||
|
/* add broadcasted list
|
||||||
|
* - this will have to be finished later -*/
|
||||||
|
|
||||||
|
/* make the list viewable */
|
||||||
|
for (i = 0; i < srvlst_cnt; i++) {
|
||||||
|
if (srvlst_dat[i].gamename[0] != 0) /* gamename is present */
|
||||||
|
sprintf (text, "%s", srvlst_dat[i].gamename);
|
||||||
|
else
|
||||||
|
sprintf (text, "%s:%s", srvlst_dat[i].host, srvlst_dat[i].port);
|
||||||
|
strncpy (srvlst_text[i].text, text, LEN_CHARENTRY);
|
||||||
|
}
|
||||||
|
charlist_fillarraypointer (srvlst_text, srvlst_cnt);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* show a list of servers you can select */
|
||||||
|
void net_getserver () {
|
||||||
|
int menuselect = 0, entry = 0;
|
||||||
|
_charlist *sel_entry = &srvlst_text[0];
|
||||||
|
|
||||||
|
d_printf ("net_getserver\n");
|
||||||
|
|
||||||
|
bman.servername[0] = 0;
|
||||||
|
ogc_browsestart ();
|
||||||
|
|
||||||
|
menu_new ("Join a Game", 500, 400);
|
||||||
|
menu_create_list ("Host a Game", -1, 50, 475, 250, srvlst_text, &sel_entry, 1);
|
||||||
|
menu_create_button ("OK", -1, 325, 150, 0);
|
||||||
|
|
||||||
|
while (menuselect != -1 && bman.state != GS_quit) {
|
||||||
|
srvlist_rebuildlist ();
|
||||||
|
menuselect = menu_loop ();
|
||||||
|
|
||||||
|
switch (menuselect) {
|
||||||
|
case (0):
|
||||||
|
// Ok Join Selected Game
|
||||||
|
case (1): // Join a Game
|
||||||
|
entry = &srvlst_text[0] - sel_entry;
|
||||||
|
d_printf ("Selected Entry %s:%s Game:%s\n", srvlst_dat[entry].host, srvlst_dat[entry].port, srvlst_dat[entry].gamename);
|
||||||
|
bman.net_ai_family = srvlst_dat[entry].ai_family;
|
||||||
|
sprintf (bman.servername, "%s:%s", srvlst_dat[entry].host, srvlst_dat[entry].port);
|
||||||
|
menuselect = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ogc_browsestop ();
|
||||||
|
menu_delete ();
|
||||||
|
};
|
@ -0,0 +1,282 @@
|
|||||||
|
/* $Id: ogcache-client.c,v 1.1 2003/12/24 02:42:06 stpohle Exp $
|
||||||
|
* OpenGameCache-Client: this file will hold the protocol for the gameserver communication
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
#include "bomberclone.h"
|
||||||
|
#include "udp.h"
|
||||||
|
#include "ogcache-client.h"
|
||||||
|
|
||||||
|
int ogc_sock = -1;
|
||||||
|
struct game_entry ogc_array[MAX_OGC_ENTRYS];
|
||||||
|
char ogc_host[LEN_OGCHOST];
|
||||||
|
char ogc_port[LEN_OGCPORT];
|
||||||
|
char ogc_game[LEN_GAME];
|
||||||
|
int ogc_ai_family;
|
||||||
|
struct _sockaddr ogc_addr;
|
||||||
|
int ogc_browsing = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* fill out the whole gameentry */
|
||||||
|
static void fill_gameentry (char *pos, struct game_entry *ge) {
|
||||||
|
char *pos_next; /* pointer to the next seperator */
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (pos != NULL)
|
||||||
|
{
|
||||||
|
/* search and test the next seperator */
|
||||||
|
pos_next = strchr (pos, '\t');
|
||||||
|
if (pos_next == NULL)
|
||||||
|
pos_next = strchr (pos, '\n');
|
||||||
|
/* if we found a return delete it..
|
||||||
|
* if we found the tab delete it */
|
||||||
|
if (pos_next != NULL)
|
||||||
|
{
|
||||||
|
if (pos_next[0] == '\n')
|
||||||
|
{ /* RETURN found */
|
||||||
|
pos_next[0] = '\0';
|
||||||
|
pos_next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pos_next[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the struct with our data */
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case (0): /* serial */
|
||||||
|
ge->serial = atoi (pos);
|
||||||
|
break;
|
||||||
|
case (1): /* host */
|
||||||
|
strncpy (ge->host, pos, LEN_OGCHOST);
|
||||||
|
break;
|
||||||
|
case (2): /* port */
|
||||||
|
strncpy (ge->port, pos, LEN_OGCPORT);
|
||||||
|
break;
|
||||||
|
case (3): /* game */
|
||||||
|
strncpy (ge->game, pos, LEN_GAME);
|
||||||
|
break;
|
||||||
|
case (4): /* version */
|
||||||
|
strncpy (ge->version, pos, LEN_VERSION);
|
||||||
|
break;
|
||||||
|
case (5): /* nettype */
|
||||||
|
if (strcmp (pos, "IPv6") == 0)
|
||||||
|
ge->ai_family = PF_INET6;
|
||||||
|
else
|
||||||
|
ge->ai_family = PF_INET;
|
||||||
|
break;
|
||||||
|
case (6): /* netname */
|
||||||
|
strncpy (ge->gamename, pos, LEN_GAMENAME);
|
||||||
|
break;
|
||||||
|
case (7): /* state */
|
||||||
|
strncpy (ge->status, pos, LEN_STATUS);
|
||||||
|
break;
|
||||||
|
case (8): /* curplayers */
|
||||||
|
ge->curplayers = atoi (pos);
|
||||||
|
break;
|
||||||
|
case (9): /* maxplayers */
|
||||||
|
ge->maxplayers = atoi (pos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increase i for the next entry */
|
||||||
|
i++;
|
||||||
|
if (pos_next != NULL)
|
||||||
|
pos = pos_next + 1;
|
||||||
|
else
|
||||||
|
pos = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d_printf ("fill_gameentry [Serial:%d, Addr:%s%s, Game:%s, Gamename:%s\n", ge->serial, ge->host, ge->port, ge->game, ge->gamename);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* add a game to the list or update one */
|
||||||
|
static int ogc_listadd (char *data) {
|
||||||
|
struct game_entry ge;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* fill out the entry and check if there was a problem */
|
||||||
|
fill_gameentry (data, &ge);
|
||||||
|
if (ge.serial == -1) return 0;
|
||||||
|
|
||||||
|
for (i = 0; (i < MAX_OGC_ENTRYS && ogc_array[i].serial != -1 && ogc_array[i].serial != ge.serial); i++);
|
||||||
|
|
||||||
|
if (i < MAX_OGC_ENTRYS && ogc_array[i].serial == ge.serial)
|
||||||
|
ogc_array[i] = ge;
|
||||||
|
else if (i < MAX_OGC_ENTRYS && ogc_array[i].serial == -1)
|
||||||
|
ogc_array[i] = ge;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* delete the game from the list */
|
||||||
|
static int ogc_listdel (char *data) {
|
||||||
|
int i, serial, res = 0;
|
||||||
|
|
||||||
|
serial = atoi (data);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_OGC_ENTRYS; i++)
|
||||||
|
if (ogc_array[i].serial == serial) {
|
||||||
|
ogc_array[i].serial = -1;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* work with the incoming packet */
|
||||||
|
static int ogc_do_inpacket (char *in, int len, struct _sockaddr *addr) {
|
||||||
|
char *param_start = strchr (in, ':');
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* set param_start at the place where the first parameter is
|
||||||
|
* and if there is a : delete this one */
|
||||||
|
if (param_start == NULL) {
|
||||||
|
if ((param_start = strchr (in, '\n')) != NULL) {
|
||||||
|
param_start[0] = '\0';
|
||||||
|
param_start = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
param_start[0] = '\0';
|
||||||
|
param_start++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* work with the incoming data
|
||||||
|
*/
|
||||||
|
if (strcmp (in, "ENTRY") == 0)
|
||||||
|
i = ogc_listadd (param_start);
|
||||||
|
|
||||||
|
else if (strcmp (in, "DELENTRY") == 0)
|
||||||
|
i = ogc_listdel (param_start);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* start a new listen server to get the list */
|
||||||
|
int ogc_init (char *localport, char *server, char *port, char *game, int ai_family) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* check if the socket is still open, if so close it */
|
||||||
|
if (ogc_sock != -1) ogc_shutdown ();
|
||||||
|
|
||||||
|
ogc_sock = udp_server (localport, ai_family);
|
||||||
|
if (ogc_sock <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
strncpy (ogc_host, server, LEN_OGCHOST);
|
||||||
|
strncpy (ogc_port, port, LEN_OGCHOST);
|
||||||
|
strncpy (ogc_game, game, LEN_GAME);
|
||||||
|
ogc_ai_family = ai_family;
|
||||||
|
|
||||||
|
dns_filladdr (ogc_host, LEN_OGCHOST, ogc_port, LEN_OGCPORT, ogc_ai_family, &ogc_addr);
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_OGC_ENTRYS; i++)
|
||||||
|
ogc_array[i].serial = -1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* send the status of the curent game to the game cache */
|
||||||
|
int ogc_sendgamestatus (int sock, char *game, char *version, char *gamename,
|
||||||
|
int curplayers, int maxplayers, char *status) {
|
||||||
|
char data[BUF_SIZE];
|
||||||
|
|
||||||
|
if (sock <= 0 || ogc_sock <= 0) return 0;
|
||||||
|
sprintf (data, "GAME:%s\t%s\t%s", game, version, gamename);
|
||||||
|
if (ogc_ai_family == PF_INET)
|
||||||
|
sprintf (data, "%s\tIPv4", data);
|
||||||
|
else
|
||||||
|
sprintf (data, "%s\tIPv6", data);
|
||||||
|
sprintf (data, "%s\t%d\t%d\t%s", data, curplayers, maxplayers, status);
|
||||||
|
|
||||||
|
udp_send (sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* send to the gamecache that this game has quit */
|
||||||
|
int ogc_sendgamequit (int sock) {
|
||||||
|
char data[BUF_SIZE];
|
||||||
|
|
||||||
|
if (sock <= 0 || ogc_sock <= 0) return 0;
|
||||||
|
|
||||||
|
sprintf (data, "QUIT:");
|
||||||
|
udp_send (sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* send to the gamecache that this browser does not anymore exist */
|
||||||
|
void ogc_shutdown () {
|
||||||
|
if (ogc_sock <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ogc_browsestop ();
|
||||||
|
udp_close (ogc_sock);
|
||||||
|
|
||||||
|
ogc_sock = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* check the socket for incoming data and work
|
||||||
|
* with them if there are any */
|
||||||
|
int ogc_loop () {
|
||||||
|
int len, i = 0;
|
||||||
|
char in[BUF_SIZE];
|
||||||
|
struct _sockaddr inaddr;
|
||||||
|
|
||||||
|
if (ogc_sock <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len = udp_get (ogc_sock, in, BUF_SIZE, &inaddr, ogc_ai_family);
|
||||||
|
|
||||||
|
if (len > 0) { /* we have got something */
|
||||||
|
d_printf ("ogc_got: %s\n", in);
|
||||||
|
i = ogc_do_inpacket (in, len, &inaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* send to the gamecache that we want
|
||||||
|
* to browse through the open games */
|
||||||
|
void ogc_browsestart () {
|
||||||
|
char data[BUF_SIZE];
|
||||||
|
|
||||||
|
if (ogc_sock <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sprintf (data, "LISTGAMES:%s", ogc_game);
|
||||||
|
|
||||||
|
udp_send (ogc_sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
||||||
|
ogc_browsing = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* send the gamecache that we don't want to watch the list no more */
|
||||||
|
void ogc_browsestop () {
|
||||||
|
char data[BUF_SIZE];
|
||||||
|
|
||||||
|
ogc_browsing = 0;
|
||||||
|
if (ogc_sock <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sprintf (data, "LISTQUIT:");
|
||||||
|
|
||||||
|
udp_send (ogc_sock, data, strlen (data), &ogc_addr, ogc_ai_family);
|
||||||
|
};
|
@ -0,0 +1,11 @@
|
|||||||
|
# CROP Files
|
||||||
|
|
||||||
|
SRES=64x640
|
||||||
|
ARES=320x640
|
||||||
|
SPOS=+0+0
|
||||||
|
|
||||||
|
rm -rf crop*
|
||||||
|
rm -rf bomb.bmp
|
||||||
|
|
||||||
|
echo "MONTAGE Fire";
|
||||||
|
montage -tile 5x1 -geometry $SRES fire_single.bmp -geometry $SRES fire_single.bmp -geometry $SRES fire_single.bmp -geometry $SRES fire_single.bmp -geometry $SRES fire_single.bmp -crop $ARES bmp:fireout.bmp
|
@ -0,0 +1,39 @@
|
|||||||
|
# CROP Files
|
||||||
|
|
||||||
|
RES=214x295
|
||||||
|
POS=+211+65
|
||||||
|
|
||||||
|
SRES=93x128
|
||||||
|
SPOS=+0+0
|
||||||
|
|
||||||
|
# 1x20
|
||||||
|
# ARES=93x2560
|
||||||
|
# APOS=+0+0
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1x50
|
||||||
|
# ARES=93x6400
|
||||||
|
# APOS=+0+0
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1x60
|
||||||
|
ARES=93x7680
|
||||||
|
APOS=+0+0
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1x70
|
||||||
|
# ARES=93x8960
|
||||||
|
# APOS=+0+0
|
||||||
|
#
|
||||||
|
|
||||||
|
rm -rf crop*
|
||||||
|
rm -rf out*
|
||||||
|
|
||||||
|
for i in `ls *.bmp`; do
|
||||||
|
echo "CROP & SCALE " $i
|
||||||
|
montage -crop $RES$POS $i -geometry $RES+0+0 bmp:crop-$i
|
||||||
|
mogrify -filter Point -antialias -resize $SRES crop-$i
|
||||||
|
done;
|
||||||
|
|
||||||
|
echo "MONTAGE SingeAnim";
|
||||||
|
montage -tile 1x70 -geometry $SRES crop-*.bmp -crop $ARES bmp:out.bmp
|
@ -0,0 +1,8 @@
|
|||||||
|
# CROP Files
|
||||||
|
|
||||||
|
SRES=64x64
|
||||||
|
ARES=64x320
|
||||||
|
SPOS=+0+0
|
||||||
|
|
||||||
|
echo "MONTAGE Stone";
|
||||||
|
montage -tile 1x5 -geometry $SRES stone0*.bmp -crop $ARES bmp:stone.bmp
|
Loading…
Reference in new issue