2003-07-28 01:47:41 +00:00
|
|
|
/* Copyright (C) 1994-2003 Revolution Software Ltd
|
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*/
|
|
|
|
|
2003-07-28 03:12:49 +00:00
|
|
|
#include "stdafx.h"
|
2003-07-28 01:47:41 +00:00
|
|
|
#include "driver96.h"
|
|
|
|
#include "menu.h"
|
|
|
|
#include "d_draw.h"
|
|
|
|
#include "render.h"
|
2003-08-20 21:17:23 +00:00
|
|
|
#include "common/rect.h"
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
#define MENUDEEP 40
|
|
|
|
#define MAXMENUANIMS 8
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
static uint8 menuStatus[2] = {
|
2003-07-28 01:47:41 +00:00
|
|
|
RDMENU_HIDDEN, RDMENU_HIDDEN
|
|
|
|
};
|
2003-08-20 11:13:13 +00:00
|
|
|
|
2003-08-28 06:36:15 +00:00
|
|
|
static byte *icons[2][RDMENU_MAXPOCKETS] = {
|
2003-08-20 12:08:55 +00:00
|
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
|
|
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
2003-07-28 01:47:41 +00:00
|
|
|
};
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
static uint8 pocketStatus[2][RDMENU_MAXPOCKETS] = {
|
2003-08-20 12:08:55 +00:00
|
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
2003-07-28 01:47:41 +00:00
|
|
|
};
|
|
|
|
|
2003-08-20 11:13:13 +00:00
|
|
|
static uint8 iconCount = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-28 06:36:15 +00:00
|
|
|
void ClearIconArea(int menu, int pocket, ScummVM::Rect *r) {
|
|
|
|
byte *dst;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
r->top = menu * (RENDERDEEP + MENUDEEP) + (MENUDEEP - RDMENU_ICONDEEP) / 2;
|
|
|
|
r->bottom = r->top + RDMENU_ICONDEEP;
|
|
|
|
r->left = RDMENU_ICONSTART + pocket * (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
|
|
|
|
r->right = r->left + RDMENU_ICONWIDE;
|
|
|
|
|
|
|
|
dst = lpBackBuffer + r->top * screenWide + r->left;
|
|
|
|
|
|
|
|
for (i = 0; i < RDMENU_ICONDEEP; i++) {
|
|
|
|
memset(dst, 0, RDMENU_ICONWIDE);
|
|
|
|
dst += screenWide;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* This function should be called regularly to process the menubar system. The
|
|
|
|
* rate at which this function is called will dictate how smooth the menu
|
|
|
|
* system is.
|
|
|
|
*/
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
int32 ProcessMenu(void) {
|
2003-08-28 06:36:15 +00:00
|
|
|
byte *src, *dst;
|
2003-08-21 11:42:27 +00:00
|
|
|
uint8 menu;
|
2003-08-28 06:36:15 +00:00
|
|
|
uint8 i, j;
|
2003-08-21 11:42:27 +00:00
|
|
|
uint8 complete;
|
|
|
|
uint8 frameCount;
|
|
|
|
int32 curx, xoff;
|
|
|
|
int32 cury, yoff;
|
2003-08-28 06:36:15 +00:00
|
|
|
ScummVM::Rect r1, r2;
|
2003-08-21 11:42:27 +00:00
|
|
|
int32 delta;
|
|
|
|
static int32 lastTime = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
if (lastTime == 0) {
|
|
|
|
lastTime = SVM_timeGetTime();
|
|
|
|
frameCount = 1;
|
|
|
|
} else {
|
|
|
|
delta = SVM_timeGetTime() - lastTime;
|
|
|
|
if (delta > 250) {
|
|
|
|
lastTime += delta;
|
|
|
|
delta = 250;
|
|
|
|
frameCount = 1;
|
|
|
|
} else {
|
|
|
|
frameCount = (uint8) ((iconCount + 8) * delta / 750);
|
|
|
|
lastTime += frameCount * 750 / (iconCount + 8);
|
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
while (frameCount-- > 0) {
|
|
|
|
for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) {
|
|
|
|
if (menuStatus[menu] == RDMENU_OPENING) {
|
|
|
|
// The menu is opening, so process it here
|
|
|
|
complete = 1;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Propagate the animation from the first icon.
|
|
|
|
for (i = RDMENU_MAXPOCKETS - 1; i > 0; i--) {
|
|
|
|
pocketStatus[menu][i] = pocketStatus[menu][i - 1];
|
|
|
|
if (pocketStatus[menu][i] != MAXMENUANIMS)
|
|
|
|
complete = 0;
|
|
|
|
}
|
|
|
|
if (pocketStatus[menu][i] != MAXMENUANIMS)
|
|
|
|
complete = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// ... and animate the first icon
|
|
|
|
if (pocketStatus[menu][0] != MAXMENUANIMS)
|
|
|
|
pocketStatus[menu][0]++;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Check to see if the menu is fully open
|
|
|
|
if (complete)
|
|
|
|
menuStatus[menu] = RDMENU_SHOWN;
|
|
|
|
} else if (menuStatus[menu] == RDMENU_CLOSING) {
|
|
|
|
// The menu is closing, so process it here
|
|
|
|
complete = 1;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Propagate the animation from the first icon.
|
|
|
|
for (i = RDMENU_MAXPOCKETS - 1; i > 0; i--) {
|
2003-08-28 06:36:15 +00:00
|
|
|
if (icons[menu][i] && pocketStatus[menu][i] != 0 && pocketStatus[menu][i - 1] == 0) {
|
|
|
|
ClearIconArea(menu, i, &r1);
|
|
|
|
UploadRect(&r1);
|
|
|
|
}
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
pocketStatus[menu][i] = pocketStatus[menu][i - 1];
|
|
|
|
if (pocketStatus[menu][i] != 0)
|
|
|
|
complete = 0;
|
|
|
|
}
|
|
|
|
if (pocketStatus[menu][i] != 0)
|
|
|
|
complete = 0;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// ... and animate the first icon
|
2003-08-28 06:36:15 +00:00
|
|
|
if (pocketStatus[menu][0] != 0) {
|
2003-08-20 21:17:23 +00:00
|
|
|
pocketStatus[menu][0]--;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-28 06:36:15 +00:00
|
|
|
if (pocketStatus[menu][0] == 0) {
|
|
|
|
ClearIconArea(menu, 0, &r1);
|
|
|
|
UploadRect(&r1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if the menu is fully closed
|
2003-08-20 21:17:23 +00:00
|
|
|
if (complete)
|
|
|
|
menuStatus[menu] = RDMENU_HIDDEN;
|
|
|
|
}
|
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
2003-08-20 21:17:23 +00:00
|
|
|
|
|
|
|
// Does the menu need to be drawn?
|
|
|
|
for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) {
|
|
|
|
if (menuStatus[menu] != RDMENU_HIDDEN) {
|
|
|
|
// Draw the menu here.
|
|
|
|
curx = RDMENU_ICONSTART + RDMENU_ICONWIDE / 2;
|
|
|
|
cury = (MENUDEEP / 2) + (RENDERDEEP + MENUDEEP) * menu;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
for (i = 0; i < RDMENU_MAXPOCKETS; i++) {
|
|
|
|
if (icons[menu][i]) {
|
2003-08-28 06:36:15 +00:00
|
|
|
// Since we no longer clear the screen
|
|
|
|
// after each frame we need to clear
|
|
|
|
// the icon area.
|
|
|
|
|
|
|
|
ClearIconArea(menu, i, &r1);
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
if (pocketStatus[menu][i] == MAXMENUANIMS) {
|
|
|
|
xoff = (RDMENU_ICONWIDE / 2);
|
2003-08-28 06:36:15 +00:00
|
|
|
r2.left = curx - xoff;
|
|
|
|
r2.right = r2.left + RDMENU_ICONWIDE;
|
2003-08-20 21:17:23 +00:00
|
|
|
yoff = (RDMENU_ICONDEEP / 2);
|
2003-08-28 06:36:15 +00:00
|
|
|
r2.top = cury - yoff;
|
|
|
|
r2.bottom = r2.top + RDMENU_ICONDEEP;
|
2003-08-20 21:17:23 +00:00
|
|
|
} else {
|
|
|
|
xoff = (RDMENU_ICONWIDE / 2) * pocketStatus[menu][i] / MAXMENUANIMS;
|
2003-08-28 06:36:15 +00:00
|
|
|
r2.left = curx - xoff;
|
|
|
|
r2.right = curx + xoff;
|
2003-08-20 21:17:23 +00:00
|
|
|
yoff = (RDMENU_ICONDEEP / 2) * pocketStatus[menu][i] / MAXMENUANIMS;
|
2003-08-28 06:36:15 +00:00
|
|
|
r2.top = cury - yoff;
|
|
|
|
r2.bottom = cury + yoff;
|
2003-08-20 21:17:23 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-21 11:42:27 +00:00
|
|
|
if (xoff != 0 && yoff != 0) {
|
2003-08-28 06:36:15 +00:00
|
|
|
dst = lpBackBuffer + r2.top * screenWide + r2.left;
|
|
|
|
src = icons[menu][i];
|
2003-08-21 11:42:27 +00:00
|
|
|
|
|
|
|
if (pocketStatus[menu][i] != MAXMENUANIMS) {
|
|
|
|
SquashImage(
|
2003-08-28 06:36:15 +00:00
|
|
|
dst, screenWide, r2.right - r2.left, r2.bottom - r2.top,
|
2003-08-26 06:53:00 +00:00
|
|
|
src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP, NULL);
|
2003-08-21 11:42:27 +00:00
|
|
|
} else {
|
2003-08-28 06:36:15 +00:00
|
|
|
for (j = 0; j < RDMENU_ICONDEEP; j++) {
|
2003-08-21 11:42:27 +00:00
|
|
|
memcpy(dst, src, RDMENU_ICONWIDE);
|
|
|
|
src += RDMENU_ICONWIDE;
|
2003-08-28 06:36:15 +00:00
|
|
|
dst += screenWide;
|
2003-08-21 11:42:27 +00:00
|
|
|
}
|
|
|
|
}
|
2003-08-28 06:36:15 +00:00
|
|
|
UploadRect(&r1);
|
2003-08-20 21:17:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
curx += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);
|
2003-08-28 06:36:15 +00:00
|
|
|
r1.left += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);
|
|
|
|
r1.right += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);
|
2003-08-20 21:17:23 +00:00
|
|
|
}
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
2003-08-20 21:17:23 +00:00
|
|
|
|
2003-07-28 07:22:40 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* This function brings a specified menu into view.
|
|
|
|
* @param menu RDMENU_TOP or RDMENU_BOTTOM, depending on which menu to show
|
|
|
|
* @return RD_OK, or an error code
|
|
|
|
*/
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
int32 ShowMenu(uint8 menu) {
|
|
|
|
// Check for invalid menu parameter
|
2003-07-28 01:47:41 +00:00
|
|
|
if (menu > RDMENU_BOTTOM)
|
2003-08-20 21:17:23 +00:00
|
|
|
return RDERR_INVALIDMENU;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Check that the menu is not currently shown, or in the process of
|
|
|
|
// being shown.
|
|
|
|
if (menuStatus[menu] == RDMENU_SHOWN || menuStatus[menu] == RDMENU_OPENING)
|
|
|
|
return RDERR_INVALIDCOMMAND;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
menuStatus[menu] = RDMENU_OPENING;
|
2003-07-28 07:22:40 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* This function hides a specified menu.
|
|
|
|
* @param menu RDMENU_TOP or RDMENU_BOTTOM depending on which menu to hide
|
|
|
|
* @return RD_OK, or an error code
|
|
|
|
*/
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
int32 HideMenu(uint8 menu) {
|
|
|
|
// Check for invalid menu parameter
|
2003-07-28 01:47:41 +00:00
|
|
|
if (menu > RDMENU_BOTTOM)
|
|
|
|
return(RDERR_INVALIDMENU);
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Check that the menu is not currently hidden, or in the process of
|
|
|
|
// being hidden.
|
|
|
|
if (menuStatus[menu] == RDMENU_HIDDEN || menuStatus[menu] == RDMENU_CLOSING)
|
|
|
|
return RDERR_INVALIDCOMMAND;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
|
|
|
menuStatus[menu] = RDMENU_CLOSING;
|
2003-07-28 07:22:40 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* This function hides both menus immediately.
|
|
|
|
*/
|
|
|
|
|
2003-08-28 06:36:15 +00:00
|
|
|
int32 CloseMenuImmediately(void) {
|
|
|
|
ScummVM::Rect r;
|
|
|
|
int i;
|
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
menuStatus[0] = RDMENU_HIDDEN;
|
|
|
|
menuStatus[1] = RDMENU_HIDDEN;
|
2003-08-28 06:36:15 +00:00
|
|
|
|
|
|
|
for (i = 0; i < RDMENU_MAXPOCKETS; i++) {
|
|
|
|
if (icons[0][i]) {
|
|
|
|
ClearIconArea(0, i, &r);
|
|
|
|
UploadRect(&r);
|
|
|
|
}
|
|
|
|
if (icons[1][i]) {
|
|
|
|
ClearIconArea(1, i, &r);
|
|
|
|
UploadRect(&r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-07-28 01:47:41 +00:00
|
|
|
memset(pocketStatus, 0, sizeof(uint8) * 2 * RDMENU_MAXPOCKETS);
|
2003-08-28 06:36:15 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* This function sets a menubar icon.
|
|
|
|
* @param menu RDMENU_TOP or RDMENU_BOTTOM, depending on which menu to change
|
|
|
|
* @param pocket the menu pocket to change
|
|
|
|
* @param icon icon data, or NULL to clear the icon
|
|
|
|
* @return RD_OK, or an error code
|
|
|
|
*/
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
int32 SetMenuIcon(uint8 menu, uint8 pocket, uint8 *icon) {
|
2003-08-28 06:36:15 +00:00
|
|
|
ScummVM::Rect r;
|
|
|
|
|
2003-08-20 11:13:13 +00:00
|
|
|
debug(5, "stub SetMenuIcon( %d, %d )", menu, pocket);
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Check for invalid menu parameter.
|
2003-07-28 01:47:41 +00:00
|
|
|
if (menu > RDMENU_BOTTOM)
|
2003-08-20 21:17:23 +00:00
|
|
|
return RDERR_INVALIDMENU;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Check for invalid pocket parameter
|
2003-07-28 01:47:41 +00:00
|
|
|
if (pocket >= RDMENU_MAXPOCKETS)
|
2003-08-20 21:17:23 +00:00
|
|
|
return RDERR_INVALIDPOCKET;
|
2003-07-28 01:47:41 +00:00
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// If there is an icon in the requested menu/pocket, clear it out.
|
|
|
|
if (icons[menu][pocket]) {
|
2003-07-28 01:47:41 +00:00
|
|
|
iconCount--;
|
|
|
|
free(icons[menu][pocket]);
|
|
|
|
icons[menu][pocket] = NULL;
|
2003-08-28 06:36:15 +00:00
|
|
|
ClearIconArea(menu, pocket, &r);
|
|
|
|
UploadRect(&r);
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
// Only put the icon in the pocket if it is not NULL
|
|
|
|
if (icon != NULL) {
|
2003-07-28 01:47:41 +00:00
|
|
|
iconCount++;
|
|
|
|
icons[menu][pocket] = (uint8 *) malloc(RDMENU_ICONWIDE * RDMENU_ICONDEEP);
|
|
|
|
if (icons[menu][pocket] == NULL)
|
2003-08-20 21:17:23 +00:00
|
|
|
return RDERR_OUTOFMEMORY;
|
2003-07-28 01:47:41 +00:00
|
|
|
memcpy(icons[menu][pocket], icon, RDMENU_ICONWIDE * RDMENU_ICONDEEP);
|
|
|
|
}
|
2003-07-28 07:22:40 +00:00
|
|
|
return RD_OK;
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:13:57 +00:00
|
|
|
/**
|
|
|
|
* @return The status of the menu
|
|
|
|
*/
|
|
|
|
|
2003-08-20 21:17:23 +00:00
|
|
|
uint8 GetMenuStatus(uint8 menu) {
|
2003-07-28 01:47:41 +00:00
|
|
|
if (menu > RDMENU_BOTTOM)
|
2003-08-20 21:17:23 +00:00
|
|
|
return RDMENU_HIDDEN;
|
|
|
|
return menuStatus[menu];
|
2003-07-28 01:47:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|