Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,437 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/core/imath.h"
#include "m4/graphics/gr_sprite.h"
#include "m4/gui/game_menu.h"
#include "m4/gui/gui_vmng.h"
#include "m4/m4.h"
namespace M4 {
namespace GUI {
int16 SaveLoadMenuBase::SL_THUMBNAIL_W;
int16 SaveLoadMenuBase::SL_THUMBNAIL_H;
int16 SaveLoadMenuBase::SL_DIALOG_BOX;
int16 SaveLoadMenuBase::SL_EMPTY_THUMB_25;
int16 SaveLoadMenuBase::SL_SAVE_BTN_GREY;
int16 SaveLoadMenuBase::SL_SAVE_BTN_NORM;
int16 SaveLoadMenuBase::SL_SAVE_BTN_OVER;
int16 SaveLoadMenuBase::SL_SAVE_BTN_PRESS;
int16 SaveLoadMenuBase::SL_LOAD_BTN_GREY;
int16 SaveLoadMenuBase::SL_LOAD_BTN_NORM;
int16 SaveLoadMenuBase::SL_LOAD_BTN_OVER;
int16 SaveLoadMenuBase::SL_LOAD_BTN_PRESS;
int16 SaveLoadMenuBase::SL_CANCEL_BTN_NORM;
int16 SaveLoadMenuBase::SL_CANCEL_BTN_OVER;
int16 SaveLoadMenuBase::SL_CANCEL_BTN_PRESS;
int16 SaveLoadMenuBase::SL_UP_BTN_GREY_19;
int16 SaveLoadMenuBase::SL_UP_BTN_NORM_13;
int16 SaveLoadMenuBase::SL_UP_BTN_OVER_15;
int16 SaveLoadMenuBase::SL_UP_BTN_PRESS_17;
int16 SaveLoadMenuBase::SL_DOWN_BTN_GREY_20;
int16 SaveLoadMenuBase::SL_DOWN_BTN_NORM_14;
int16 SaveLoadMenuBase::SL_DOWN_BTN_OVER_16;
int16 SaveLoadMenuBase::SL_DOWN_BTN_PRESS_18;
int16 SaveLoadMenuBase::SL_SAVE_LABEL_7;
int16 SaveLoadMenuBase::SL_LOAD_LABEL_9;
int16 SaveLoadMenuBase::SL_SLIDER_BTN_NORM_21;
int16 SaveLoadMenuBase::SL_SLIDER_BTN_OVER_22;
int16 SaveLoadMenuBase::SL_SLIDER_BTN_PRESS_23;
int16 SaveLoadMenuBase::SL_LINE_NORM;
int16 SaveLoadMenuBase::SL_LINE_OVER;
int16 SaveLoadMenuBase::SL_LINE_PRESS;
int16 SaveLoadMenuBase::SL_SCROLL_BAR_24;
int16 SaveLoadMenuBase::SL_TOTAL_SPRITES;
void SaveLoadMenuBase::init() {
SL_DIALOG_BOX = 0;
if (IS_RIDDLE) {
SL_THUMBNAIL_W = 213;
SL_THUMBNAIL_H = 160;
SL_LINE_NORM = 5;
SL_LINE_OVER = 6;
SL_LINE_PRESS = 6;
SL_SAVE_LABEL_7 = 7;
SL_LOAD_LABEL_9 = 9;
SL_UP_BTN_NORM_13 = 13;
SL_DOWN_BTN_NORM_14 = 14;
SL_UP_BTN_OVER_15 = 15;
SL_DOWN_BTN_OVER_16 = 16;
SL_UP_BTN_PRESS_17 = 17;
SL_DOWN_BTN_PRESS_18 = 18;
SL_UP_BTN_GREY_19 = 19;
SL_DOWN_BTN_GREY_20 = 20;
SL_SLIDER_BTN_NORM_21 = 21;
SL_SLIDER_BTN_OVER_22 = 22;
SL_SLIDER_BTN_PRESS_23 = 23;
SL_SCROLL_BAR_24 = 24;
SL_EMPTY_THUMB_25 = 25;
SL_TOTAL_SPRITES = 26;
// Unused
SL_SAVE_BTN_GREY = -1;
SL_SAVE_BTN_NORM = -1;
SL_SAVE_BTN_OVER = -1;
SL_SAVE_BTN_PRESS = -1;
SL_LOAD_BTN_GREY = -1;
SL_LOAD_BTN_NORM = -1;
SL_LOAD_BTN_OVER = -1;
SL_LOAD_BTN_PRESS = -1;
SL_CANCEL_BTN_NORM = -1;
SL_CANCEL_BTN_OVER = -1;
SL_CANCEL_BTN_PRESS = -1;
} else {
SL_THUMBNAIL_W = 215;
SL_THUMBNAIL_H = 162;
SL_EMPTY_THUMB_25 = 1;
SL_SAVE_BTN_GREY = 2;
SL_SAVE_BTN_NORM = 3;
SL_SAVE_BTN_OVER = 4;
SL_SAVE_BTN_PRESS = 5;
SL_LOAD_BTN_GREY = 6;
SL_LOAD_BTN_NORM = 7;
SL_LOAD_BTN_OVER = 8;
SL_LOAD_BTN_PRESS = 9;
SL_CANCEL_BTN_NORM = 10;
SL_CANCEL_BTN_OVER = 11;
SL_CANCEL_BTN_PRESS = 12;
SL_UP_BTN_GREY_19 = 13;
SL_UP_BTN_NORM_13 = 14;
SL_UP_BTN_OVER_15 = 15;
SL_UP_BTN_PRESS_17 = 16;
SL_DOWN_BTN_GREY_20 = 17;
SL_DOWN_BTN_NORM_14 = 18;
SL_DOWN_BTN_OVER_16 = 19;
SL_DOWN_BTN_PRESS_18 = 20;
SL_SAVE_LABEL_7 = 21;
SL_LOAD_LABEL_9 = 22;
SL_SLIDER_BTN_NORM_21 = 23;
SL_SLIDER_BTN_OVER_22 = 24;
SL_SLIDER_BTN_PRESS_23 = 25;
SL_LINE_NORM = 26;
SL_LINE_OVER = 27;
SL_LINE_PRESS = 28;
SL_SCROLL_BAR_24 = 29;
SL_TOTAL_SPRITES = 30;
}
}
void SaveLoadMenuBase::initializeSlotTables() {
const SaveStateList saves = g_engine->listSaves();
// First reset all the slots to empty
for (int i = 0; i < MAX_SLOTS; ++i) {
Common::strcpy_s(_GM(slotTitles)[i], 80, "<empty>");
_GM(slotInUse)[i] = false;
}
for (const auto &save : saves) {
if (save.getSaveSlot() != 0) {
Common::String desc = save.getDescription();
Common::strcpy_s(_GM(slotTitles)[save.getSaveSlot() - 1], 80, desc.c_str());
_GM(slotInUse)[save.getSaveSlot() - 1] = true;
}
}
}
Sprite *SaveLoadMenuBase::menu_CreateThumbnail(int32 *spriteSize) {
Buffer RLE8Buff;
uint8 *srcPtr, *srcPtr2, *srcPtr3, *srcRowPtr, *destPtr;
int32 i, status;
int32 currRow, beginRow;
// Create a Sprite for the thumbNail
Sprite *thumbNailSprite = (Sprite *)mem_alloc(sizeof(Sprite), "sprite");
if (thumbNailSprite == nullptr) {
return nullptr;
}
GrBuff *thumbNail = new GrBuff((MAX_VIDEO_X + 1) / 3, (MAX_VIDEO_Y + 1) / 3);
Buffer *destBuff = thumbNail->get_buffer();
if (!destBuff) {
return nullptr;
}
ScreenContext *gameScreen = vmng_screen_find(_G(gameDrawBuff), &status);
if (!gameScreen || (status != SCRN_ACTIVE)) {
return nullptr;
}
Buffer *scrnBuff = _G(gameDrawBuff)->get_buffer();
if (!scrnBuff) {
return nullptr;
}
// Grab the interface buffer
Buffer *intrBuff = _G(gameInterfaceBuff)->get_buffer();
if (gameScreen->y1 > 0) {
// Paint the top of the thumbnail black
beginRow = gameScreen->y1;
memset(destBuff->data, 21, (beginRow / 3) * destBuff->stride);
srcRowPtr = (uint8 *)(scrnBuff->data + (-gameScreen->x1));
destPtr = (uint8 *)(destBuff->data + ((beginRow / 3) * destBuff->stride));
} else {
srcRowPtr = (uint8 *)(scrnBuff->data + ((-gameScreen->y1) * scrnBuff->stride) + (-gameScreen->x1));
beginRow = 0;
destPtr = destBuff->data;
}
int32 endRow = imath_min(MAX_VIDEO_Y, gameScreen->y2);
for (currRow = beginRow; currRow <= endRow; currRow += 3) {
// Set the src pointers
srcPtr = srcRowPtr;
srcPtr2 = srcRowPtr + scrnBuff->stride;
srcPtr3 = srcRowPtr + (scrnBuff->stride << 1);
for (i = 0; i < (MAX_VIDEO_X + 1) / 3; i++) {
// Calculate the average - make sure not to extend past the end of the buffer
if (endRow - currRow < 1) {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2)) / 3));
} else if (endRow - currRow < 2) {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2) +
*srcPtr2 + *(srcPtr2 + 1) + *(srcPtr2 + 2)) / 6));
} else {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2) +
*srcPtr2 + *(srcPtr2 + 1) + *(srcPtr2 + 2) +
*srcPtr3 + *(srcPtr3 + 1) + *(srcPtr3 + 2)) / 9));
}
if (*destPtr == 0) {
*destPtr = 21;
}
// Increment the pointers
srcPtr += 3;
srcPtr2 += 3;
srcPtr3 += 3;
destPtr++;
}
// Update the row pointer
srcRowPtr += scrnBuff->stride * 3;
}
// Reset the currRow
beginRow = currRow;
// Paint the interface section of the thumbnail
if (currRow < MAX_VIDEO_Y) {
// If the interface is visible, grab it
if (intrBuff) {
srcRowPtr = intrBuff->data;
endRow = imath_min(MAX_VIDEO_Y, beginRow + intrBuff->h - 1);
for (currRow = beginRow; currRow <= endRow; currRow += 3) {
// Set the src pointers
srcPtr = srcRowPtr;
srcPtr2 = srcRowPtr + intrBuff->stride;
srcPtr3 = srcRowPtr + (intrBuff->stride << 1);
for (i = 0; i < (MAX_VIDEO_X + 1) / 3; i++) {
// If the pix is outside of the inventory objects in the interface, set to black
// if ((srcPtr - srcRowPtr < 180) || (srcPtr - srcRowPtr > 575)) {
if (true) { // for now make everything in the interface black
*destPtr = 21;
}
// Else calculate the average - make sure not to extend past the end of the buffer
else {
if (endRow - currRow < 1) {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2)) / 3));
} else if (endRow - currRow < 2) {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2) +
*srcPtr2 + *(srcPtr2 + 1) + *(srcPtr2 + 2)) / 6));
} else {
*destPtr = (uint8)((uint32)((*srcPtr + *(srcPtr + 1) + *(srcPtr + 2) +
*srcPtr2 + *(srcPtr2 + 1) + *(srcPtr2 + 2) +
*srcPtr3 + *(srcPtr3 + 1) + *(srcPtr3 + 2)) / 9));
}
if (*destPtr == 0) {
*destPtr = 21;
}
}
// Increment the pointers
srcPtr += 3;
srcPtr2 += 3;
srcPtr3 += 3;
destPtr++;
}
// Update the row pointer
srcRowPtr += intrBuff->stride * 3;
}
} else {
// Else paint the bottom of the thumbnail black
destPtr = (uint8 *)(destBuff->data + ((currRow / 3) * destBuff->stride));
memset(destPtr, 21, (destBuff->h - (currRow / 3)) * destBuff->stride);
}
}
// Reset the currRow
beginRow = currRow;
if (currRow < MAX_VIDEO_Y) {
// Paint the bottom of the thumbnail black
destPtr = (uint8 *)(destBuff->data + ((currRow / 3) * destBuff->stride));
memset(destPtr, 21, (destBuff->h - (currRow / 3)) * destBuff->stride);
}
// Compress the thumbNail data into the RLE8Buff
if ((*spriteSize = (int32)gr_sprite_RLE8_encode(destBuff, &RLE8Buff)) <= 0) {
return nullptr;
}
// Fill in the Sprite structure
thumbNailSprite->w = destBuff->w;
thumbNailSprite->h = destBuff->h;
thumbNailSprite->encoding = RLE8;
thumbNailSprite->data = nullptr;
thumbNailSprite->sourceHandle = NewHandle(*spriteSize, "thumbNail source");
thumbNailSprite->sourceOffset = 0;
// Now copy the RLE8Buff into the thumbNail source handle
HLock(thumbNailSprite->sourceHandle);
thumbNailSprite->data = (uint8 *)(*(thumbNailSprite->sourceHandle));
memcpy(thumbNailSprite->data, RLE8Buff.data, *spriteSize);
HUnLock(thumbNailSprite->sourceHandle);
// Release all buffers
_G(gameDrawBuff)->release();
if (intrBuff) {
_G(gameInterfaceBuff)->release();
}
thumbNail->release();
// Free up both the thumbNail and the RLE8Buff
delete thumbNail;
mem_free((void *)RLE8Buff.data);
return thumbNailSprite;
}
bool SaveLoadMenuBase::loadThumbnail(int32 slotNum) {
Sprite *&thumbNailSprite = _GM(thumbNails)[slotNum];
return g_engine->loadSaveThumbnail(slotNum + 1, thumbNailSprite);
}
void SaveLoadMenuBase::unloadThumbnail(int32 slotNum) {
if (_GM(thumbNails)[slotNum]->sourceHandle) {
HUnLock(_GM(thumbNails)[slotNum]->sourceHandle);
DisposeHandle(_GM(thumbNails)[slotNum]->sourceHandle);
_GM(thumbNails)[slotNum]->sourceHandle = nullptr;
}
}
void SaveLoadMenuBase::updateThumbnails(int32 firstSlot, guiMenu *myMenu) {
int32 i, startIndex, endIndex;
// Make sure there is something to update
if (firstSlot == _GM(thumbIndex)) {
return;
}
// Ensure firstSlot is in a valid range
firstSlot = imath_max(imath_min(firstSlot, 89), 0);
if (firstSlot > _GM(thumbIndex)) {
// Dump Out all thumbnails in slots which don't overlap
startIndex = _GM(thumbIndex);
endIndex = imath_min(_GM(thumbIndex) + 9, firstSlot - 1);
for (i = startIndex; i <= endIndex; i++) {
unloadThumbnail(i);
}
// Load in all thumbnails missing thumbnails
startIndex = imath_max(_GM(thumbIndex) + 10, firstSlot);
endIndex = imath_min(firstSlot + 9, 98);
for (i = startIndex; i <= endIndex; i++) {
if (_GM(slotInUse)[i]) {
if (!loadThumbnail(i)) {
_GM(slotInUse)[i] = false;
menuItemButton::disableButton(nullptr, 1001 + i - firstSlot, myMenu);
guiMenu::itemRefresh(nullptr, 1001 + i - firstSlot, myMenu);
}
}
}
} else {
// Else firstSlot < _GM(thumbIndex)
// Dump Out all thumbnails in slots which don't overlap
startIndex = imath_max(firstSlot + 10, _GM(thumbIndex));
endIndex = imath_min(_GM(thumbIndex) + 9, 98);
for (i = startIndex; i <= endIndex; i++) {
unloadThumbnail(i);
}
// Load in all thumbnails missing thumbnails
startIndex = firstSlot;
endIndex = imath_min(firstSlot + 9, _GM(thumbIndex) - 1);
for (i = startIndex; i <= endIndex; i++) {
if (_GM(slotInUse)[i]) {
if (!loadThumbnail(i)) {
_GM(slotInUse)[i] = false;
menuItemButton::disableButton(nullptr, 1001 + i - firstSlot, myMenu);
guiMenu::itemRefresh(nullptr, 1001 + i - firstSlot, myMenu);
}
}
}
}
// Set the var
_GM(thumbIndex) = firstSlot;
}
void SaveLoadMenuBase::setFirstSlot(int32 firstSlot, guiMenu *myMenu) {
if (!myMenu) {
return;
}
// Ensure firstSlot is in a valid range
firstSlot = imath_max(imath_min(firstSlot, 89), 0);
// Change the prompt and special tag of each of the slot buttons
for (int32 i = 0; i < MAX_SLOTS_SHOWN; i++) {
menuItemButton *myButton = (menuItemButton *)guiMenu::getItem(i + 1001, myMenu);
myButton->prompt = _GM(slotTitles)[firstSlot + i];
if (_GM(currMenuIsSave) || _GM(slotInUse)[firstSlot + i]) {
myButton->itemFlags = menuItemButton::BTN_STATE_NORM;
} else {
myButton->itemFlags = menuItemButton::BTN_STATE_GREY;
}
myButton->specialTag = firstSlot + i + 1;
guiMenu::itemRefresh(myButton, i + 1001, myMenu);
}
}
} // namespace GUI
} // namespace M4

View File

@@ -0,0 +1,90 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_GAME_MENU_H
#define M4_GUI_GUI_GAME_MENU_H
#include "m4/m4_types.h"
#include "m4/gui/gui_menu_items.h"
namespace M4 {
namespace GUI {
class SaveLoadMenuBase {
public:
static void init();
static int16 SL_THUMBNAIL_W;
static int16 SL_THUMBNAIL_H;
static int16 SL_DIALOG_BOX;
static int16 SL_EMPTY_THUMB_25;
static int16 SL_SAVE_BTN_GREY;
static int16 SL_SAVE_BTN_NORM;
static int16 SL_SAVE_BTN_OVER;
static int16 SL_SAVE_BTN_PRESS;
static int16 SL_LOAD_BTN_GREY;
static int16 SL_LOAD_BTN_NORM;
static int16 SL_LOAD_BTN_OVER;
static int16 SL_LOAD_BTN_PRESS;
static int16 SL_CANCEL_BTN_NORM;
static int16 SL_CANCEL_BTN_OVER;
static int16 SL_CANCEL_BTN_PRESS;
static int16 SL_UP_BTN_GREY_19;
static int16 SL_UP_BTN_NORM_13;
static int16 SL_UP_BTN_OVER_15;
static int16 SL_UP_BTN_PRESS_17;
static int16 SL_DOWN_BTN_GREY_20;
static int16 SL_DOWN_BTN_NORM_14;
static int16 SL_DOWN_BTN_OVER_16;
static int16 SL_DOWN_BTN_PRESS_18;
static int16 SL_SAVE_LABEL_7;
static int16 SL_LOAD_LABEL_9;
static int16 SL_SLIDER_BTN_NORM_21;
static int16 SL_SLIDER_BTN_OVER_22;
static int16 SL_SLIDER_BTN_PRESS_23;
static int16 SL_LINE_NORM;
static int16 SL_LINE_OVER;
static int16 SL_LINE_PRESS;
static int16 SL_SCROLL_BAR_24;
static int16 SL_TOTAL_SPRITES;
static constexpr int16 SL_SAVE_TITLE = 11;
static constexpr int16 SL_LOAD_TITLE = 12;
static constexpr int16 SL_SAVE_LABEL_GREY = 8;
static constexpr int16 SL_LOAD_LABEL_GREY = 10;
protected:
static void initializeSlotTables();
static Sprite *menu_CreateThumbnail(int32 *spriteSize);
static bool loadThumbnail(int32 slotNum);
static void unloadThumbnail(int32 slotNum);
static void setFirstSlot(int32 firstSlot, guiMenu *myMenu);
public:
static void updateThumbnails(int32 firstSlot, guiMenu *myMenu);
};
} // namespace GUI
} // namespace M4
#endif

77
engines/m4/gui/gui.h Normal file
View File

@@ -0,0 +1,77 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_H
#define M4_GUI_GUI_H
#include "m4/m4_types.h"
#include "m4/graphics/gr_buff.h"
namespace M4 {
struct M4sprite {
M4sprite *next = nullptr;
M4sprite *prev = nullptr;
int32 x = 0;
int32 y = 0;
int32 w = 0;
int32 h = 0;
int32 xOffset = 0; // the "hotspot" of the sprite, ie: the registration point
int32 yOffset = 0;
uint8 encoding = 0;
uint8 *data = nullptr;
MemHandle sourceHandle = nullptr;
int32 sourceOffset = 0;
};
struct transSprite {
M4sprite *srcSprite = nullptr;
Buffer *scrnBuffer = nullptr;
};
struct M4Rect {
int32 x1, y1, x2, y2;
};
struct RectList {
RectList *next;
RectList *prev;
int32 x1, y1, x2, y2;
};
struct matte {
matte *nextMatte;
void *myScreen;
int32 x1;
int32 y1;
int32 x2;
int32 y2;
int32 w;
int32 h;
uint8 *SrcBuffer;
uint32 SrcPitch;
};
} // End of namespace M4
#endif

View File

@@ -0,0 +1,145 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/gui_buffer.h"
#include "m4/gui/gui_vmng.h"
#include "m4/vars.h"
namespace M4 {
bool gui_buffer_system_init() {
return true;
}
void gui_buffer_system_shutdown() {
}
static void Buffer_Show(void *s, void *r, void *b, int32 destX, int32 destY) {
ScreenContext *myScreen = (ScreenContext *)s;
RectList *myRectList = (RectList *)r;
Buffer *destBuffer = (Buffer *)b;
RectList *myRect;
// Parameter verification
if (!myScreen) return;
Buffer *myBuffer = (Buffer *)(myScreen->scrnContent);
if (!myBuffer)
return;
// If no destBuffer, then draw directly to video
if (!destBuffer) {
myRect = myRectList;
while (myRect) {
vmng_refresh_video(myRect->x1, myRect->y1, myRect->x1 - myScreen->x1, myRect->y1 - myScreen->y1,
myRect->x2 - myScreen->x1, myRect->y2 - myScreen->y1, myBuffer);
myRect = myRect->next;
}
} else {
// Draw to the dest buffer
myRect = myRectList;
while (myRect) {
gr_buffer_rect_copy_2(myBuffer, destBuffer, myRect->x1 - myScreen->x1, myRect->y1 - myScreen->y1,
destX, destY, myRect->x2 - myRect->x1 + 1, myRect->y2 - myRect->y1 + 1);
myRect = myRect->next;
}
}
}
bool gui_buffer_register(int32 x1, int32 y1, Buffer *myBuf, uint32 scrnFlags, EventHandler evtHandler) {
int32 x2 = x1 + myBuf->w - 1;
int32 y2 = y1 + myBuf->h - 1;
if (!vmng_screen_create(x1, y1, x2, y2, SCRN_BUF, scrnFlags | SF_OFFSCRN, (void *)myBuf,
(RefreshFunc)Buffer_Show, evtHandler))
return false;
return true;
}
void GrBuff_Show(void *s, void *r, void *b, int32 destX, int32 destY) {
ScreenContext *myScreen = (ScreenContext *)s;
RectList *myRectList = (RectList *)r;
Buffer *destBuffer = (Buffer *)b;
RectList *myRect;
// Parameter verification
if (!myScreen)
return;
GrBuff *myGrBuffer = (GrBuff *)myScreen->scrnContent;
if (!myGrBuffer)
return;
Buffer *myBuffer = myGrBuffer->get_buffer();
if (!myBuffer)
return;
// If no destBuffer, then draw directly to video
if (!destBuffer) {
myRect = myRectList;
while (myRect) {
myGrBuffer->refresh_video(myRect->x1, myRect->y1, myRect->x1 - myScreen->x1, myRect->y1 - myScreen->y1,
myRect->x2 - myScreen->x1, myRect->y2 - myScreen->y1);
myRect = myRect->next;
}
} else {
// Else draw to the dest buffer
myRect = myRectList;
while (myRect) {
gr_buffer_rect_copy_2(myBuffer, destBuffer, myRect->x1 - myScreen->x1, myRect->y1 - myScreen->y1,
destX, destY, myRect->x2 - myRect->x1 + 1, myRect->y2 - myRect->y1 + 1);
myRect = myRect->next;
}
}
myGrBuffer->release();
}
bool gui_GrBuff_register(int32 x1, int32 y1, GrBuff *myBuf, uint32 scrnFlags, EventHandler evtHandler) {
return (vmng_screen_create(x1, y1, x1 + myBuf->w - 1, y1 + myBuf->h - 1,
SCRN_BUF, scrnFlags | SF_OFFSCRN, (void *)myBuf,
(RefreshFunc)GrBuff_Show, evtHandler) == nullptr) ? false : true;
}
bool gui_buffer_set_event_handler(void *myBuf, EventHandler evtHandler) {
ScreenContext *myScreen = vmng_screen_find(myBuf, nullptr);
if (myScreen == nullptr)
return false;
myScreen->evtHandler = evtHandler;
return true;
}
void gui_buffer_deregister(void *myBuf) {
vmng_screen_dispose(myBuf);
}
void gui_buffer_activate(Buffer *myBuf) {
vmng_screen_show((void *)myBuf);
}
bool gui_buffer_add_key(Buffer *myBuf, long myKey, HotkeyCB cb) {
return AddScreenHotkey((void *)myBuf, myKey, cb);
}
} // End of namespace M4

View File

@@ -0,0 +1,72 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_BUFFER_H
#define M4_GUI_GUI_BUFFER_H
#include "m4/m4_types.h"
#include "m4/graphics/gr_buff.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
/**
* Initialize any code associated with managing buffers in the GUI
*/
bool gui_buffer_system_init();
/**
* Shutdown any code associated with buffers management
*/
void gui_buffer_system_shutdown();
/**
* Register a Buffer with the view manager by creating a view mananger screen
* @param x1 Where the screen should initially be placed, coords relative
to the top left hand monitor corner.
* @param y1 The screens initial "y" coord
* @param scrnFlags Flags defining the screens: layer, transparency,
moveability, etc.
* @param evtHandler A pointer to the procedure to be executed when
the view manager registers a keyboard or mouse event
* @returns The success of the call
* @remarks The user is responsible for keeping the Buffer *.
Any changes to the contents will be made by the user.
*/
bool gui_buffer_register(int32 x1, int32 y1, Buffer *myBuf, uint32 scrnFlags, EventHandler evtHandler);
void gui_buffer_deregister(void *myBuf);
bool gui_GrBuff_register(int32 x1, int32 y1, GrBuff *myBuf, uint32 scrnFlags, EventHandler evtHandler);
void gui_buffer_activate(Buffer *myBuf);
bool gui_buffer_add_key(Buffer *myBuf, long myKey, HotkeyCB cb);
/**
* Change which procedure will handle the events sent to the screen, which was
* created to managed the Buffer specified.
* @param myBuf The Buffer specified.
* @param evtHandler The new procedure to handle keyboard and mouse events.
*/
bool gui_buffer_set_event_handler(void *myBuf, EventHandler evtHandler);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,530 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/gui_cheapo.h"
#include "m4/gui/gui_vmng_core.h"
#include "m4/gui/gui_vmng_screen.h"
#include "m4/graphics/gr_font.h"
#include "m4/graphics/gr_pal.h"
#include "m4/graphics/gr_series.h"
#include "m4/adv_r/adv_trigger.h"
#include "m4/core/cstring.h"
#include "m4/core/errors.h"
#include "m4/m4.h"
#include "m4/mem/mem.h"
#include "m4/mem/memman.h"
#include "m4/vars.h"
namespace M4 {
namespace GUI {
RectClass::RectClass() {
}
RectClass::RectClass(const RectClass *r) {
if (!r) {
error_show(FL, 'CGNR');
} else {
_x1 = r->_x1;
_y1 = r->_y1;
_x2 = r->_x2;
_y2 = r->_y2;
}
}
RectClass::RectClass(int16 x1, int16 y1, int16 x2, int16 y2) :
_x1(x1), _y1(y1), _x2(x2), _y2(y2) {
}
RectClass::~RectClass() {
}
void RectClass::copyInto(RectClass *r) const {
if (!r) {
error_show(FL, 'CGNR');
} else {
r->_x1 = _x1;
r->_y1 = _y1;
r->_x2 = _x2;
r->_y2 = _y2;
}
}
void RectClass::set(int16 x1, int16 y1, int16 x2, int16 y2) {
_x1 = x1;
_y1 = y1;
_x2 = x2;
_y2 = y2;
}
void RectClass::set(const RectClass *r) {
if (!r) {
error_show(FL, 'CGNR');
} else {
_x1 = r->_x1;
_y1 = r->_y1;
_x2 = r->_x2;
_y2 = r->_y2;
}
}
int16 RectClass::inside(int16 x, int16 y) const {
if ((x >= _x1) && (x <= _x2) && (y >= _y1) && (y <= _y2))
return 1;
return 0;
}
//-------------------------------------------------------------------------------------------
TextField::TextField(int16 x1, int16 y1, int16 x2, int16 y2) :
RectClass(x1, y1, x2, y2) {
_string = nullptr;
_string_len = 0;
_must_redraw = true;
}
TextField::~TextField() {
if (_string != nullptr)
mem_free(_string);
}
void TextField::set_string(const char *string) {
_must_redraw = true;
if (string == nullptr && _string != nullptr) {
_string[0] = '\0';
return;
}
int16 string_len = (int16)(cstrlen(string) + 1);
if (_string == nullptr) {
_string = (char *)mem_alloc(string_len, "string");
} else {
if (_string_len < string_len) {
_string = (char *)mem_realloc(_string, string_len, "string");
}
}
if (!_string)
error_show(FL, 'OOM!', "TextField set_string:%s", _string);
_string_len = string_len;
cstrcpy(_string, string);
}
void TextField::draw(GrBuff *myBuffer) {
if (!INTERFACE_VISIBLE)
return;
Buffer *myBuff = myBuffer->get_buffer();
gr_color_set(__BLACK);
gr_buffer_rect_fill(myBuff, _x1, _y1, _x2 - _x1, _y2 - _y1);
if (IS_RIDDLE) {
gr_font_set_color(gr_pal_get_ega_color(15) & 0xFF);
gr_font_set(_G(font_inter));
} else {
gr_font_set(_G(font_inter));
font_set_colors(1, 2, 3);
}
gr_font_write(myBuff, _string, _x1, _y1, 0, 1);
myBuffer->release();
ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
_must_redraw = false;
}
//-------------------------------------------------------------------------------------------
void ButtonClass::init() {
_relaxed = _over = _picked = 0;
_tag = 0;
_must_redraw = true;
_state = BUTTON_RELAXED;
_tracking = -1;
}
ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag) : RectClass(r) {
init();
_name = btnName;
_tag = tag;
}
ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite) : RectClass(r),
_tag(tag), _unknown(unknown), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
}
ButtonClass::ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
int16 relaxed, int16 over, int16 picked, int sprite) : RectClass(r),
_tag(tag), _unknown(0), _relaxed(relaxed), _over(over), _picked(picked), _sprite(sprite) {
}
ButtonClass::ButtonClass() : RectClass() {
init();
_name = "?";
}
ButtonClass::~ButtonClass() {
zap_resources();
}
void ButtonClass::set_name(const Common::String &btnName) {
_name = btnName;
}
bool ButtonClass::is_hidden() const {
return _hidden;
}
void ButtonClass::set_sprite_relaxed(int16 r) {
_relaxed = r;
}
void ButtonClass::set_sprite_picked(int16 p) {
_picked = p;
}
void ButtonClass::set_sprite_over(int16 o) {
_over = o;
}
void ButtonClass::set_sprite_unknown(int16 val) {
_unknown = val;
}
int16 ButtonClass::get_tag() const {
return _tag;
}
void ButtonClass::zap_resources() {
if (_relaxed)
ClearWSAssets(_WS_ASSET_CELS, _relaxed, _relaxed);
if (_over)
ClearWSAssets(_WS_ASSET_CELS, _over, _over);
if (_picked)
ClearWSAssets(_WS_ASSET_CELS, _picked, _picked);
}
void ButtonClass::set(const ButtonClass *b) {
zap_resources();
_name = b->_name;
_x1 = b->_x1;
_y1 = b->_y1;
_x2 = b->_x2;
_y2 = b->_y2;
_tag = b->_tag;
_relaxed = b->_relaxed;
_over = b->_over;
_picked = b->_picked;
}
void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag) {
_x1 = x1;
_y1 = y1;
_x2 = x2;
_y2 = y2;
_tag = tag;
}
void ButtonClass::set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag,
int16 unknown, int16 relaxed, int16 over, int16 picked, int32 sprite) {
zap_resources();
_x1 = x1;
_y1 = y1;
_x2 = x2;
_y2 = y2;
_tag = tag;
_unknown = unknown;
_relaxed = relaxed;
_over = over;
_picked = picked;
_sprite = sprite;
}
int16 ButtonClass::inside(int16 x, int16 y) const {
if (RectClass::inside(x, y))
return _tag;
return -1;
}
ControlStatus ButtonClass::track(int32 eventType, int16 x, int16 y) {
if (!INTERFACE_VISIBLE)
return NOTHING;
ButtonState old_state = _state;
ControlStatus result = NOTHING;
bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
int16 overTag = inside(x, y);
if (overTag == _tag) {
// if Button is pressed
if (button_clicked) {
if (_tracking == 1) {
result = TRACKING;
} else {
_tracking = 1;
result = IN_CONTROL;
_state = BUTTON_PICKED;
}
_G(inv_suppress_click_sound) = false;
} else {
// if Button isn't pressed
if (_tracking == 1) {
result = SELECTED;
} else {
result = OVER_CONTROL;
}
_state = BUTTON_OVER;
_tracking = -1;
}
} else {
result = NOTHING;
_tracking = -1;
_state = BUTTON_RELAXED;
}
if (old_state != _state)
_must_redraw = true;
return result;
}
void ButtonClass::draw(GrBuff *myBuffer) {
if (!INTERFACE_VISIBLE)
return;
if (!_must_redraw)
return;
Buffer *myBuff = myBuffer->get_buffer();
gr_color_set(__BLACK);
gr_buffer_rect_fill(myBuff, _x1, _y1 - 2, _x2 - _x1, _y2 - _y1 + 2);
if (_hidden == false) {
switch (_state) {
case BUTTON_0:
series_show_frame(_sprite, _unknown, myBuff, _x1, _y1);
break;
case BUTTON_RELAXED:
series_show_frame(_sprite, _relaxed, myBuff, _x1, _y1);
break;
case BUTTON_OVER:
series_show_frame(_sprite, _over, myBuff, _x1, _y1);
break;
case BUTTON_PICKED:
series_show_frame(_sprite, _picked, myBuff, _x1, _y1);
break;
}
}
myBuffer->release();
_must_redraw = false;
ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
RestoreScreensInContext(_x1, _y1 - 2, _x2, _y2, iC);
}
void ButtonClass::hide() {
_hidden = true;
_must_redraw = true;
}
void ButtonClass::unhide() {
_hidden = false;
_must_redraw = true;
}
//-------------------------------------------------------------------------------------------
Toggler::Toggler() : ButtonClass() {
_toggle_state = SELECTED;
_state = BUTTON_PICKED;
}
ControlStatus Toggler::track(int32 eventType, int16 x, int16 y) {
if (!INTERFACE_VISIBLE)
return NOTHING;
ButtonState old_state = _state;
ControlStatus result = NOTHING;
bool button_clicked = (eventType == _ME_L_click) || (eventType == _ME_L_hold) || (eventType == _ME_L_drag);
int16 overTag = inside(x, y);
if (overTag == _tag) {
// if Button is pressed
if (button_clicked) {
_tracking = 1;
result = IN_CONTROL;
} else {
// Button isn't pressed
if (_tracking == 1) {
result = SELECTED;
_toggle_state = (_toggle_state == SELECTED) ? NOTHING : SELECTED;
} else {
result = OVER_CONTROL;
}
_tracking = -1;
}
} else {
if (button_clicked && _tracking == 1) {
result = TRACKING;
} else {
result = NOTHING;
_tracking = -1;
}
}
_state = (_toggle_state == SELECTED) ? BUTTON_PICKED : BUTTON_RELAXED;
if (old_state != _state)
_must_redraw = true;
return result;
}
//-------------------------------------------------------------------------------------------
InterfaceBox::InterfaceBox(const RectClass &r) {
r.copyInto(this);
_highlight_index = -1;
_must_redraw_all = true;
_selected = false;
_index = 0;
for (int16 iter = 0; iter < MAX_BUTTONS; iter++)
_button[iter] = nullptr;
}
InterfaceBox::~InterfaceBox() {
}
int16 InterfaceBox::inside(int16 x, int16 y) const {
if (!_index)
return -1;
if (!RectClass::inside(x, y))
return -1;
int16 iter;
for (iter = 0; iter < _index; iter++) {
if (_button[iter]->inside(x, y))
return _button[iter]->get_tag();
}
return -1;
}
void InterfaceBox::highlight_button(int16 index) {
if (_highlight_index == index) {
return;
}
if (_highlight_index != -1)
_button[_highlight_index]->_must_redraw = true;
if (index == -1)
_selected = false;
_highlight_index = index;
if (_highlight_index != -1)
_button[_highlight_index]->_must_redraw = true;
}
void InterfaceBox::set_selected(bool s) {
if (s == _selected)
return;
_selected = s;
if (_highlight_index != -1)
_button[_highlight_index]->_must_redraw = true;
}
void InterfaceBox::add(ButtonClass *b) {
if (!b) {
error_show(FL, 'CGIA');
} else if (_index >= MAX_BUTTONS) {
error_show(FL, 'CGIA');
} else {
// Convert to global coordinates
b->_x1 += _x1;
b->_x2 += _x1;
b->_y1 += _y1;
b->_y2 += _y1;
_button[_index] = b;
_button[_index]->_must_redraw = true;
++_index;
}
}
ControlStatus InterfaceBox::track(int32 eventType, int16 x, int16 y) {
ControlStatus result = NOTHING;
for (int iter = 0; iter < _index; iter++) {
if (_button[iter]->track(eventType, x, y) == SELECTED) {
_highlight_index = _button[iter]->get_tag();
term_message("selected button: %d", iter);
result = SELECTED;
break;
}
}
return result;
}
void InterfaceBox::draw(GrBuff *myBuffer) {
if (!INTERFACE_VISIBLE)
return;
for (int iter = 0; iter < _index; iter++) {
_button[iter]->_must_redraw |= _must_redraw_all;
_button[iter]->draw(myBuffer);
}
if (_must_redraw_all) {
ScreenContext *iC = vmng_screen_find(_G(gameInterfaceBuff), nullptr);
RestoreScreensInContext(_x1, _y1, _x2, _y2, iC);
}
_must_redraw_all = false;
}
} // namespace GUI
} // namespace M4

164
engines/m4/gui/gui_cheapo.h Normal file
View File

@@ -0,0 +1,164 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_CHEAPO_H
#define M4_GUI_CHEAPO_H
#include "common/str.h"
#include "m4/graphics/gr_buff.h"
#include "m4/m4_types.h"
namespace M4 {
namespace GUI {
constexpr int16 MAX_BUTTONS = 20;
enum ControlStatus {
NOTHING, IN_CONTROL, OVER_CONTROL, SELECTED, TRACKING
};
enum ButtonState {
BUTTON_0, BUTTON_RELAXED, BUTTON_OVER, BUTTON_PICKED
};
class RectClass;
class ButtonClass;
class InterfaceBox;
class RectClass {
public:
int16 _x1 = 0, _x2 = 0, _y1 = 0, _y2 = 0;
public:
RectClass();
RectClass(int16 x1, int16 y1, int16 x2, int16 y2);
RectClass(const RectClass *);
virtual ~RectClass();
virtual int16 inside(int16 x, int16 y) const;
void copyInto(RectClass *r) const;
void set(int16 x1, int16 y1, int16 x2, int16 y2);
void set(const RectClass *r);
};
class TextField : public RectClass {
private:
char *_string = nullptr;
int16 _string_len = 0;
public:
bool _must_redraw = false;
public:
TextField(int16 x1, int16 y1, int16 x2, int16 y2);
~TextField();
void set_string(const char *string);
void draw(GrBuff *interface_buffer);
};
class ButtonClass : public RectClass {
protected:
int16 _tag = 0;
int16 _unknown = 0;
int16 _relaxed = 0;
int16 _over = 0;
int16 _picked = 0;
int16 _tracking = 0;
int32 _sprite = 0;
bool _highlighted = false;
bool _hidden = false;
void init();
void zap_resources();
public:
ButtonState _state = BUTTON_RELAXED;
Common::String _name;
bool _must_redraw = false;
public:
ButtonClass();
ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag);
ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
int16 unknown, int16 relaxed, int16 over, int16 picked, int sprite);
ButtonClass(const RectClass &r, const Common::String &btnName, int16 tag,
int16 relaxed, int16 over, int16 picked, int sprite);
~ButtonClass();
void draw(GrBuff *interface_buffer);
int16 inside(int16 x, int16 y) const override;
virtual ControlStatus track(int32 eventType, int16 x, int16 y);
void set(const ButtonClass *b);
void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag);
void set(int16 x1, int16 y1, int16 x2, int16 y2, int16 tag, int16 unknown,
int16 relaxed, int16 over, int16 picked, int32 sprite);
void set_name(const Common::String &btnName);
int16 get_tag() const;
void hide();
void unhide();
bool is_hidden() const;
void set_sprite_relaxed(int16 r);
void set_sprite_picked(int16 p);
void set_sprite_over(int16 o);
void set_sprite_unknown(int16 val);
};
class Toggler : public ButtonClass {
public:
ControlStatus _toggle_state;
public:
Toggler();
ControlStatus track(int32 eventType, int16 x, int16 y);
};
class InterfaceBox : public RectClass {
private:
bool _selected = false;
int16 _index = 0;
ButtonClass *_button[MAX_BUTTONS] = { nullptr };
public:
int16 _highlight_index = 0;
bool _must_redraw_all = false;
public:
InterfaceBox(const RectClass &r);
~InterfaceBox();
void draw(GrBuff *interface_buffer);
int16 inside(int16 x, int16 y) const override;
ControlStatus track(int32 eventType, int16 x, int16 y);
void add(ButtonClass *b);
int16 check_inventory(int16 x, int16 y);
void highlight_button(int16 index);
void set_selected(bool);
};
} // namespace GUI
} // namespace M4
#endif

File diff suppressed because it is too large Load Diff

185
engines/m4/gui/gui_dialog.h Normal file
View File

@@ -0,0 +1,185 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_DIALOG_H
#define M4_GUI_GUI_DIALOG_H
#include "m4/m4_types.h"
#include "m4/graphics/gr_buff.h"
#include "m4/gui/gui.h"
#include "m4/gui/gui_item.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
enum {
TS_GIVEN = 0, TS_JUST_LEFT, TS_JUST_RIGHT, TS_CENTRE
};
struct Dialog {
int32 w, h;
int32 num_items;
Item *itemList;
Item *listBottom;
Item *cancel_item, *return_item, *default_item;
GrBuff *dlgBuffer;
// General support methods
void destroy();
void refresh();
void resize(int32 newW, int32 newH);
void configure(int32 defaultTag, int32 returnTag, int32 cancelTag);
void setDefault(int32 tag);
bool setPressed(int32 tag);
void show();
// Add methods
bool addMessage(int32 x, int32 y, const char *prompt, int32 tag);
bool addPicture(int32 x, int32 y, Buffer *myBuff, int32 tag);
bool addButton(int32 x, int32 y, const char *prompt, M4CALLBACK cb, int32 tag);
bool addRepeatButton(int32 x, int32 y, const char *prompt, M4CALLBACK cb, int32 tag);
bool addList(int32 x1, int32 y1, int32 x2, int32 y2, M4CALLBACK cb, int32 tag);
// Item Fields
Item *getItem(int32 tag);
void changeItemPrompt(const char *newPrompt, Item *myItem, int32 tag);
bool removeItem(Item *myItem, int32 tag);
void refreshItem(Item *myItem, int32 tag);
// Text Fields
bool addTextField(int32 x1, int32 y1, int32 x2, const char *defaultPrompt, M4CALLBACK cb, int32 tag, int32 fieldLength);
void registerTextField();
};
struct TextScrn {
int32 w, h;
int32 textColor;
int32 textColor_alt1;
int32 textColor_alt2;
int32 hiliteColor;
int32 hiliteColor_alt1;
int32 hiliteColor_alt2;
int32 luminance;
Font *myFont;
TextItem *myTextItems;
TextItem *hiliteItem;
GrBuff *textScrnBuffer;
};
struct Dialog_Globals {
bool okButton = false;
//event handler vars
bool movingScreen = false;
Item *clickItem = nullptr;
Item *doubleClickItem = nullptr;
char listboxSearchStr[80] = { 0 };
};
bool gui_dialog_init();
void gui_dialog_shutdown();
//GENERAL DIALOG SUPPORT
Dialog *DialogCreateAbsolute(int32 x1, int32 y1, int32 x2, int32 y2, uint32 scrnFlags);
Dialog *DialogCreate(M4Rect *r, uint32 scrnFlags);
void vmng_Dialog_Destroy(Dialog *d); //used only by viewmgr.cpp **DO NOT USE
void DialogDestroy(Dialog *d, M4Rect *r = nullptr);
void Dialog_Refresh(Dialog *d);
void Dialog_Refresh_All();
void Dialog_Resize(Dialog *d, int32 newW, int32 newH);
bool GetDialogCoords(Dialog *d, M4Rect *r);
void Dialog_Configure(Dialog *d, int32 defaultTag, int32 returnTag, int32 cancelTag);
void Dialog_SetDefault(Dialog *d, int32 tag);
bool Dialog_SetPressed(Dialog *d, int32 tag);
//MESSAGE TYPE SUPPORT
bool Dialog_Add_Message(Dialog *d, int32 x, int32 y, const char *prompt, int32 tag);
//PICTURE TYPE SUPPORT
bool Dialog_Add_Picture(Dialog *d, int32 x, int32 y, Buffer *myBuff, int32 tag);
//BUTTON TYPE SUPPORT
bool Dialog_Add_Button(Dialog *d, int32 x, int32 y, const char *prompt, M4CALLBACK cb, int32 tag);
bool Dialog_Add_RepeatButton(Dialog *d, int32 x, int32 y, const char *prompt, M4CALLBACK cb, int32 tag);
//LIST TYPE SUPPORT
bool Dialog_Add_List(Dialog *d, int32 x1, int32 y1, int32 x2, int32 y2, M4CALLBACK cb, int32 tag);
bool Dialog_Add_DirList(Dialog *d, int32 x1, int32 y1, int32 x2, int32 y2, M4CALLBACK cb, int32 tag, char *myDir, char *myTypes);
bool Dialog_Change_DirList(Dialog *d, Item *myItem, const char *myDir, const char *myTypes);
bool Dialog_Add_List_Item(Dialog *d, Item *myItem, const char *prompt, int32 tag, int32 listTag, int32 addMode, bool refresh);
bool Dialog_Delete_List_Item(Dialog *d, Item *myItem, int32 tag, ListItem *myListItem, int32 listTag);
bool Dialog_Change_List_Item(Dialog *d, Item *myItem, int32 tag, ListItem *myListItem, int32 listTag, char *newPrompt, int32 newListTag, int32 changeMode, bool refresh);
void Dialog_EmptyListBox(Dialog *d, Item *i, int32 tag);
char *Dialog_GetListItemPrompt(Dialog *d, Item *i, int32 tag, int32 listTag);
ListItem *Dialog_GetCurrListItem(Dialog *d, Item *i, int32 tag);
char *Dialog_GetCurrListItemPrompt(Dialog *d, Item *i, int32 tag);
bool Dialog_GetCurrListItemTag(Dialog *d, Item *i, int32 tag, int32 *listTag);
bool Dialog_ListItemExists(Dialog *d, Item *myItem, int32 tag, char *prompt, int32 listTag);
bool Dialog_ListboxSearch(Dialog *d, Item *myItem, int32 tag, int32 searchMode, char *searchStr, int32 parm1);
void Dialog_GetPrevListItem(Dialog *d);
void Dialog_GetNextListItem(Dialog *d);
//TEXTFIELD TYPE SUPPORT
bool Dialog_Add_TextField(Dialog *d, int32 x1, int32 y1, int32 x2, const char *defaultPrompt, M4CALLBACK cb, int32 tag, int32 fieldLength);
void Dialog_RegisterTextField(Dialog *d);
//HOTKEY SUPPORT
bool Dialog_Add_Key(Dialog *d, long myKey, HotkeyCB cb);
bool Dialog_Remove_Key(Dialog *d, long myKey);
//GENERAL ITEM SUPPORT
Item *Dialog_Get_Item(Dialog *d, int32 tag);
void Dialog_Change_Item_Prompt(Dialog *d, const char *newPrompt, Item *myItem, int32 tag);
bool Dialog_Remove_Item(Dialog *d, Item *myItem, int32 tag);
void Dialog_Refresh_Item(Dialog *d, Item *myItem, int32 tag);
void Dialog_KeyMouseCollision();
void Dialog_SystemError(char *s);
bool sizeofGUIelement_border(int16 el_type, int32 *w, int32 *h);
bool sizeofGUIelement_interior(ButtonDrawRec *bdr, M4Rect *myRect);
bool drawGUIelement(ButtonDrawRec *bdr, M4Rect *myRect);
bool custom_drawGUIelement(ButtonDrawRec *bdr, M4Rect *myRect);
bool custom_sizeofGUIelement_border(int16 el_type, int32 *w, int32 *h);
bool custom_sizeofGUIelement_interior(ButtonDrawRec *bdr, M4Rect *myRect);
//----------------------------------------------------------------------------------------
//TEXTSCRN STUFF...
TextScrn *TextScrn_Create(int32 x1, int32 y1, int32 x2, int32 y2, int32 luminance, uint32 scrnFlags,
int32 textColor, int32 hiliteColor,
int32 textColor_alt1 = 0, int32 hiliteColor_alt1 = 0,
int32 textColor_alt2 = 0, int32 hiliteColor_alt2 = 0);
void vmng_TextScrn_Destroy(TextScrn *myTextScrn);
void TextScrn_Destroy(TextScrn *myTextScrn);
void TextScrn_Activate(TextScrn *myTextScrn);
bool TextScrn_Add_Key(TextScrn *myTextScrn, long myKey, HotkeyCB cb);
bool TextScrn_Add_TextItem(TextScrn *myTextScrn, int32 x, int32 y, int32 tag,
int32 justification, const char *prompt, M4CALLBACK callback);
bool TextScrn_Add_Message(TextScrn *myTextScrn, int32 x, int32 y, int32 tag,
int32 justification, const char *prompt);
void TextScrn_Change_TextItem(TextScrn *myTextScrn, int32 tag, char *prompt, uint8 color);
void TextScrn_Delete_TextItem(TextScrn *myTextScrn, int32 tag);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,36 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_EVENT_H
#define M4_GUI_GUI_EVENT_H
#include "m4/m4_types.h"
namespace M4 {
enum {
EVENT_MOUSE = 0, EVENT_KEY
};
} // End of namespace M4
#endif

1832
engines/m4/gui/gui_item.cpp Normal file

File diff suppressed because it is too large Load Diff

160
engines/m4/gui/gui_item.h Normal file
View File

@@ -0,0 +1,160 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_ITEM_H
#define M4_GUI_GUI_ITEM_H
#include "m4/m4_types.h"
#include "m4/graphics/gr_font.h"
namespace M4 {
#define ITEM_NORMAL 0x00000
#define ITEM_PRESSED 0x00001
#define ITEM_DEFAULT 0x00001
#define ITEM_RETURN 0x00002
#define SU_PRESSED 0x0100
#define SD_PRESSED 0x0200
#define PU_PRESSED 0x0400
#define PD_PRESSED 0x0800
#define THUMB_PRESSED 0x1000
#define BOX_PRESSED 0x2000
#define AREA_PRESSED 0x3f00
#define NO_SCROLL 0x0000
#define SCROLLABLE 0x0001
#define PAGEABLE 0x0002
#define FILL_INTERIOR 1 // a flag for use by DrawTile
#define BORDER 0
enum ItemType {
MESSAGE, PICTURE, BUTTON, LISTBOX, TEXTFIELD, REPEAT_BUTTON, DIALOGBOX
};
enum {
LIST_BY_TAG = 0,
LIST_ALPH,
LIST_SEQUN
};
struct ListItem {
char prompt[80];
int32 tag;
struct ListItem *next;
struct ListItem *prev;
};
struct TextItem {
TextItem *next;
int32 justification;
int32 x;
int32 y;
int32 w;
int32 h;
int32 tag;
int32 type;
char *prompt;
M4CALLBACK callback;
};
struct Item {
Item *next;
Item *prev;
M4CALLBACK callback;
ItemType type;
int32 status;
Font *myFont;
char *prompt;
char *aux;
char *aux2;
int32 promptMax;
int32 myListCount;
int32 viewIndex;
int32 thumbY;
ListItem *myList;
ListItem *currItem;
ListItem *viewTop;
ListItem *viewBottom;
int32 listView;
int32 x, y, w, h;
int32 tag;
};
struct Item_Globals {
char *origPrompt = nullptr;
char *undoPrompt = nullptr;
char *undoAux = nullptr;
char *undoAux2 = nullptr;
Item *currTextField = nullptr;
int32 buttonWidth = 0;
int32 buttonHeight = 0;
char clipBoard[100] = { 0 };
};
bool InitItems(void);
Item *Item_create(Item *parent, enum ItemType type, int32 tag, M4CALLBACK cb);
void Item_destroy(Item *myItem);
void Item_empty_list(Item *myItem);
Item *ItemAdd(Item *itemList, int32 x, int32 y, int32 w, int32 h, const char *prompt, int32 tag,
ItemType type, M4CALLBACK cb, int32 promptMax);
Item *ItemFind(Item *itemList, int32 tag);
bool Item_SetViewBottom(Item *i);
bool ListItemExists(Item *myItem, char *prompt, int32 listTag);
bool ListItemAdd(Item *myItem, char *prompt, int32 listTag, int32 addMode, ListItem *changedItem);
bool ListItemDelete(Item *myItem, ListItem *myListItem, int32 listTag);
bool ListItemChange(Item *myItem, ListItem *myListItem, int32 listTag,
char *newPrompt, int32 newTag, int32 changeMode);
void ViewCurrListItem(Item *myItem);
ListItem *ListItemFind(Item *myItem, int32 searchMode, char *searchStr, int32 parm1);
bool ListItemSearch(Item *myItem, int32 searchMode, char *searchStr, int32 parm1);
bool DoubleClickOnListBox(Item *myItem, int32 xOffset, int32 yOffset);
bool ClickOnListBox(Item *myItem, int32 xOffset, int32 yOffset, int32 scrollType);
bool ResetDefaultListBox(Item *myItem);
bool Item_change_prompt(Item *myItem, const char *newPrompt);
void Item_ClearOrigPrompt(void);
Item *Item_RestoreTextField(void);
Item *Item_CheckTextField(void);
void Item_SaveTextField(Item *myItem);
void SetTextBlockBegin(Item *myItem, int32 relXPos);
void SetTextBlockEnd(Item *myItem, int32 relXPos);
bool Item_TextEdit(Item *myItem, int32 parm1);
bool GetNextListItem(Item *myItem);
bool GetNextPageList(Item *myItem);
bool GetPrevListItem(Item *myItem);
bool GetPrevPageList(Item *myItem);
bool Item_show(Item *i, void *bdrDialog, Buffer *scrBuf, int32 itemType);
void Item_format(Item *i);
Item *Item_set_default(Item *itemList, Item *currDefault, int32 tag);
Item *Item_set_pressed(Item *itemList, Item *myItem, int32 tag);
Item *Item_set_unpressed(Item *itemList, Item *myItem, int32 tag);
Item *Item_set_cancel(Item *itemList, int32 tag);
Item *Item_set_next_default(Item *currDefault, Item *itemList);
Item *Item_set_prev_default(Item *currDefault, Item *listBottom);
} // End of namespace M4
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,395 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_MENU_ITEMS_H
#define M4_GUI_GUI_MENU_ITEMS_H
#include "graphics/surface.h"
#include "m4/m4_types.h"
#include "m4/graphics/gr_buff.h"
#include "m4/gui/gui_univ.h"
#include "m4/graphics/gr_font.h"
namespace M4 {
namespace Burger {
namespace GUI {
enum options_menu_sprites {
OM_DIALOG_BOX,
OM_SLIDER_BTN_NORM,
OM_SLIDER_BTN_OVER,
OM_SLIDER_BTN_PRESS,
OM_SLIDER_BAR,
OM_DONE_BTN_GREY,
OM_DONE_BTN_NORM,
OM_DONE_BTN_OVER,
OM_DONE_BTN_PRESS,
OM_CANCEL_BTN_NORM,
OM_CANCEL_BTN_OVER,
OM_CANCEL_BTN_PRESS,
OM_TOTAL_SPRITES
};
} // namespace GUI
} // namespace Burger
namespace Riddle {
namespace GUI {
enum options_menu_sprites {
OM_DIALOG_BOX,
OM_SLIDER_BTN_NORM = 5,
OM_SLIDER_BTN_OVER = 6,
OM_SLIDER_BTN_PRESS = 7,
OM_SCROLLING_ON_BTN_NORM = 8,
OM_SCROLLING_ON_BTN_OVER = 9,
OM_SCROLLING_ON_BTN_PRESS = 13,
OM_SCROLLING_OFF_BTN_NORM = 11,
OM_SCROLLING_OFF_BTN_OVER = 12,
OM_SCROLLING_OFF_BTN_PRESS = 10,
OM_TOTAL_SPRITES = 14
};
} // namespace GUI
} // namespace Riddle
namespace GUI {
#define _GM(X) ::M4::g_vars->_menu.X
#define LockMouseSprite mouse_lock_sprite
#define UnlockMouseSprite mouse_unlock_sprite
enum save_load_menu_item_tags {
SL_TAG_SAVE = 100,
SL_TAG_SAVE_LABEL,
SL_TAG_LOAD,
SL_TAG_LOAD_LABEL,
SL_TAG_CANCEL,
SL_TAG_SAVE_TITLE_LABEL,
SL_TAG_LOAD_TITLE_LABEL,
SL_TAG_VSLIDER,
SL_TAG_THUMBNAIL
};
struct menuItem;
struct guiMenu;
typedef bool (*ItemHandlerFunction)(menuItem *theItem, int32 eventType, int32 event, int32 x, int32 y, void **currItem);
typedef void (*DrawFunction)(void *source, guiMenu *dest, int32 x1, int32 y1, int32 x2, int32 y2);
typedef void (*DestroyFunction)(menuItem *theItem);
typedef M4CALLBACK CALLBACK;
typedef M4sprite Sprite;
enum game_menu_sprites {
GM_DIALOG_BOX,
GM_BUTTON_GREY,
GM_BUTTON_NORM,
GM_BUTTON_OVER,
GM_BUTTON_PRESS,
GM_TOTAL_SPRITES
};
struct guiMenu;
struct menuItem {
enum {
TEXT_COLOR_GREY_HILITE = 192,
TEXT_COLOR_GREY_FOREGROUND = 210,
TEXT_COLOR_GREY_SHADOW = 229,
TEXT_COLOR_NORM_HILITE = 3,
TEXT_COLOR_NORM_FOREGROUND = 2,
TEXT_COLOR_NORM_SHADOW = 1,
TEXT_COLOR_OVER_HILITE = 3,
TEXT_COLOR_OVER_FOREGROUND = 2,
TEXT_COLOR_OVER_SHADOW = 1,
TEXT_COLOR_PRESS_HILITE = 3,
TEXT_COLOR_PRESS_FOREGROUND = 2,
TEXT_COLOR_PRESS_SHADOW = 1,
};
menuItem *next = nullptr;
menuItem *prev = nullptr;
guiMenu *myMenu = nullptr;
int32 tag = 0;
int32 x1 = 0, y1 = 0, x2 = 0, y2 = 0;
bool transparent = false;
GrBuff *background = nullptr;
CALLBACK callback = nullptr;
DrawFunction redraw = nullptr;
DestroyFunction destroy = nullptr;
ItemHandlerFunction itemEventHandler = nullptr;
static void destroyItem(menuItem *theItem);
static bool cursorInsideItem(menuItem *myItem, int32 cursorX, int32 cursorY);
};
struct menuItemMsg : public menuItem {
private:
static void drawMsg(menuItemMsg *myItem, guiMenu *myMenu, int32 x, int32 y, int32, int32);
public:
int32 itemFlags = 0;
static menuItemMsg *msgAdd(guiMenu *myMenu, int32 tag, int32 x, int32 y, int32 w, int32 h, bool transparent = false);
static void disableMsg(menuItemMsg *myItem, int32 tag, guiMenu *myMenu);
static void enableMsg(menuItemMsg *myItem, int32 tag, guiMenu *myMenu);
};
struct menuItemButton : public menuItem {
private:
static void drawButton(menuItemButton *myItem, guiMenu *myMenu,
int32 x, int32 y, int32, int32);
public:
enum button_states {
BTN_STATE_NORM = 0,
BTN_STATE_OVER = 1,
BTN_STATE_PRESS = 2,
BTN_STATE_GREY = 3
};
enum button_types {
BTN_TYPE_GM_GENERIC,
// Burger
BTN_TYPE_SL_SAVE,
BTN_TYPE_SL_LOAD,
BTN_TYPE_SL_CANCEL,
BTN_TYPE_SL_TEXT,
BTN_TYPE_OM_DONE,
BTN_TYPE_OM_CANCEL,
// Riddle
BTN_TYPE_OM_SCROLLING_ON,
BTN_TYPE_OM_SCROLLING_OFF
};
int32 itemFlags = 0;
int32 buttonType = 0;
const char *prompt = nullptr;
menuItem *assocItem = nullptr;
int32 specialTag = 0;
static menuItemButton *add(guiMenu *myMenu, int32 tag, int32 x, int32 y, int32 w, int32 h, CALLBACK callback = nullptr,
int32 buttonType = 0, bool ghosted = false, bool transparent = false,
const char *prompt = nullptr, ItemHandlerFunction i_handler = (ItemHandlerFunction)handler);
static void disableButton(menuItemButton *myItem, int32 tag, guiMenu *myMenu);
static void enableButton(menuItemButton *myItem, int32 tag, guiMenu *myMenu);
static bool handler(menuItemButton *theItem, int32 eventType, int32 event,
int32 x, int32 y, void **currItem);
};
struct menuItemHSlider : public menuItem {
private:
static void drawHSlider(menuItemHSlider *myItem, guiMenu *myMenu, int32 x, int32 y, int32, int32);
static bool handler(menuItemHSlider *myItem, int32 eventType, int32 event, int32 x, int32 y, void **currItem);
public:
int32 itemFlags = 0;
int32 thumbW = 0, thumbH = 0;
int32 thumbX = 0, maxThumbX = 0;
int32 percent = 0;
enum {
H_THUMB_NORM = 0,
H_THUMB_OVER = 1,
H_THUMB_PRESS = 2
};
static menuItemHSlider *add(guiMenu *myMenu, int32 tag,
int32 x, int32 y, int32 w, int32 h, int32 initPercent = 0,
CALLBACK callback = nullptr, bool transparent = false);
};
struct menuItemVSlider : public menuItem {
private:
static int32 whereIsCursor(menuItemVSlider *myVSlider, int32 y);
public:
int32 itemFlags = 0;
int32 thumbW = 0, thumbH = 0;
int32 thumbY = 0, minThumbY = 0, maxThumbY = 0;
int32 percent = 0;
enum {
VS_NORM = 0x0000,
VS_OVER = 0x0001,
VS_PRESS = 0x0002,
VS_GREY = 0x0003,
VS_STATUS = 0x000f,
VS_UP = 0x0010,
VS_PAGE_UP = 0x0020,
VS_THUMB = 0x0030,
VS_PAGE_DOWN = 0x0040,
VS_DOWN = 0x0050,
VS_COMPONENT = 0x00f0
};
static menuItemVSlider *add(guiMenu *myMenu, int32 tag, int32 x, int32 y, int32 w, int32 h,
int32 initPercent = 0, CALLBACK callback = nullptr, bool transparent = false);
static void disableVSlider(menuItemVSlider *myItem, int32 tag, guiMenu *myMenu);
static void enableVSlider(menuItemVSlider *myItem, int32 tag, guiMenu *myMenu);
static void drawVSlider(menuItemVSlider *myItem, guiMenu *myMenu, int32 x, int32 y, int32, int32);
static bool handler(menuItemVSlider *myItem, int32 eventType, int32 event, int32 x, int32 y, void **currItem);
};
struct menuItemTextField : public menuItem {
int32 itemFlags = 0;
int32 specialTag = 0;
int32 pixWidth = 0;
char prompt[80] = { 0 };
char *promptEnd = nullptr;
char *cursor = nullptr;
enum {
TF_NORM = 0,
TF_OVER = 1,
TF_GREY = 2
};
static menuItemTextField *add(guiMenu *myMenu, int32 tag, int32 x, int32 y, int32 w, int32 h, int32 initFlags,
const char *prompt = nullptr, int32 specialtag = 0, CALLBACK callback = nullptr, bool transparent = false);
static bool handler(menuItemTextField *myItem, int32 eventType, int32 event, int32 x, int32 y, void **currItem);
static void drawTextField(menuItemTextField *myItem, guiMenu *myMenu, int32 x, int32 y, int32, int32);
};
struct guiMenu {
private:
static void show(void *s, void *r, void *b, int32 destX, int32 destY);
static bool eventHandler(guiMenu *theMenu, int32 eventType, int32 parm1, int32 parm2, int32 parm3, bool *currScreen);
public:
GrBuff *menuBuffer = nullptr;
menuItem *itemList = nullptr;
CALLBACK cb_return = nullptr;
CALLBACK cb_esc = nullptr;
EventHandler menuEventHandler = nullptr;
static bool initialize(RGB8 *myPalette);
static void shutdown(bool fadeToColor);
static guiMenu *create(Sprite *backgroundSprite, int32 x1, int32 y1, int32 scrnFlags);
static void destroy(guiMenu *myMenu);
static void configure(guiMenu *myMenu, CALLBACK cb_return, CALLBACK cb_esc);
static GrBuff *copyBackground(guiMenu *myMenu, int32 x, int32 y, int32 w, int32 h);
static menuItem *getItem(int32 tag, guiMenu *myMenu);
static void itemDelete(menuItem *myItem, int32 tag, guiMenu *myMenu);
static void itemRefresh(menuItem *myItem, int32 tag, guiMenu *myMenu);
static bool loadSprites(const char *series, int32 numSprites);
static void unloadSprites();
};
struct MenuGlobals {
//GLOBAL VARS
bool menuSystemInitialized = false;
bool buttonClosesDialog = false;
bool interfaceWasVisible = false;
RGB8 *menuPalette = nullptr;
bool dumpedCodes = false;
bool dumpedBackground = false;
menuItem *menuCurrItem = nullptr;
guiMenu *gameMenu = nullptr;
guiMenu *opMenu = nullptr;
guiMenu *slMenu = nullptr;
guiMenu *errMenu = nullptr;
//menu sprite series vars
char *menuSeriesResource = nullptr;
MemHandle menuSeriesHandle = nullptr;
int32 menuSeriesOffset = 0;
int32 menuSeriesPalOffset = 0;
Font *menuFont = nullptr;
// menu sprites array (used to hold all the sprites for the current menu, spriteCount is set tot he number of sprites in the series)
int32 spriteCount = 0;
Sprite **menuSprites = nullptr;
// VARS SPECIFIC TO THE GAME MENUS SYSTEM
// An array of slot titles used by the save/load menus
char **slotTitles = nullptr;
bool *slotInUse = nullptr;
int32 firstSlotIndex = 0; // Slot at the top of the list on menu
int32 slotSelected = -1; // Slot currently selected
bool deleteSaveDesc = false;
Sprite **thumbNails = nullptr;
Sprite *saveLoadThumbNail = nullptr; // Original used for menu display
Graphics::Surface _thumbnail; // ScummVM version used for savegame
int32 sizeofThumbData = -1;
int32 thumbIndex = 0;
bool currMenuIsSave = true; // Used to determine load or save menu
bool saveLoadFromHotkey = false; // Come from hotkey, not through game menu
bool gameMenuFromMain = false; // Come from main menu, not through escape
int32 remember_digi_volume = 0; // For cancelling out of the options menu
int32 remember_digestability = 0; // For cancelling out of the options menu
~MenuGlobals() {
_thumbnail.free();
}
};
extern void gui_DrawSprite(Sprite *mySprite, Buffer *myBuff, int32 x, int32 y);
//======================================
//
// gamemenu module defines
//
#define MENU_DEPTH 9 // video depth for menu popup boxes
#define MAX_SLOTS 99 // number of save games you can have
#define MAX_SLOTS_SHOWN 8 // number of slots in the scrolling field
} // namespace GUI
} // namespace M4
#endif

View File

@@ -0,0 +1,306 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/gui_mouse.h"
#include "m4/gui/gui_vmng.h"
#include "m4/core/imath.h"
#include "m4/core/mouse.h"
#include "m4/graphics/gr_sprite.h"
#include "m4/mem/res.h"
#include "m4/vars.h"
namespace M4 {
static void transShow(void *s, void *r, void *b, int32 destX, int32 destY);
bool gui_mouse_init() {
_G(mouseBuffer).data = nullptr;
if ((_G(mouseBuffer).data = (uint8 *)mem_alloc(32 * 32, "mouse graphic")) == nullptr) {
return false;
}
_G(mouseBuffer).w = 32;
_G(mouseBuffer).stride = 32;
_G(mouseBuffer).h = 32;
auto &mouseSprite = _G(mouseSprite);
if (!mouseSprite) {
if ((mouseSprite = (M4sprite *)mem_alloc(sizeof(M4sprite), "mouse sprite")) == nullptr) {
return false;
}
mouseSprite->x = 0;
mouseSprite->y = 0;
mouseSprite->w = 32;
mouseSprite->h = 32;
mouseSprite->xOffset = 0;
mouseSprite->yOffset = 0;
mouseSprite->encoding = 0;
mouseSprite->data = GetMousePicture();
mouseSprite->sourceHandle = nullptr;
mouseSprite->sourceOffset = 0;
_G(mouseX1offset) = mouseSprite->xOffset;
_G(mouseY1offset) = mouseSprite->yOffset;
_G(mouseX2offset) = mouseSprite->w - _G(mouseX1offset) - 1;
_G(mouseY2offset) = mouseSprite->h - _G(mouseY1offset) - 1;
}
if ((_G(mouseScreenSource) = (transSprite *)mem_alloc(sizeof(transSprite), "mouse transSprite")) == nullptr) {
return false;
}
_G(mouseScreenSource)->srcSprite = mouseSprite;
_G(mouseScreenSource)->scrnBuffer = &_G(mouseBuffer);
if ((_G(mouseScreen) = vmng_screen_create(0, 0, mouseSprite->w - 1, mouseSprite->h - 1, SCRN_TRANS, SF_MOUSE | SF_OFFSCRN | SF_TRANSPARENT,
(void *)_G(mouseScreenSource), transShow, nullptr)) == nullptr) {
return false;
}
_G(mouseSeriesHandle) = nullptr;
_G(mouseSeriesOffset) = 0;
_G(mouseSeriesPalOffset) = 0;
return true;
}
void gui_mouse_shutdown() {
mem_free(_G(mouseSprite));
gr_buffer_free(&_G(mouseBuffer));
mem_free((void *)_G(mouseScreenSource));
_G(mouseSeriesHandle) = nullptr;
_G(mouseSeriesOffset) = 0;
_G(mouseSeriesPalOffset) = 0;
}
void transShow(void *s, void *r, void *b, int32 destX, int32 destY) {
ScreenContext *myScreen = (ScreenContext *)s;
matte *myRectList = (matte *)r;
Buffer *destBuffer = (Buffer *)b;
Buffer drawSpriteBuff;
DrawRequest spriteDrawReq;
matte *myMatte, tempMatte;
RectList *updateList, *updateRect;
RectList *newUpdateList;
// Parameter verification
if (!myScreen)
return;
transSprite *mySource = (transSprite *)(myScreen->scrnContent);
if (!mySource)
return;
Buffer *myBuff = (Buffer *)(mySource->scrnBuffer);
if (!myBuff)
return;
M4sprite *mySprite = mySource->srcSprite;
if (!mySprite)
return;
// If no destBuffer, then draw directly to video
if (!destBuffer) {
tempMatte.nextMatte = nullptr;
// Loop through the dirty matte list
myMatte = myRectList;
while (myMatte) {
// Create an updateRectList to catch the black areas afterwards
updateList = vmng_CreateNewRect(myMatte->x1, myMatte->y1, myMatte->x2, myMatte->y2);
updateList->prev = nullptr;
updateList->next = nullptr;
// Now loop through all the screens behind myScreen
ScreenContext *tempScreen = myScreen->behind;
while (tempScreen && updateList) {
// Duplicate the updateList
newUpdateList = vmng_DuplicateRectList(updateList);
// Loop through the updateList
updateRect = updateList;
while (updateRect) {
// See if it intersects
tempMatte.x1 = imath_max(updateRect->x1, tempScreen->x1);
tempMatte.y1 = imath_max(updateRect->y1, tempScreen->y1);
tempMatte.x2 = imath_min(updateRect->x2, tempScreen->x2);
tempMatte.y2 = imath_min(updateRect->y2, tempScreen->y2);
if (tempScreen->redraw && (tempMatte.x1 <= tempMatte.x2) && (tempMatte.y1 <= tempMatte.y2)) {
// Draw the intersected part of tempScreen onto myBuffer
(tempScreen->redraw)(tempScreen, (void *)&tempMatte, myBuff, tempMatte.x1 - myScreen->x1, tempMatte.y1 - myScreen->y1);
// Remove that rectangle from the update list
vmng_RemoveRectFromRectList(&newUpdateList, tempMatte.x1, tempMatte.y1, tempMatte.x2, tempMatte.y2);
}
// Get the next updateRect
updateRect = updateRect->next;
}
// The newUpdateList now contains all the pieces not covered by tempScreen;
// turf the update list, and replace it with the newUpdateList
vmng_DisposeRectList(&updateList);
updateList = newUpdateList;
// Now get the next screen
tempScreen = tempScreen->behind;
}
// Now we've gone through all the screens, whatever is left in the updateList should be filled in with black
gr_color_set(__BLACK);
updateRect = updateList;
while (updateRect) {
gr_buffer_rect_fill(myBuff, updateRect->x1 - myScreen->x1, updateRect->y1 - myScreen->y1,
updateRect->x2 - updateRect->x1 + 1, updateRect->y2 - updateRect->y1 + 1);
updateRect = updateRect->next;
}
// Now dispose of the updateList
vmng_DisposeRectList(&updateList);
// And finally, get the next matte
myMatte = myMatte->nextMatte;
}
// Now myBuff should contain a copy of everything on the screen, except the actual contents of this transparent screen
// Now would be the time to draw the contents
if (mySprite->sourceHandle) {
HLock(mySprite->sourceHandle);
mySprite->data = (uint8 *)((intptr)*(mySprite->sourceHandle) + mySprite->sourceOffset);
drawSpriteBuff.w = mySprite->w;
drawSpriteBuff.stride = mySprite->w;
drawSpriteBuff.h = mySprite->h;
drawSpriteBuff.encoding = (mySprite->encoding) & (uint8)0x7f;
drawSpriteBuff.data = mySprite->data;
spriteDrawReq.Src = &drawSpriteBuff;
spriteDrawReq.Dest = myBuff;
spriteDrawReq.x = 0;
spriteDrawReq.y = 0;
spriteDrawReq.scaleX = 100;
spriteDrawReq.scaleY = 100;
spriteDrawReq.srcDepth = 0;
spriteDrawReq.depthCode = nullptr;
spriteDrawReq.Pal = nullptr;
spriteDrawReq.ICT = nullptr;
gr_sprite_draw(&spriteDrawReq);
// Unlock the handle
HUnLock(mySprite->sourceHandle);
} else if (mySprite->data) {
// Else the data for the transparent sprite is stored directly in mySprite->data
// Loop through the rows
for (int32 j = 0; (j < mySprite->h) && (j < myBuff->h); j++) {
// Set the rowPtr and the destPtr
uint8 *rowPtr = mySprite->data + (j * mySprite->w);
uint8 *destPtr = myBuff->data + (j * myBuff->stride);
// Loop through the columns
for (int32 i = 0; (i < mySprite->w) && (i < myBuff->w); i++) {
if (*rowPtr) {
*destPtr = *rowPtr;
}
destPtr++;
rowPtr++;
}
}
}
// Now dump the matte list out to video
myMatte = myRectList;
while (myMatte) {
vmng_refresh_video(myMatte->x1, myMatte->y1, myMatte->x1 - myScreen->x1, myMatte->y1 - myScreen->y1,
myMatte->x2 - myScreen->x1, myMatte->y2 - myScreen->y1, myBuff);
myMatte = myMatte->nextMatte;
}
} else {
// Else draw to the dest buffer
myMatte = myRectList;
while (myMatte) {
gr_buffer_rect_copy_2(myBuff, destBuffer, myMatte->x1 - myScreen->x1, myMatte->y1 - myScreen->y1,
destX, destY, myMatte->x2 - myMatte->x1 + 1, myMatte->y2 - myMatte->y1 + 1);
myMatte = myMatte->nextMatte;
}
}
}
bool mouse_set_sprite(int32 spriteNum) {
if (_G(mouseIsLocked)) {
_G(newMouseNum) = spriteNum;
return true;
}
if (spriteNum == _G(currMouseNum)) {
return true;
}
if (!_G(mouseSeriesHandle) || !*_G(mouseSeriesHandle))
return false;
M4sprite *tempSprite = CreateSprite(_G(mouseSeriesHandle), _G(mouseSeriesOffset), spriteNum,
_G(mouseSprite), nullptr);
if (tempSprite == nullptr)
return false;
_G(mouseSprite) = tempSprite;
_G(mouseX1offset) = _G(mouseSprite)->xOffset;
_G(mouseY1offset) = _G(mouseSprite)->yOffset;
_G(mouseX2offset) = _G(mouseSprite)->w - _G(mouseX1offset) - 1;
_G(mouseY2offset) = _G(mouseSprite)->h - _G(mouseY1offset) - 1;
gui_mouse_refresh();
_G(currMouseNum) = spriteNum;
return true;
}
void gui_mouse_refresh() {
MoveScreenAbs(_G(mouseScreen), _G(mouseX) - _G(mouseX1offset),
_G(mouseY) - _G(mouseY1offset));
}
void mouse_hide() {
vmng_screen_hide(_G(mouseScreenSource));
}
void mouse_show() {
vmng_screen_show(_G(mouseScreenSource));
}
void mouse_lock_sprite(int32 mouseNum) {
_G(mouseIsLocked) = false;
mouse_set_sprite(mouseNum);
_G(mouseIsLocked) = true;
}
void mouse_unlock_sprite() {
_G(mouseIsLocked) = false;
mouse_set_sprite(_G(newMouseNum));
}
} // End of namespace M4

View File

@@ -0,0 +1,80 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_MOUSE_H
#define M4_GUI_GUI_MOUSE_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
#include "m4/mem/reloc.h"
namespace M4 {
constexpr uint32 kArrowCursor = 0;
struct Mouse_Globals {
ScreenContext *_mouseScreen = nullptr;
transSprite *_mouseScreenSource = nullptr;
Buffer _mouseBuffer; // A scratch buffer used by RedrawMouse()
Common::String _mouseSeriesResource;
MemHandle _mouseSeriesHandle = nullptr;
int32 _mouseSeriesOffset = 0;
int32 _mouseSeriesPalOffset = 0;
M4sprite *_mouseSprite = nullptr; // The specific sprite which is drawn to indicate the current mouse position.
int32 _mouseX1offset = 0; // These two are the "x" and "Y" offset into the sprite which will center that
int32 _mouseY1offset = 0; // sprite onto the current mouse position. ie. the mouse "hot spot".
int32 _mouseX2offset = 0; // These two are the horizontal and vertical distances from the mouse "hot spot"
int32 _mouseY2offset = 0; // to the edge of the sprite.
int32 _currMouseNum = 0; // The current index into the sprite series of the sprite which currently is the mouse.
bool _mouseIsLocked = false; // An bool which when TRUE will prevent any other mouse from being set.
int32 _newMouseNum = 0; // An int32 which stores the currMouseNum while the mouse is locked.
int32 _hideMouseX1 = MIN_VIDEO_X - 1; // These 4 represent the mouse "hide" rectangle. The mouse is drawn if'f it is
int32 _hideMouseY1 = MIN_VIDEO_Y - 1; // located within the mouse "show" rectangle (below), or it is not within the
int32 _hideMouseX2 = MIN_VIDEO_X - 1; // mouse "hide" rectangle. ie. If the "hide" rect covers the whole monitor, and
int32 _hideMouseY2 = MIN_VIDEO_Y - 1; // the "show" rectangle covers a specific window, then the mouse will be hidden
// everywhere except within the specific window.
int32 _showMouseX1 = MIN_VIDEO_X; // These 4 represent the mouse "show" rectangle.
int32 _showMouseY1 = MIN_VIDEO_Y;
int32 _showMouseX2 = MAX_VIDEO_X;
int32 _showMouseY2 = MAX_VIDEO_Y;
int32 _mouseX = MAX_VIDEO_X >> 1; // The current mouse "x" position (global coords).
int32 _mouseY = MAX_VIDEO_Y >> 1; // The current mouse "y" position (global coords).
int32 _oldX = MAX_VIDEO_X >> 1; // The previous mouse "x" and "y" position. When the mouse has moved, the
int32 _oldY = MAX_VIDEO_Y >> 1; // position where the mouse sprite was last drawn is here.
};
bool gui_mouse_init();
void gui_mouse_shutdown();
bool mouse_set_sprite(int32 spriteNum);
void gui_mouse_refresh();
void mouse_hide();
void mouse_show();
void mouse_lock_sprite(int32 mouseNum);
void mouse_unlock_sprite();
} // End of namespace M4
#endif

252
engines/m4/gui/gui_sys.cpp Normal file
View File

@@ -0,0 +1,252 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/gui_sys.h"
#include "m4/gui/gui_dialog.h"
#include "m4/gui/gui_event.h"
#include "m4/gui/gui_vmng.h"
#include "m4/mem/memman.h"
#include "m4/vars.h"
namespace M4 {
static bool inScreen(ScreenContext *sc, int32 x, int32 y);
bool gui_system_init() {
_G(systemHotkeys) = nullptr;
return true;
}
void gui_system_shutdown() {
Hotkey *myHotkeys = _G(systemHotkeys);
Hotkey *tempHotkey = myHotkeys;
while (tempHotkey) {
myHotkeys = myHotkeys->next;
mem_free(tempHotkey);
tempHotkey = myHotkeys;
}
}
void gui_system_event_handler() {
ScreenContext *myScreen;
Hotkey *myHotkey;
int32 parm1 = 0;
bool blocked;
bool found;
if (!_G(vmng_Initted))
return;
// Allow pending events to be processed
g_events->process();
// WORKAROUND: Keep the player_info up to date, in case the game
// is saved directly via the GMM without moving the mouse
if (_G(my_walker) && _G(player).walker_in_this_scene &&
_G(player).walker_visible && _G(player).comm_allowed &&
INTERFACE_VISIBLE)
player_update_info();
// Deal with mouse events first..
_G(mouseX) = _G(MouseState).CursorColumn;
_G(mouseY) = _G(MouseState).CursorRow;
const MouseEvent newMouseEvent = mouse_get_event();
if (newMouseEvent != _ME_no_event) { // We have a mouse event
gui_mouse_refresh();
_G(oldX) = _G(mouseX);
_G(oldY) = _G(mouseY);
// currScreen is a global, the address of which is passed to every window's evtHandler.
// If the evtHandler sets currScreen to true, then that window will receive all mouse events,
// regardless of any windows in front of this one, until its evtHandler sets currScreen to false.
if (_G(currScreen)) {
if (_G(eventToScreen)->scrnFlags & SF_GET_MOUSE) {
(_G(eventToScreen)->evtHandler)(_G(eventToScreen)->scrnContent, EVENT_MOUSE,
newMouseEvent, _G(mouseX), _G(mouseY), &_G(currScreen));
}
} else {
myScreen = _G(frontScreen);
blocked = false;
found = false;
// Loop through the active window list, until we find a window which accepts
// mouse events and/or one that blocks them.
while (myScreen && (!found) && (!blocked)) {
if (myScreen->scrnFlags & SF_BLOCK_MOUSE)
blocked = true;
if ((myScreen->scrnFlags & SF_GET_MOUSE) && inScreen(myScreen, _G(mouseX), _G(mouseY)))
found = true; // The mouse must be within the window's
else
myScreen = myScreen->behind; // Boundaries to receive the event.
}
if (found && (myScreen->evtHandler)) {
// NOTE: if the window accepts mouse events, and the mouse is within the window's
// boundaries, the event will never be passed on.
(myScreen->evtHandler)(myScreen->scrnContent, EVENT_MOUSE, newMouseEvent, _G(mouseX), _G(mouseY), &_G(currScreen));
} else {
_G(currScreen) = false;
}
if (_G(currScreen))
_G(eventToScreen) = myScreen;
}
}
// Check keyboard
if (util_kbd_check(&parm1)) {
// Scan window list for windows with event handlers, aborting the scan if we find
// a window which handles or blocks key events. The event is passed to the handler
// if found.
//
bool handled = false;
myScreen = _G(frontScreen);
found = false;
blocked = false;
while (myScreen && (!found) && (!blocked)) { // Loop through windows until we find a window that accepts key events and/or
if (myScreen->scrnFlags & SF_BLOCK_KEY)
blocked = true; // one that blocks them.
if (myScreen->scrnFlags & SF_GET_KEY) {
found = true;
if (myScreen->evtHandler) {
handled = (myScreen->evtHandler)(myScreen->scrnContent, EVENT_KEY, parm1, 0, 0, nullptr);
}
} else myScreen = myScreen->behind;
}
// Scan window list for windows with hotkey lists, aborting the scan if we find
// a window which blocks key events. If the window has a hotkey list, we check if
// the key event matches any of the hotkeys. If it does, scanning aborts, and that
// key's callback is invoked. If it doesn't the search continues.
blocked = false;
while (myScreen && (!blocked) && (!handled)) {
if (myScreen->scrnFlags & SF_BLOCK_KEY)
blocked = true;
if (myScreen->scrnFlags & SF_GET_KEY) {
myHotkey = myScreen->scrnHotkeys;
while (myHotkey && (!handled)) {
if (myHotkey->myKey == parm1) {
handled = true;
_G(currScreen) = false;
Dialog_KeyMouseCollision();
if (myHotkey->callback) {
(myHotkey->callback)((void *)static_cast<intptr>(parm1), (void *)myScreen->scrnContent);
}
} else myHotkey = myHotkey->next;
}
}
myScreen = myScreen->behind;
}
// finally, if no window blocked the key, and no window handled the key, check
// the list of system hotkeys, invoking the callback if one is found.
if ((!handled) && (!blocked)) {
myHotkey = _G(systemHotkeys);
while (myHotkey && (!handled)) {
if (myHotkey->myKey == parm1) {
handled = true;
_G(currScreen) = false;
Dialog_KeyMouseCollision();
if (myHotkey->callback) {
(myHotkey->callback)((void *)static_cast<intptr>(parm1), nullptr);
}
} else myHotkey = myHotkey->next;
}
}
} // end key handling check
}
void AddSystemHotkey(int32 myKey, HotkeyCB callback) {
if (!_G(vmng_Initted)) {
return;
}
Hotkey *myHotkey = _G(systemHotkeys);
while (myHotkey && (myHotkey->myKey != myKey)) {
myHotkey = myHotkey->next;
}
if (myHotkey) {
myHotkey->callback = callback;
} else {
if ((myHotkey = (Hotkey *)mem_alloc(sizeof(Hotkey), "hotkey")) == nullptr) {
return;
}
myHotkey->myKey = myKey;
myHotkey->callback = callback;
myHotkey->next = _G(systemHotkeys);
_G(systemHotkeys) = myHotkey;
}
}
void RemoveSystemHotkey(int32 myKey) {
if (!_G(vmng_Initted))
return;
Hotkey *myHotkey = _G(systemHotkeys);
Hotkey *tempHotkey = myHotkey;
while (myHotkey && (myHotkey->myKey != myKey)) {
if (tempHotkey != myHotkey) tempHotkey = tempHotkey->next;
myHotkey = myHotkey->next;
}
if (myHotkey) {
if (myHotkey == tempHotkey)
_G(systemHotkeys) = _G(systemHotkeys)->next;
else
tempHotkey->next = myHotkey->next;
mem_free(myHotkey);
}
}
HotkeyCB GetSystemHotkey(int32 myKey) {
if (!_G(vmng_Initted))
return (nullptr);
Hotkey *myHotkey = _G(systemHotkeys);
Hotkey *tempHotkey = myHotkey;
while (myHotkey && (myHotkey->myKey != myKey)) {
if (tempHotkey != myHotkey)
tempHotkey = tempHotkey->next;
myHotkey = myHotkey->next;
}
if (myHotkey) {
return myHotkey->callback;
}
return nullptr;
}
static bool inScreen(ScreenContext *sc, int32 x, int32 y) {
if (x >= sc->x1 && x <= sc->x2 && y >= sc->y1 && y <= sc->y2)
return true;
return false;
}
} // End of namespace M4

62
engines/m4/gui/gui_sys.h Normal file
View File

@@ -0,0 +1,62 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_SYS_H
#define M4_GUI_GUI_SYS_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
bool gui_system_init();
void gui_system_shutdown();
/**
* Determine if an event happens, and if so, which window should process the event
* This is the main "engine call" of the GUI. It should be called once each time in the
* applications main loop. All "hot key" call backs, and evtHandlers are executed from here.
*/
void gui_system_event_handler();
/**
* Add a "hot key" to the system (as opposed to a specific window).
* @param myKey The "key" which, when pressed, will cause the callback function to be executed.
* @param callback The function to be executed when "myKey" is pressed.
* @remarks If the view manager has not been initialized, or sizeof(Hotkey) memory is not available,
* the procedure will be aborted.
*/
void AddSystemHotkey(int32 myKey, HotkeyCB callback);
/**
* Remove a "hot key" from the system
*/
void RemoveSystemHotkey(int32 myKey);
/**
* To find the callback associated with a "hot key" in the system
*/
HotkeyCB GetSystemHotkey(int32 myKey);
} // End of namespace M4
#endif

69
engines/m4/gui/gui_univ.h Normal file
View File

@@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_UNIV_H
#define M4_GUI_GUI_UNIV_H
#include "m4/m4_types.h"
#include "m4/gui/gui.h"
namespace M4 {
typedef void (*RefreshFunc)(void *myScreen, void *theRectList, void *destBuffer, int32 destX, int32 destY);
typedef void (*HotkeyCB)(void *myParam, void *myContent);
typedef bool (*EventHandler)(void *scrnContent, int32 eventType,
int32 parm1, int32 parm2, int32 parm3, bool *currScreen);
struct Hotkey {
Hotkey *next;
int32 myKey;
HotkeyCB callback;
};
/**
* The main structure used by the view manager is the ScreenContext
*/
struct ScreenContext {
ScreenContext *infront;
ScreenContext *behind;
int32 x1, y1, x2, y2;
int32 scrnType;
uint32 scrnFlags;
void *scrnContent;
RefreshFunc redraw;
EventHandler evtHandler;
Hotkey *scrnHotkeys;
};
struct ButtonDrawRec {
void *dialog;
Buffer *scrBuf;
M4sprite *sprite;
int32 x1, y1, x2, y2;
int16 el_type;
bool fillMe, pressed;
};
} // End of namespace M4
#endif

67
engines/m4/gui/gui_vmng.h Normal file
View File

@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_VMNG_H
#define M4_GUI_GUI_VMNG_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
#include "m4/gui/gui_vmng_core.h"
#include "m4/gui/gui_vmng_rectangles.h"
#include "m4/gui/gui_vmng_screen.h"
namespace M4 {
enum {
SCRN_DLG = 0, SCRN_BUF, SCRN_TEXT, SCRN_TRANS
};
enum {
SCRN_ANY = 0, SCRN_ACTIVE, SCRN_INACTIVE, SCRN_UNDEFN
};
#define SF_LAYER 0x000f
#define SF_BACKGRND 0x0000
#define SF_DRIFTER 0x0001
#define SF_FLOATER 0x0002
#define SF_SURFACE 0x0003
#define SF_MOUSE 0x000e
#define SF_GET_NONE 0x0000
#define SF_GET_KEY 0x0010
#define SF_GET_MOUSE 0x0020
#define SF_GET_ALL 0x0030
#define SF_BLOCK_NONE 0x0000
#define SF_BLOCK_KEY 0x0040
#define SF_BLOCK_MOUSE 0x0080
#define SF_BLOCK_ALL 0x00c0
#define SF_IMMOVABLE 0x0100 // if set, it ain't draggable
#define SF_OFFSCRN 0x0200 // can be dragged off screen, if it's draggable
#define SF_TRANSPARENT 0x0400 // if the screen is transparent
#define SF_DEFAULT SF_DRIFTER | SF_GET_ALL | SF_BLOCK_NONE
#define SF_ALERT SF_FLOATER | SF_GET_ALL | SF_BLOCK_ALL
} // End of namespace M4
#endif

View File

@@ -0,0 +1,325 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
/**
* THE GUI:
* gui_vmng.cpp controls the windowing system. The gui is comprised of layered independent
* windows. The view manager controls which pieces of each window are visible, and which
* window receives events. The contents of of the windows, whether they be dialog boxes,
* buffers, or some new addition has no bearing on the performance of the view manager.
* Therefore, each window is created with a layer, an event handler, and a redraw function.
* When the view manager determines that an area of a window needs to be redrawn, it
* simply calls that window's redraw function. It is up to the redraw function to ensure
* that the rectangle is properly redrawn. If an event occurs, the view manager will
* determine which window should handle the event.
*
* To recap then, it manages the visual display of each window's current position
* and relative layer, and when either a keyboard event, or mouse event is registered, which
* window's evtHandler will be given the event to process. In addition to requesting a
* window to redraw a portion of itself, or handle an event which has occurred, vmng.cpp
* also displays the mouse in its current location. Through the use of an off screen bitmap
* which is an exact duplicate of what is visible on the monitor, the view manager creates
* a flicker-free graphical display of the mouse and all visible windows.
*
* NOTE: FOR MANY OF THE FOLLOWING PROCEDURES, A "void *scrnContent" IS LISTED AMONG THE
* PARAMETERS. THIS PARAMETER REFERS TO THE STRUCTURE FOR WHICH THE WINDOW WAS CREATED, BE
* IT A (Buffer*), (Dialog*), (TextScrn*), OR WHATEVER. SINCE THE VIEW MANAGER ONLY
* REQUESTS WINDOW REFRESHES AND PASSES EVENTS, THE CONTENTS OF THE WINDOW ARE UNKNOWN,
* AND THEREFORE, ALL ARE STORED AS (void*). FROM NOW ON, THIS WILL BE KNOWN AS THE "WINDOW
* IDENTIFIER".
*
* NOTE: THE TERM "WINDOW" AND THE TERM "SCREEN" ARE COMPLETELY INTERCHANGEABLE DURING
* THE DOCUMENTATION OF ANY GUI SOURCE CODE.
*
* NOTE: ANY PROCEDURE IN THIS FILE WHICH, WHEN EXECUTED, RESULTS IN A VISUAL CHANGE TO
* THE MONITOR (SUCH AS vmng_screen_show(), or MoveScreen())
* WILL ALSO RESTORE THE MONITOR'S IMAGE, TAKING CARE OF A VIDEO REFRESH REQUIREMENTS.
*/
#include "common/system.h"
#include "graphics/surface.h"
#include "m4/gui/gui_vmng.h"
#include "m4/gui/gui_dialog.h"
#include "m4/core/imath.h"
#include "m4/mem/memman.h"
#include "m4/mem/mem.h"
#include "m4/vars.h"
namespace M4 {
bool vmng_init() {
if (_G(vmng_Initted))
return false;
_G(vmng_Initted) = true;
_G(frontScreen) = nullptr;
_G(backScreen) = nullptr;
_G(inactiveScreens) = nullptr;
if (!mem_register_stash_type(&_G(memtypeSCRN), sizeof(ScreenContext), 32, "+SCRN")) {
return false;
}
if (!mem_register_stash_type(&_G(memtypeMATTE), sizeof(matte), 32, "+guiMATTE")) {
return false;
}
if (!mem_register_stash_type(&_G(memtypeRECT), sizeof(RectList), 256, "+guiRecList")) {
return false;
}
return true;
}
void vmng_shutdown() {
Hotkey *myHotkeys, *tempHotkey;
if (!_G(vmng_Initted))
return;
_G(vmng_Initted) = false;
// First, destroy all active windows
ScreenContext *myScreen = _G(frontScreen);
while (myScreen) {
_G(frontScreen) = _G(frontScreen)->behind;
if (myScreen->scrnType == SCRN_DLG) {
vmng_Dialog_Destroy((Dialog *)myScreen->scrnContent);
} else if (myScreen->scrnType == SCRN_TEXT) {
vmng_TextScrn_Destroy((TextScrn *)myScreen->scrnContent);
}
myHotkeys = myScreen->scrnHotkeys;
tempHotkey = myHotkeys;
while (tempHotkey) {
myHotkeys = myHotkeys->next;
mem_free(tempHotkey);
tempHotkey = myHotkeys;
}
mem_free_to_stash((void *)myScreen, _G(memtypeSCRN));
myScreen = _G(frontScreen);
}
// Duplicate the above loop exactly for the list of inactive windows
myScreen = _G(inactiveScreens);
while (myScreen) {
_G(inactiveScreens) = _G(inactiveScreens)->behind;
if (myScreen->scrnType == SCRN_DLG) {
vmng_Dialog_Destroy((Dialog *)myScreen->scrnContent);
} else if (myScreen->scrnType == SCRN_TEXT) {
vmng_TextScrn_Destroy((TextScrn *)myScreen->scrnContent);
}
myHotkeys = myScreen->scrnHotkeys;
tempHotkey = myHotkeys;
while (tempHotkey) {
myHotkeys = myHotkeys->next;
mem_free(tempHotkey);
tempHotkey = myHotkeys;
}
mem_free_to_stash((void *)myScreen, _G(memtypeSCRN));
myScreen = _G(inactiveScreens);
}
}
ScreenContext *vmng_screen_create(int32 x1, int32 y1, int32 x2, int32 y2, int32 scrnType, uint32 scrnFlags,
void *scrnContent, RefreshFunc redraw, EventHandler evtHandler) {
ScreenContext *myScreen;
if (!_G(vmng_Initted))
return nullptr;
if ((myScreen = (ScreenContext *)mem_get_from_stash(_G(memtypeSCRN), "+SCRN")) == nullptr)
return nullptr;
myScreen->x1 = x1;
myScreen->y1 = y1;
myScreen->x2 = x2;
myScreen->y2 = y2;
myScreen->scrnType = scrnType;
myScreen->scrnFlags = scrnFlags;
myScreen->scrnContent = scrnContent;
myScreen->redraw = redraw;
myScreen->evtHandler = evtHandler;
myScreen->scrnHotkeys = nullptr;
if (_G(inactiveScreens))
_G(inactiveScreens)->infront = myScreen;
myScreen->behind = _G(inactiveScreens);
myScreen->infront = nullptr;
_G(inactiveScreens) = myScreen;
return myScreen;
}
void vmng_screen_dispose(void *scrnContent) {
ScreenContext *myScreen = ExtractScreen(scrnContent, SCRN_ANY);
if (myScreen == nullptr)
return;
RestoreScreens(myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
Hotkey *myHotkeys = myScreen->scrnHotkeys;
Hotkey *tempHotkey = myHotkeys;
while (tempHotkey) {
myHotkeys = myHotkeys->next;
mem_free(tempHotkey);
tempHotkey = myHotkeys;
}
mem_free_to_stash((void *)myScreen, _G(memtypeSCRN));
}
void vmng_screen_hide(void *scrnContent) {
ScreenContext *myScreen;
if ((myScreen = ExtractScreen(scrnContent, SCRN_ACTIVE)) == nullptr) return;
RestoreScreens(myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
myScreen->behind = _G(inactiveScreens);
myScreen->infront = nullptr;
if (_G(inactiveScreens))
_G(inactiveScreens)->infront = myScreen;
_G(inactiveScreens) = myScreen;
}
void vmng_screen_show(void *scrnContent) {
ScreenContext *myScreen = ExtractScreen(scrnContent, SCRN_ANY);
if (myScreen == nullptr)
return;
if (!_G(frontScreen)) {
myScreen->infront = nullptr;
myScreen->behind = nullptr;
_G(frontScreen) = myScreen;
_G(backScreen) = myScreen;
} else {
ScreenContext *tempScreen = _G(frontScreen);
while (tempScreen &&
((tempScreen->scrnFlags & SF_LAYER) > (myScreen->scrnFlags & SF_LAYER))) {
tempScreen = tempScreen->behind;
}
if (!tempScreen) {
myScreen->behind = nullptr;
myScreen->infront = _G(backScreen);
_G(backScreen)->behind = myScreen;
_G(backScreen) = myScreen;
} else if (tempScreen == _G(frontScreen)) {
myScreen->behind = _G(frontScreen);
myScreen->infront = nullptr;
_G(frontScreen)->infront = myScreen;
_G(frontScreen) = myScreen;
} else {
myScreen->behind = tempScreen;
myScreen->infront = tempScreen->infront;
tempScreen->infront = myScreen;
myScreen->infront->behind = myScreen;
}
}
RestoreScreens(myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
}
ScreenContext *vmng_screen_find(void *scrnContent, int32 *status) {
int32 myStatus = SCRN_ACTIVE;
if (!_G(vmng_Initted))
return nullptr;
ScreenContext *myScreen = _G(frontScreen);
while (myScreen && (myScreen->scrnContent != scrnContent))
myScreen = myScreen->behind;
if (!myScreen) {
myStatus = SCRN_INACTIVE;
myScreen = _G(inactiveScreens);
while (myScreen && (myScreen->scrnContent != scrnContent))
myScreen = myScreen->behind;
}
if (status) {
if (myScreen)
*status = myStatus;
else
*status = SCRN_UNDEFN;
}
return myScreen;
}
void vmng_refresh_video(int32 scrnX, int32 scrnY, int32 x1, int32 y1, int32 x2, int32 y2, Buffer *srcBuffer) {
assert(x2 <= srcBuffer->w && y2 <= srcBuffer->h);
const byte *srcP = srcBuffer->data + (y1 * srcBuffer->stride) + x1;
g_system->copyRectToScreen(srcP, srcBuffer->stride, scrnX, scrnY,
x2 - x1 + 1, y2 - y1 + 1);
}
ScreenContext *ExtractScreen(void *scrnContent, int32 status) {
ScreenContext *myScreen = nullptr, *tempScreen;
if (!_G(vmng_Initted))
return nullptr;
if ((status == SCRN_ANY) || (status == SCRN_ACTIVE)) {
// Search the active list, and remove the window if it is found
myScreen = _G(frontScreen);
while (myScreen && (myScreen->scrnContent != scrnContent))
myScreen = myScreen->behind;
if (myScreen) {
if (myScreen == _G(frontScreen)) {
if (myScreen == _G(backScreen)) {
_G(frontScreen) = nullptr;
_G(backScreen) = nullptr;
} else {
_G(frontScreen) = _G(frontScreen)->behind;
_G(frontScreen)->infront = nullptr;
}
} else {
tempScreen = myScreen->infront;
tempScreen->behind = myScreen->behind;
if (tempScreen->behind)
tempScreen->behind->infront = tempScreen;
else
_G(backScreen) = tempScreen;
}
}
}
if (((status == SCRN_ANY) && (!myScreen)) || (status == SCRN_INACTIVE)) {
// Search the inactive list and remove the window if it is found
myScreen = _G(inactiveScreens);
while (myScreen && (myScreen->scrnContent != scrnContent))
myScreen = myScreen->behind;
if (myScreen) {
if (myScreen == _G(inactiveScreens)) {
_G(inactiveScreens) = _G(inactiveScreens)->behind;
if (_G(inactiveScreens))
_G(inactiveScreens)->infront = nullptr;
} else {
tempScreen = myScreen->infront;
tempScreen->behind = myScreen->behind;
if (tempScreen->behind) tempScreen->behind->infront = tempScreen;
}
}
}
return myScreen;
}
} // End of namespace M4

View File

@@ -0,0 +1,122 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_VMNG_CORE_H
#define M4_GUI_GUI_VMNG_CORE_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
/**
* To initialize the GUI view manager.
* @returns The success of the call
* @remarks Should be called once during program initialization,
* after dpmi_init_mem() has been called.
*/
bool vmng_init();
/**
* Shutdown the GUI view manager, and release all resources.
*
* Since applications can be written in which Dialogs are designed, created, and
* Their callback procedures are executed by the view manager, it is not always
* necessary for the application to retain the (Dialog*)s which it created.
* Therefore, Any windows which contain a (Dialog*) and still exist also destroy
* The Dialog for which they were created. The same goes for (TextScrn*)s.
*/
void vmng_shutdown();
/**
* Create a new window for the identifier given (scrnContent).
* @param x1 Top left x
* @param y1 Top left y
* @param x2 Bottom right x
* @param y2 Bottom right y
* @param scrnType One of: SCRN_DLG (Dialog), SCRN_BUF (Buffer),
* SCRN_TEXT (TextScrn). to identify scrnContent type.
* @param See the overview at the top of this file for an explanation of scrnFlags.
* @param scrnContent The identifier for the new window.
* @param redraw The function pointer which will be called when the view
* manager requests the window to redraw a portion of itself.
* @param evtHandler The function pointer call when the view manager
* determines that an event should be processed by this window.
* @remarks If TRUE is returned, the window was successfully created, and is currently
* in the list of inactive windows. A call to vmng_screen_show() will activate
* (make visible) this window.
*/
ScreenContext *vmng_screen_create(int32 x1, int32 y1, int32 x2, int32 y2, int32 scrnType, uint32 scrnFlags,
void *scrnContent, RefreshFunc redraw, EventHandler evtHandler);
/**
* Return the ScreenContext * associated with a window, and to determine whether it is active,
* exists but is inactive (invisible, no events are received or blocked), or is undefined
* (does not exist).
* @param scrnContent The window identifier.
* @param status If not nullptr, the status: SCRN_ACTIVE, SCRN_INACTIVE, or SCRN_UNDEFN
* is recoreded here.
* @returns the ScreenContext* associated with the window which was created for
* the structure scrnContent. returns nullptr if now window was found.
*/
ScreenContext *vmng_screen_find(void *scrnContent, int32 *status); // was FindScreen
/**
* Remove a window from the active list, and place it on the inactive list
* @param The window identifier
*/
void vmng_screen_hide(void *scrnContent); // was HideScreen
/**
* Place a window at the front of its layer on the active list.
* @param scrnContent The window Identifier.
* @remarks If the window is currently inactive, it will be activated and placed
* into the list at the front of its layer (SF_BACKGRND, SF_DRIFTER, SF_FLOATER, or SF_SURFACE).
* If the window is already active, it will be moved to the front of its layer.
*/
void vmng_screen_show(void *scrnContent); // was ShowScreen
/**
* Place a window at the back of its layer.
* @param scrnContent The window Identifier.
* @remarks Essentially this procedure does the same as vmng_screen_show(),
* the only difference is that the window is at the back of its layer.
*/
void vmng_screen_to_back(void *scrnContent); // was MoveScreenToBack
/**
* Release all resources associated with the window.
* @param scrnContent The window Identifier.
*/
void vmng_screen_dispose(void *scrnContent); // was DestroyScreen
void vmng_refresh_video(int32 scrnX, int32 scrnY, int32 x1, int32 y1, int32 x2, int32 y2, Buffer *srcBuffer);
/**
* Remove the window from either the active list of windows, or the inactive list,
* wherever it was found.
*/
ScreenContext *ExtractScreen(void *scrnContent, int32 status);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,503 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/gui_vmng_rectangles.h"
#include "m4/gui/gui_vmng.h"
#include "m4/core/errors.h"
#include "m4/core/imath.h"
#include "m4/mem/mem.h"
#include "m4/vars.h"
namespace M4 {
#define LEFT_EDGE 1
#define RIGHT_EDGE 2
RectList *vmng_CreateNewRect(int32 x1, int32 y1, int32 x2, int32 y2) {
RectList *newRect;
if ((newRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectList")) == nullptr) {
error_show(FL, 'OOS!', "vmng_CreateNewRect");
}
newRect->x1 = x1;
newRect->y1 = y1;
newRect->x2 = x2;
newRect->y2 = y2;
newRect->next = nullptr;
newRect->prev = nullptr;
return newRect;
}
void vmng_AddRectToRectList(RectList **theRectList, int32 rectX1, int32 rectY1, int32 rectX2, int32 rectY2) {
// First make sure we have a valid rectangle
if ((rectX1 > rectX2) || (rectY1 > rectY2)) {
return;
}
// Initialize the dirty rect list
RectList *dirtyRectList = vmng_CreateNewRect(rectX1, rectY1, rectX2, rectY2);
// Initialize the clean rectList
RectList *cleanRectList = nullptr;
RectList *endCleanRectList = nullptr;
// Use a local var for theRectlist
RectList *myRectList = *theRectList;
// Loop through all the dirtyRects
RectList *dirtyRect = dirtyRectList;
while (dirtyRect) {
// Remove dirtyRect from the head of the dirtyRectList
dirtyRectList = dirtyRectList->next;
// Set the intersected flag
bool intersected = false;
// Loop on through
RectList *myRect = myRectList;
while (myRect) {
// If the two rectangles intersect
if ((dirtyRect->x1 <= myRect->x2) && (dirtyRect->x2 >= myRect->x1) && (dirtyRect->y1 <= myRect->y2) && (dirtyRect->y2 >= myRect->y1)) {
// Set the intersected flag
intersected = true;
// If dirtyRect is not completely contained within myRect
if ((dirtyRect->x1 < myRect->x1) || (dirtyRect->y1 < myRect->y1) || (dirtyRect->x2 > myRect->x2) || (dirtyRect->y2 > myRect->y2)) {
// First remove it from the list
if (myRect->prev) {
myRect->prev->next = myRect->next;
} else {
myRectList = myRect->next;
}
if (myRect->next) {
myRect->next->prev = myRect->prev;
}
RectList *newRect;
// So now there is an intersection.
// If myRect sticks out above dirtyRect, chop it off and put it in the main rect list, to be recheck by other dirty rects
if (myRect->y1 < dirtyRect->y1) {
newRect = vmng_CreateNewRect(myRect->x1, myRect->y1, myRect->x2, dirtyRect->y1 - 1);
newRect->prev = nullptr;
newRect->next = myRectList;
if (myRectList) {
myRectList->prev = newRect;
}
myRectList = newRect;
// And set the top of myRect to be the same as dirtyRect
myRect->y1 = dirtyRect->y1;
} else if (dirtyRect->y1 < myRect->y1) {
// else if dirtyRect sticks out above chop it off and put it on the dirty list
newRect = vmng_CreateNewRect(dirtyRect->x1, dirtyRect->y1, dirtyRect->x2, myRect->y1 - 1);
newRect->next = dirtyRectList;
dirtyRectList = newRect;
// and set the top of dirtyRect to be the same as myRect
dirtyRect->y1 = myRect->y1;
}
// If myRect sticks out below dirtyRect, chop it off and put it in the main rect list, to be recheck by other dirty rects
if (myRect->y2 > dirtyRect->y2) {
newRect = vmng_CreateNewRect(myRect->x1, dirtyRect->y2 + 1, myRect->x2, myRect->y2);
newRect->prev = nullptr;
newRect->next = myRectList;
if (myRectList) {
myRectList->prev = newRect;
}
myRectList = newRect;
// and set the bottom of myRect to be the same as dirtyRect
myRect->y2 = dirtyRect->y2;
} else if (dirtyRect->y2 > myRect->y2) {
//else if dirtyRect sticks out below myRect...
newRect = vmng_CreateNewRect(dirtyRect->x1, myRect->y2 + 1, dirtyRect->x2, dirtyRect->y2);
newRect->next = dirtyRectList;
dirtyRectList = newRect;
// and set the bottom of dirtyRect to be the same as myRect
dirtyRect->y2 = myRect->y2;
}
// Now we've got overlapping rectangles which are the same height. create one max width one
// If the dirtyRect sticks out on either side, the resulting rect is still dirty, otherwise clean
if ((dirtyRect->x1 < myRect->x1) || (dirtyRect->x2 > myRect->x2)) {
// Use dirtyRect to become the max width rect
dirtyRect->x1 = imath_min(dirtyRect->x1, myRect->x1);
dirtyRect->x2 = imath_max(dirtyRect->x2, myRect->x2);
dirtyRect->next = dirtyRectList;
dirtyRectList = dirtyRect;
// And turf myRect
mem_free_to_stash(myRect, _G(memtypeRECT));
} else {
// Else we can put what's left of myRect onto the clean list and turf dirtyRect
// Note: it is impossible to split the dirtyRect list vertically, they always stretch horizontally,
// therefore if this dirty rect does not stick out the sides, what's left of myRect is clean
myRect->prev = nullptr;
myRect->next = cleanRectList;
if (cleanRectList) {
cleanRectList->prev = myRect;
} else {
endCleanRectList = myRect;
}
cleanRectList = myRect;
mem_free_to_stash((void *)dirtyRect, _G(memtypeRECT));
}
// Exit the loop
myRect = nullptr;
} else {
// else through away dirtyRect, and get the next dirtyRect
mem_free_to_stash(dirtyRect, _G(memtypeRECT));
myRect = nullptr;
}
} else {
// else get the next rect
myRect = myRect->next;
}
}
//if we didn't intersect, put the dirtyRect on the clean list
if (!intersected) {
dirtyRect->prev = nullptr;
dirtyRect->next = cleanRectList;
if (cleanRectList) {
cleanRectList->prev = dirtyRect;
} else {
endCleanRectList = dirtyRect;
}
cleanRectList = dirtyRect;
}
// get the next dirty rect
dirtyRect = dirtyRectList;
}
// now, just add the clean list onto the dirty list
if (cleanRectList) {
//now add the entire cleanRectList to the front of myRectList
endCleanRectList->next = myRectList;
if (myRectList) {
myRectList->prev = endCleanRectList;
}
myRectList = cleanRectList;
}
// Return the rect list
*theRectList = myRectList;
}
RectList *vmng_DuplicateRectList(RectList *myRectList) {
RectList *newRectList = nullptr;
RectList *prevRect = nullptr;
RectList *myRect = myRectList;
while (myRect) {
// Duplicate myRect and stick it on the newRectList
RectList *tempRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectList");
if (tempRect == nullptr) {
error_show(FL, 'OOS!', "vmng_DuplicateRectList()");
}
tempRect->x1 = myRect->x1;
tempRect->y1 = myRect->y1;
tempRect->x2 = myRect->x2;
tempRect->y2 = myRect->y2;
tempRect->prev = prevRect;
tempRect->next = nullptr;
if (prevRect) {
prevRect->next = tempRect;
} else {
newRectList = tempRect;
}
prevRect = tempRect;
//get the next rectangle
myRect = myRect->next;
}
return newRectList;
}
bool vmng_RectIntersectsRectList(RectList *myRectList, int32 x1, int32 y1, int32 x2, int32 y2) {
// Parameter verification
if ((!myRectList) || (x1 > x2) || (y1 > y2)) {
return false;
}
// Loop through the list, and break as soon as there is an intersection
RectList *myRect = myRectList;
while (myRect) {
// Calculate the intersection
const int32 intrX1 = imath_max(myRect->x1, x1);
const int32 intrY1 = imath_max(myRect->y1, y1);
const int32 intrX2 = imath_min(myRect->x2, x2);
const int32 intrY2 = imath_min(myRect->y2, y2);
// If we intersected, return true
if ((intrX1 <= intrX2) && (intrY1 <= intrY2)) {
return true;
}
// else get the next rect in the list
myRect = myRect->next;
}
// We made it through the entire list with no intersections - return false
return false;
}
bool vmng_ClipRectList(RectList **myRectList, int32 clipX1, int32 clipY1, int32 clipX2, int32 clipY2) {
// Loop through myRect list
RectList *myRect = *myRectList;
while (myRect) {
// Set the next rect
RectList *nextRect = myRect->next;
// Clip myRect
const int32 x1 = imath_max(myRect->x1, clipX1);
const int32 y1 = imath_max(myRect->y1, clipY1);
const int32 x2 = imath_min(myRect->x2, clipX2);
const int32 y2 = imath_min(myRect->y2, clipY2);
// If we have a valid rectangle
if ((x1 <= x2) && (y1 <= y2)) {
// Clip the rectangle
myRect->x1 = x1;
myRect->y1 = y1;
myRect->x2 = x2;
myRect->y2 = y2;
} else {
// Else remove it from the rectList and turf it
if (myRect->prev) {
myRect->prev->next = myRect->next;
} else {
*myRectList = myRect->next;
}
if (myRect->next) {
myRect->next->prev = myRect->prev;
}
mem_free_to_stash((void *)myRect, _G(memtypeRECT));
}
// Check the next rect
myRect = nextRect;
}
return true;
}
bool vmng_RectListValid(RectList *myRectList) {
RectList *myRect = myRectList;
while (myRect) {
RectList *tempRectList = myRect->next;
if (vmng_RectIntersectsRectList(tempRectList, myRect->x1, myRect->y1, myRect->x2, myRect->y2)) {
return false;
}
myRect = myRect->next;
}
return true;
}
void vmng_DisposeRectList(RectList **rectList) {
// Loop through the rect list
RectList *myRect = *rectList;
while (myRect) {
// Remove myRect from the head of the list
*rectList = myRect->next;
// Dispose of myRect;
mem_free_to_stash((void *)myRect, _G(memtypeRECT));
// Get the next rectangle
myRect = *rectList;
}
}
void vmng_RemoveRectFromRectList(RectList **scrnRectList, int32 x1, int32 y1, int32 x2, int32 y2) {
RectList *tempRect;
RectList *rectList = *scrnRectList;
// Go through the rectList list breaking down any rects which intersect the given coords
RectList *unsortedRectList = nullptr;
RectList *myRect = rectList;
while (myRect) {
// Set the nextRect pointer
RectList *nextRect = myRect->next;
// Check for an intersection
const int32 tempX1 = imath_max(x1, myRect->x1);
const int32 tempY1 = imath_max(y1, myRect->y1);
const int32 tempX2 = imath_min(x2, myRect->x2);
const int32 tempY2 = imath_min(y2, myRect->y2);
// If we have an intersection
if ((tempX1 <= tempX2) && (tempY1 <= tempY2)) {
// Break myRect apart into any pieces not covered by x1, y1, x2, y2
// Top edge
if (myRect->y1 < y1) {
// Create a new rect of just the part that extends beyond the top of myRect
tempRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectangle");
if (tempRect == nullptr) {
error_show(FL, 'OOS!', "vmng_AddRectToRectList");
}
tempRect->x1 = myRect->x1;
tempRect->y1 = myRect->y1;
tempRect->x2 = myRect->x2;
tempRect->y2 = y1 - 1;
// Add tempRect to the unsortedRectList
tempRect->next = unsortedRectList;
unsortedRectList = tempRect;
// Update myRect
myRect->y1 = y1;
}
// Bottom edge
if (myRect->y2 > y2) {
// Create a new rect of just the part that extends beyond the top of myRect
tempRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectangle");
if (tempRect == nullptr) {
error_show(FL, 'OOS!', "vmng_AddRectToRectList");
}
tempRect->x1 = myRect->x1;
tempRect->y1 = y2 + 1;
tempRect->x2 = myRect->x2;
tempRect->y2 = myRect->y2;
// Add tempRect to the unsortedRectList
tempRect->next = unsortedRectList;
unsortedRectList = tempRect;
// Update myRect
myRect->y2 = y2;
}
// Left edge
if (myRect->x1 < x1) {
// Create a new rect of just the part that extends beyond the top of myRect
tempRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectangle");
if (tempRect == nullptr) {
error_show(FL, 'OOS!', "vmng_AddRectToRectList");
}
tempRect->x1 = myRect->x1;
tempRect->y1 = myRect->y1;
tempRect->x2 = x1 - 1;
tempRect->y2 = myRect->y2;
// Add tempRect to the unsortedRectList
tempRect->next = unsortedRectList;
unsortedRectList = tempRect;
}
// Right edge
if (myRect->x2 > x2) {
// Create a new rect of just the part that extends beyond the top of myRect
tempRect = (RectList *)mem_get_from_stash(_G(memtypeRECT), "+guiRectangle");
if (tempRect == nullptr) {
error_show(FL, 'OOS!', "vmng_AddRectToRectList");
}
tempRect->x1 = x2 + 1;
tempRect->y1 = myRect->y1;
tempRect->x2 = myRect->x2;
tempRect->y2 = myRect->y2;
// Add tempRect to the unsortedRectList
tempRect->next = unsortedRectList;
unsortedRectList = tempRect;
}
// Remove myRect from the list and turf it
if (myRect->next) {
myRect->next->prev = myRect->prev;
}
if (myRect->prev) {
myRect->prev->next = myRect->next;
} else {
rectList = myRect->next;
}
mem_free_to_stash((void *)myRect, _G(memtypeRECT));
}
// Get the next rect
myRect = nextRect;
}
// Now go through the unsorted list and insert them into the main list
tempRect = unsortedRectList;
while (tempRect) {
unsortedRectList = unsortedRectList->next;
// For each unsorted rect, loop through the rect list until its place is found
bool finished = false;
RectList *prevRect = nullptr;
myRect = rectList;
while (myRect && (!finished)) {
// If it goes before myRect
if (tempRect->y2 <= myRect->y2) {
finished = true;
} else {
prevRect = myRect;
myRect = myRect->next;
}
}
// tempRect belongs after prevRect
if (prevRect) {
tempRect->prev = prevRect;
tempRect->next = prevRect->next;
if (prevRect->next) {
prevRect->next->prev = tempRect;
}
prevRect->next = tempRect;
} else {
// else it belongs at the front of rectList
tempRect->prev = nullptr;
tempRect->next = rectList;
if (rectList) {
rectList->prev = tempRect;
}
rectList = tempRect;
}
// Get the next unsorted rect
tempRect = unsortedRectList;
}
// Set the screen rect list to the resulting rect list
*scrnRectList = rectList;
}
} // End of namespace M4

View File

@@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_VMNG_RECTANGLES_H
#define M4_GUI_GUI_VMNG_RECTANGLES_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
RectList *vmng_CreateNewRect(int32 x1, int32 y1, int32 x2, int32 y2);
void vmng_AddRectToRectList(RectList **scrnRectList, int32 x1, int32 y1, int32 x2, int32 y2);
RectList *vmng_DuplicateRectList(RectList *myRectList);
bool vmng_RectIntersectsRectList(RectList *myRectList, int32 x1, int32 y1, int32 x2, int32 y2);
bool vmng_RectListValid(RectList *myRectList);
bool vmng_ClipRectList(RectList **myRectList, int32 clipX1, int32 clipY1, int32 clipX2, int32 clipY2);
void vmng_DisposeRectList(RectList **rectList);
void vmng_RemoveRectFromRectList(RectList **scrnRectList, int32 x1, int32 y1, int32 x2, int32 y2);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,362 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/system.h"
#include "common/rect.h"
#include "graphics/surface.h"
#include "m4/gui/gui_vmng_screen.h"
#include "m4/gui/gui_vmng.h"
#include "m4/vars.h"
namespace M4 {
static void vmng_black_out_video(int32 x1, int32 y1, int32 x2, int32 y2);
static bool MoveScreen(ScreenContext *myScreen, int32 parmX, int32 parmY, bool deltaMove);
bool GetScreenCoords(void *scrnContent, int32 *x1, int32 *y1, int32 *x2, int32 *y2) {
ScreenContext *myScreen = vmng_screen_find(scrnContent, nullptr);
if (myScreen == nullptr)
return false;
if (x1)
*x1 = myScreen->x1;
if (y1)
*y1 = myScreen->y1;
if (x2)
*x2 = myScreen->x2;
if (y2)
*y2 = myScreen->y2;
return true;
}
void RestoreScreens(int32 updateX1, int32 updateY1, int32 updateX2, int32 updateY2) {
RectList *updateRectList, *scrnUpdateList, *tempRect;
if (!_G(vmng_Initted) || _G(system_shutting_down)) {
return;
}
// Clip to screen
if (updateX1 < MIN_VIDEO_X)
updateX1 = MIN_VIDEO_X;
if (updateY1 < MIN_VIDEO_Y)
updateY1 = MIN_VIDEO_Y;
if (updateX2 > MAX_VIDEO_X)
updateX2 = MAX_VIDEO_X;
if (updateY2 > MAX_VIDEO_Y)
updateY2 = MAX_VIDEO_Y;
// Throw away inside out rectangles
if ((updateX2 < updateX1) || (updateY2 < updateY1)) {
return;
}
// Create a master updateRectList - when this list is empty, the screen has been redrawn
updateRectList = vmng_CreateNewRect(updateX1, updateY1, updateX2, updateY2);
// First loop through the screens back to front, drawing only the transparent screens
ScreenContext *myScreen = _G(backScreen);
while (myScreen && updateRectList) {
// We only draw transparent screens on the first pass
if ((myScreen->scrnFlags & SF_TRANSPARENT) && myScreen->redraw) {
// Duplicate the updateRectList
scrnUpdateList = vmng_DuplicateRectList(updateRectList);
// Now clip the scrnUpdateList with the coordinates of myScreen, see if there is anything visible
vmng_ClipRectList(&scrnUpdateList, myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
// Now remove the rects of all screens blocking the scrnUpdateList
ScreenContext *tempScreen = myScreen->infront;
while (scrnUpdateList && tempScreen) {
vmng_RemoveRectFromRectList(&scrnUpdateList, tempScreen->x1, tempScreen->y1, tempScreen->x2, tempScreen->y2);
tempScreen = tempScreen->infront;
}
// If there is anything left of the scrnUpdateList, redraw it
if (scrnUpdateList) {
(myScreen->redraw)((void *)myScreen, (void *)scrnUpdateList, nullptr, 0, 0);
// Now remove all the updated rects from the updateRectList
tempRect = scrnUpdateList;
while (tempRect && updateRectList) {
vmng_RemoveRectFromRectList(&updateRectList, tempRect->x1, tempRect->y1, tempRect->x2, tempRect->y2);
tempRect = tempRect->next;
}
// Now turf the scrnUpdateList
vmng_DisposeRectList(&scrnUpdateList);
}
}
// Get the next screen
myScreen = myScreen->infront;
}
// Now, draw from front to back the non-transparent screens. This way, we can detect when the entire update region has been
// filled, however, if one transparent screen is infront of another, the back transparent screen must be drawn first.
myScreen = _G(frontScreen);
while (myScreen && updateRectList) {
// Make sure it isn't a transparent screen
if (!(myScreen->scrnFlags & SF_TRANSPARENT) && myScreen->redraw) {
// Duplicate the updateRectList
scrnUpdateList = vmng_DuplicateRectList(updateRectList);
// Now clip the scrnUpdateList with the coordinates of myScreen, see what has to be redrawn
vmng_ClipRectList(&scrnUpdateList, myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
// If there is anything visible, redraw it
if (scrnUpdateList) {
myScreen->redraw((void *)myScreen, (void *)scrnUpdateList, nullptr, 0, 0);
// Now remove all the updated rects from the updateRectList
tempRect = scrnUpdateList;
while (tempRect && updateRectList) {
vmng_RemoveRectFromRectList(&updateRectList, tempRect->x1, tempRect->y1, tempRect->x2, tempRect->y2);
tempRect = tempRect->next;
}
// Now turf the scrnUpdateList
vmng_DisposeRectList(&scrnUpdateList);
}
}
// Get the next screen
myScreen = myScreen->behind;
}
// Now, if there is anything left, it should be filled in with black
if (updateRectList) {
tempRect = updateRectList;
while (tempRect) {
vmng_black_out_video(tempRect->x1, tempRect->y1, tempRect->x2, tempRect->y2);
tempRect = tempRect->next;
}
// Now turf the updateRectList
vmng_DisposeRectList(&updateRectList);
}
}
void RestoreScreensInContext(int32 x1, int32 y1, int32 x2, int32 y2, ScreenContext *myScreen) {
//verify the gui has been initted
if (!_G(vmng_Initted)) {
return;
}
//verify parameters
ScreenContext *tempScreen = _G(frontScreen);
while (tempScreen && (tempScreen != myScreen)) {
tempScreen = tempScreen->behind;
}
if (!tempScreen) {
return;
}
//now restore screens
x1 += myScreen->x1;
y1 += myScreen->y1;
x2 += myScreen->x1;
y2 += myScreen->y1;
//restore video
RestoreScreens(x1, y1, x2, y2);
}
bool ResizeScreen(void *scrnContent, int32 newW, int32 newH) {
if ((newW <= 0) || (newH <= 0))
return false;
int32 status;
ScreenContext *myScreen = vmng_screen_find(scrnContent, &status);
if (myScreen == nullptr)
return false;
const int32 oldX2 = myScreen->x2;
myScreen->x2 = myScreen->x1 + newW - 1;
if (myScreen->x2 < oldX2) {
RestoreScreens(myScreen->x2 + 1, myScreen->y1, oldX2, myScreen->y2);
}
const int32 oldY2 = myScreen->y2;
myScreen->y2 = myScreen->y1 + newH - 1;
if (myScreen->y2 < oldY2) {
RestoreScreens(myScreen->x1, myScreen->y2 + 1, myScreen->x2, oldY2);
}
return true;
}
static void vmng_black_out_video(int32 x1, int32 y1, int32 x2, int32 y2) {
Common::Rect r(x1, y1, x2 + 1, y2 + 1);
g_system->fillScreen(r, 0);
}
bool AddScreenHotkey(void *scrnContent, int32 myKey, HotkeyCB callback) {
ScreenContext *myScreen = vmng_screen_find(scrnContent, nullptr);
if (myScreen == nullptr)
return false;
Hotkey *myHotkey = (Hotkey *)mem_alloc(sizeof(Hotkey), "hotkey");
if (myHotkey == nullptr)
return false;
myHotkey->myKey = myKey;
myHotkey->callback = callback;
myHotkey->next = myScreen->scrnHotkeys;
myScreen->scrnHotkeys = myHotkey;
return true;
}
bool RemoveScreenHotkey(void *scrnContent, int32 myKey) {
ScreenContext *myScreen = vmng_screen_find(scrnContent, nullptr);
if (myScreen == nullptr)
return false;
Hotkey *myHotkey = myScreen->scrnHotkeys;
if (myHotkey->myKey == myKey) {
myScreen->scrnHotkeys = myHotkey->next;
mem_free(myHotkey);
} else {
while (myHotkey->next && (myHotkey->next->myKey != myKey)) {
myHotkey = myHotkey->next;
}
if (myHotkey->next) {
Hotkey *tempHotkey = myHotkey->next;
myHotkey->next = tempHotkey->next;
mem_free(tempHotkey);
} else {
return false;
}
}
return true;
}
bool MoveScreenAbs(ScreenContext *myScreen, int32 parmX, int32 parmY) {
return MoveScreen(myScreen, parmX, parmY, false);
}
bool MoveScreenDelta(ScreenContext *myScreen, int32 parmX, int32 parmY) {
return MoveScreen(myScreen, parmX, parmY, true);
}
bool MoveScreenDelta(int32 parmX, int32 parmY) {
return MoveScreen(_G(game_buff_ptr), parmX, parmY, true);
}
void vmng_screen_to_back(void *scrnContent) {
ScreenContext *myScreen = ExtractScreen(scrnContent, SCRN_ANY);
if (myScreen == nullptr) return;
if (!_G(backScreen)) {
myScreen->infront = nullptr;
myScreen->behind = nullptr;
_G(frontScreen) = myScreen;
_G(backScreen) = myScreen;
} else {
ScreenContext *tempScreen = _G(backScreen);
while (tempScreen &&
((tempScreen->scrnFlags & SF_LAYER) < (myScreen->scrnFlags & SF_LAYER))) {
tempScreen = tempScreen->infront;
}
if (!tempScreen) {
myScreen->infront = nullptr;
myScreen->behind = _G(frontScreen);
_G(frontScreen)->infront = myScreen;
_G(frontScreen) = myScreen;
} else if (tempScreen == _G(backScreen)) {
myScreen->infront = _G(backScreen);
myScreen->behind = nullptr;
_G(backScreen)->behind = myScreen;
_G(backScreen) = myScreen;
} else {
myScreen->infront = tempScreen;
myScreen->behind = tempScreen->behind;
tempScreen->behind = myScreen;
myScreen->behind->infront = myScreen;
}
}
RestoreScreens(myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
}
static bool MoveScreen(ScreenContext *myScreen, int32 parmX, int32 parmY, bool deltaMove) {
if (!_G(vmng_Initted))
return false;
const int32 origX1 = myScreen->x1;
const int32 origY1 = myScreen->y1;
const int32 origX2 = myScreen->x2;
const int32 origY2 = myScreen->y2;
if (!deltaMove) {
parmX -= origX1;
parmY -= origY1;
}
if (!(myScreen->scrnFlags & SF_OFFSCRN)) {
if ((myScreen->x2 + parmX) > MAX_VIDEO_X)
parmX = MAX_VIDEO_X - myScreen->x2;
else if ((myScreen->x1 + parmX) < 0)
parmX = -myScreen->x1;
if ((myScreen->y2 + parmY) > MAX_VIDEO_Y)
parmY = MAX_VIDEO_Y - myScreen->y2;
else if ((myScreen->y1 + parmY) < 0)
parmY = -myScreen->y1;
}
if (!(parmX || parmY))
return false;
myScreen->x1 += parmX;
myScreen->y1 += parmY;
myScreen->x2 += parmX;
myScreen->y2 += parmY;
if (parmY > 0) {
RestoreScreens(origX1, origY1, origX2, myScreen->y1 - 1);
if (parmX > 0) {
RestoreScreens(origX1, myScreen->y1, myScreen->x1 - 1, origY2);
} else if (parmX < 0) {
RestoreScreens(myScreen->x2 + 1, myScreen->y1, origX2, origY2);
}
} else if (parmY < 0) {
RestoreScreens(origX1, myScreen->y2 + 1, origX2, origY2);
if (parmX > 0) {
RestoreScreens(origX1, origY1, myScreen->x1 - 1, myScreen->y2);
} else if (parmX < 0) {
RestoreScreens(myScreen->x2 + 1, origY1, origX2, myScreen->y2);
}
} else if (parmX > 0) {
RestoreScreens(origX1, origY1, myScreen->x1 - 1, origY2);
} else {
RestoreScreens(myScreen->x2 + 1, origY1, origX2, origY2);
}
RestoreScreens(myScreen->x1, myScreen->y1, myScreen->x2, myScreen->y2);
return true;
}
} // End of namespace M4

View File

@@ -0,0 +1,108 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_GUI_VMNG_SCREEN_H
#define M4_GUI_GUI_VMNG_SCREEN_H
#include "m4/m4_types.h"
#include "m4/gui/gui_univ.h"
namespace M4 {
/**
* Record the (global) coordinates of the window which was created for scrnContent.
* @param scrnContent The window identifier
* @param x1 Window top-left X
* @param y1 Window top-left Y
* @param x2 Window bottom-right X
* @param y2 Window bottom-right Y
*/
bool GetScreenCoords(void *scrnContent, int32 *x1, int32 *y1, int32 *x2, int32 *y2);
/**
* Change which procedure will be called when a portion of the window
* needs to be redrawn.
* @param scrnContent The window identifier
* @param redraw The new refresh function pointer
*/
bool vmng_SetScreenRefresh(void *scrnContent, RefreshFunc redraw);
/**
* Add a "hot key" to a window.
* @paramscrnContent The window identifier
* @param myKey The "key" which, when pressed, will cause the callback function
* to be executed.
* @param callback The function to be executed when "myKey" is pressed
*/
bool AddScreenHotkey(void *scrnContent, int32 myKey, HotkeyCB callback);
/**
* Remove a hot key
* @param scrnContent The window identifier
* @param myKey The "hot key" to be removed.
* @returns False if either the window or the "hot key" could not be found,
* TRUE if successful
*/
bool RemoveScreenHotkey(void *scrnContent, int32 myKey);
/**
* Obvious shell to MoveScreen
*/
bool MoveScreenAbs(ScreenContext *myScreen, int32 parmX, int32 parmY);
/**
* Obvious shell to MoveScreen
*/
bool MoveScreenDelta(ScreenContext *myScreen, int32 parmX, int32 parmY);
bool MoveScreenDelta(int32 parmX, int32 parmY);
/**
* Resize the windows width and/or height
* @param newW The new width of the window. If <= 0, the old window width will remain
* @param newH The new height of the window. If <= 0, the old window height will remain.
* @returns TRUE if the window was found, FALSE otherwise
*/
bool ResizeScreen(void *scrnContent, int32 newW, int32 newH);
/**
* Restore the monitor image by redrawing the visible portions of each window
* intersecting the given rectangle.
* @param updateX1 Rectangle top-left X
* @param updateY1 Rectangle top-left Y
* @param updateX2 Rectangle bottom-right X
* @param updateY2 Rectangle bottom-right Y
*/
void RestoreScreens(int32 updateX1, int32 updateY1, int32 updateX2, int32 updateY2);
/**
* A shell to RestoreScreens
*/
void RestoreScreensInContext(int32 x1, int32 y1, int32 x2, int32 y2, ScreenContext *myScreen);
/**
* Capture a screenshot to a bitmap.
*/
void Screen2BuffC(int8 *Buff);
} // End of namespace M4
#endif

406
engines/m4/gui/hotkeys.cpp Normal file
View File

@@ -0,0 +1,406 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/gui/hotkeys.h"
#include "m4/gui/gui_sys.h"
#include "m4/gui/gui_vmng.h"
#include "m4/platform/keys.h"
#include "m4/adv_r/adv_walk.h"
#include "m4/burger/burger.h"
#include "m4/burger/vars.h"
#include "m4/riddle/riddle.h"
#include "m4/riddle/vars.h"
namespace M4 {
// Since we include the vars of both games, we need to reset the _G
// to only point to the common shared variables
#undef _G
#define _G(X) (g_vars->_##X)
Dialog *Hotkeys::_changeGlobalDialog;
int Hotkeys::_globalToChange;
Dialog *Hotkeys::_teleportDialog;
Hotkeys::Hotkeys() {
_globalToChange = 0;
_changeGlobalDialog = nullptr;
_teleportDialog = nullptr;
}
void Hotkeys::disable_hot_keys() {
RemoveSystemHotkey(KEY_HOME);
RemoveSystemHotkey(KEY_PAGE_UP);
RemoveSystemHotkey(KEY_PAGE_DOWN);
RemoveSystemHotkey(KEY_END);
RemoveSystemHotkey(KEY_ALT_UP);
RemoveSystemHotkey(KEY_ALT_DOWN);
RemoveSystemHotkey(KEY_ALT_LEFT);
RemoveSystemHotkey(KEY_ALT_RIGHT);
RemoveSystemHotkey(KEY_CTRL_UP);
RemoveSystemHotkey(KEY_CTRL_DOWN);
RemoveSystemHotkey(KEY_CTRL_LEFT);
RemoveSystemHotkey(KEY_CTRL_RIGHT);
RemoveSystemHotkey(KEY_F4);
RemoveSystemHotkey('[');
RemoveSystemHotkey(']');
RemoveSystemHotkey('{');
RemoveSystemHotkey('}');
//RemoveSystemHotkey( KEY_ALT_B);
RemoveSystemHotkey(KEY_ALT_C);
RemoveSystemHotkey(KEY_ALT_D);
RemoveSystemHotkey(KEY_ALT_F);
RemoveSystemHotkey(KEY_ALT_G);
RemoveSystemHotkey(KEY_ALT_I);
RemoveSystemHotkey(KEY_ALT_B);
RemoveSystemHotkey(KEY_ALT_M);
RemoveSystemHotkey(KEY_ALT_P);
RemoveSystemHotkey(KEY_ALT_R);
RemoveSystemHotkey(KEY_ALT_S);
RemoveSystemHotkey(KEY_ALT_T);
RemoveSystemHotkey(KEY_ALT_W);
RemoveSystemHotkey(KEY_ALT_Z);
}
void Hotkeys::add_hot_keys() {
AddSystemHotkey(KEY_F2, saveGame);
AddSystemHotkey(KEY_F3, loadGame);
AddSystemHotkey(KEY_F5, saveGame);
AddSystemHotkey(KEY_F7, loadGame);
AddSystemHotkey(KEY_ALT_X, exit_program);
AddSystemHotkey(KEY_CTRL_X, exit_program);
AddSystemHotkey(KEY_ALT_Q, exit_program);
AddSystemHotkey(KEY_CTRL_Q, exit_program);
AddSystemHotkey(KEY_SPACE, adv_hyperwalk_to_final_destination);
AddSystemHotkey('f', adv_hyperwalk_to_final_destination);
adv_enable_system_hot_keys();
}
void Hotkeys::adv_enable_system_hot_keys() {
term_message("System Cheats On");
AddSystemHotkey(KEY_HOME, saveScreenshot);
AddSystemHotkey(KEY_PAGE_UP, debug_memory_next_column);
AddSystemHotkey(KEY_PAGE_DOWN, debug_memory_prev_column);
AddSystemHotkey(KEY_END, debug_memory_last_column);
AddSystemHotkey(KEY_ALT_UP, player_step_up);
AddSystemHotkey(KEY_ALT_DOWN, player_step_down);
AddSystemHotkey(KEY_ALT_LEFT, player_step_left);
AddSystemHotkey(KEY_ALT_RIGHT, player_step_right);
AddSystemHotkey(KEY_CTRL_UP, player_jump_up);
AddSystemHotkey(KEY_CTRL_DOWN, player_jump_down);
AddSystemHotkey(KEY_CTRL_LEFT, player_jump_left);
AddSystemHotkey(KEY_CTRL_RIGHT, player_jump_right);
AddSystemHotkey(KEY_F4, term_next_mode);
AddSystemHotkey('[', camera_step_left);
AddSystemHotkey(']', camera_step_right);
AddSystemHotkey('{', camera_jump_left);
AddSystemHotkey('}', camera_jump_right);
AddSystemHotkey(KEY_ALT_B, toggle_inv_visible);
AddSystemHotkey(KEY_ALT_C, toggle_commands_allowed);
AddSystemHotkey(KEY_ALT_D, debug_memory_dumpcore_to_disk);
AddSystemHotkey(KEY_ALT_E, scale_editor_toggle); // Was Alt-S, but ScummVM reserves that
AddSystemHotkey(KEY_ALT_F, dbg_mem_set_search);
AddSystemHotkey(KEY_ALT_G, changeGlobal);
AddSystemHotkey(KEY_ALT_I, toggleInfoDialog);
AddSystemHotkey(KEY_ALT_B, other_cheat_with_inventory_objects);
AddSystemHotkey(KEY_ALT_M, debug_memory_toggle);
AddSystemHotkey(KEY_ALT_P, dbg_pal_toggle);
AddSystemHotkey(KEY_ALT_R, f_io_report);
AddSystemHotkey(KEY_ALT_T, teleport);
AddSystemHotkey(KEY_ALT_W, paint_walk_codes);
AddSystemHotkey(KEY_ALT_Z, pal_override);
}
void Hotkeys::exit_program(void *, void *) {
_G(kernel).going = false;
}
void Hotkeys::saveGame(void *, void *) {
g_engine->showSaveScreen();
}
void Hotkeys::loadGame(void *, void *) {
g_engine->showLoadScreen(M4Engine::kLoadFromHotkey);
}
void Hotkeys::adv_hyperwalk_to_final_destination(void *a, void *b) {
M4::adv_hyperwalk_to_final_destination(a, b);
}
void Hotkeys::f_io_report(void *, void *) {
// IO file list not available in ScummVM
}
void Hotkeys::saveScreenshot(void *, void *) {
g_system->saveScreenshot();
}
void Hotkeys::debug_memory_next_column(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::debug_memory_prev_column(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::debug_memory_last_column(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::player_step_up(void *, void *) {
player_step(0, -1);
}
void Hotkeys::player_step_down(void *, void *) {
player_step(0, 1);
}
void Hotkeys::player_step_left(void *, void *) {
player_step(-1, 0);
}
void Hotkeys::player_step_right(void *, void *) {
player_step(1, 0);
}
void Hotkeys::player_jump_up(void *, void *) {
player_step(0, -50);
}
void Hotkeys::player_jump_down(void *, void *) {
player_step(0, 50);
}
void Hotkeys::player_jump_left(void *, void *) {
player_step(-50, 0);
}
void Hotkeys::player_jump_right(void *, void *) {
player_step(50, 0);
}
void Hotkeys::player_step(int xDelta, int yDelta) {
player_update_info();
_G(player_info).x += xDelta;
_G(player_info).y += yDelta;
ws_demand_location(_G(player_info).x, _G(player_info).y);
}
void Hotkeys::term_next_mode(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::camera_step_left(void *, void *) {
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), nullptr);
MoveScreenDelta(sc, 10, 0);
}
void Hotkeys::camera_step_right(void *, void *) {
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), nullptr);
MoveScreenDelta(sc, -10, 0);
}
void Hotkeys::camera_jump_left(void *, void *) {
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), nullptr);
MoveScreenDelta(sc, 100, 0);
}
void Hotkeys::camera_jump_right(void *, void *) {
ScreenContext *sc = vmng_screen_find(_G(gameDrawBuff), nullptr);
MoveScreenDelta(sc, -100, 0);
}
void Hotkeys::toggle_inv_visible(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::toggle_commands_allowed(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::debug_memory_dumpcore_to_disk(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::dbg_mem_set_search(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::changeGlobal(void *, void *) {
if (!_changeGlobalDialog) {
gr_font_set(_G(font_tiny));
_changeGlobalDialog = DialogCreateAbsolute(250, 120, 450, 220, 242);
_changeGlobalDialog->addButton(60, 40, " Change Global Variable ",
changeGlobalChange, 1);
_changeGlobalDialog->addButton(10, 40, " Cancel ", changeGlobalCancel, 2);
char sep[5+1] = "-----";
_changeGlobalDialog->addTextField(50, 7, gr_font_string_width(sep) + 50, sep, nullptr, 3, 5);
_changeGlobalDialog->configure(3, 1, 2);
_changeGlobalDialog->show();
}
}
void Hotkeys::changeGlobalChange(void *, void *) {
// Get the global number to change
Item *textField = _changeGlobalDialog->getItem(3);
_globalToChange = atoi(textField->prompt);
if (!_globalToChange) {
changeGlobalCancel(nullptr, nullptr);
return;
}
// Destroy the current dialog
_changeGlobalDialog->destroy();
// Create secondary dialog to get value to set global to
const int globalVal = (g_engine->getGameType() == GType_Burger) ?
Burger::g_vars->_flags[(Burger::Flag)_globalToChange] :
Riddle::g_vars->_flags[(Riddle::Flag)_globalToChange];
_changeGlobalDialog = DialogCreateAbsolute(250, 120, 450, 220, 242);
_changeGlobalDialog->addButton(60, 40,
Common::String::format("Assign new value to #%d ", _globalToChange).c_str(),
changeGlobalDoChange, 1);
_changeGlobalDialog->addButton(10, 40, " Cancel ", changeGlobalCancel, 2);
char val[5+1] = "MMMMM";
_changeGlobalDialog->addTextField(50, 7,
gr_font_string_width(val) + 50,
Common::String::format("%5d", globalVal).c_str(),
nullptr, 3, 5);
_changeGlobalDialog->configure(3, 1, 2);
_changeGlobalDialog->show();
}
void Hotkeys::changeGlobalDoChange(void *, void *) {
Item *textField = _changeGlobalDialog->getItem(3);
const int globalVal = atoi(textField->prompt);
if (g_engine->getGameType() == GType_Burger)
Burger::g_vars->_flags[(Burger::Flag)_globalToChange] = globalVal;
else
Riddle::g_vars->_flags[(Riddle::Flag)_globalToChange] = globalVal;
_changeGlobalDialog->destroy();
_changeGlobalDialog = nullptr;
}
void Hotkeys::changeGlobalCancel(void *, void *) {
_changeGlobalDialog->destroy();
_changeGlobalDialog = nullptr;
}
void Hotkeys::toggleInfoDialog(void *, void *) {
if (!_G(showMousePos)) {
vmng_screen_show(_G(mousePosDialog));
_G(showMousePos) = true;
pal_override();
} else {
vmng_screen_hide(_G(mousePosDialog));
_G(showMousePos) = false;
}
}
void Hotkeys::other_cheat_with_inventory_objects(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::debug_memory_toggle(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::dbg_pal_toggle(void *, void *) {
warning("TODO: hotkey");
}
void Hotkeys::scale_editor_toggle(void *, void *) {
M4::scale_editor_toggle();
}
void Hotkeys::teleport(void *, void *) {
if (!_teleportDialog) {
gr_font_set(_G(font_tiny));
_teleportDialog = DialogCreateAbsolute(260, 150, 385, 200, 61);
_teleportDialog->addButton(60, 30, " Teleport ", teleportOk, 1);
_teleportDialog->addButton(10, 30, " Cancel ", teleportCancel, 2);
char sep_placeholder[4+1] = "MMMM";
_teleportDialog->addTextField(100, 10, gr_font_string_width(sep_placeholder) + 100,
"---", nullptr, 3, 3);
_teleportDialog->addMessage(10, 12, "Teleport where?", 4);
_teleportDialog->configure(3, 1, 2);
_teleportDialog->show();
pal_override(nullptr, nullptr);
}
}
void Hotkeys::teleportOk(void *, void *) {
Item *textField = _teleportDialog->getItem(3);
_G(game).setRoom(atoi(textField->prompt));
_G(kernel).teleported_in = true;
_teleportDialog->destroy();
_teleportDialog = nullptr;
}
void Hotkeys::teleportCancel(void *, void *) {
_teleportDialog->destroy();
_teleportDialog = nullptr;
}
void Hotkeys::paint_walk_codes(void *, void *) {
Buffer *bgBuff = _G(game_bgBuff)->get_buffer();
Buffer *drawBuff = _G(gameDrawBuff)->get_buffer();
for (int yp = 0; yp < bgBuff->h; ++yp) {
const byte *bgLine = gr_buffer_pointer(bgBuff, 0, yp);
byte *drawLine = gr_buffer_pointer(drawBuff, 0, yp);
for (int xp = 0; xp < bgBuff->w; ++xp, ++bgLine, ++drawLine) {
if (*bgLine & 0x10)
*drawLine = gr_pal_get_ega_color(1);
}
}
_G(game_bgBuff)->release();
_G(gameDrawBuff)->release();
RestoreScreens(0, 0, 639, 479);
}
void Hotkeys::pal_override(void *, void *) {
gr_pal_interface(_G(master_palette));
gr_pal_set(_G(master_palette));
Dialog_Refresh_All();
}
} // End of namespace M4

108
engines/m4/gui/hotkeys.h Normal file
View File

@@ -0,0 +1,108 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_GUI_HOTKEYS_H
#define M4_GUI_HOTKEYS_H
#include "m4/m4_types.h"
#include "m4/gui/gui_dialog.h"
namespace M4 {
enum CursorChange {
CURSCHANGE_NONE, CURSCHANGE_NEXT, CURSCHANGE_PREVIOUS, CURSCHANGE_TOGGLE
};
struct Hotkeys {
private:
static Dialog *_teleportDialog;
static Dialog *_changeGlobalDialog;
static int _globalToChange;
private:
static void exit_program(void *, void *);
static void adv_hyperwalk_to_final_destination(void *a, void *b);
static void saveScreenshot(void *, void *);
static void debug_memory_next_column(void *, void *);
static void debug_memory_prev_column(void *, void *);
static void debug_memory_last_column(void *, void *);
static void player_step_up(void *, void *);
static void player_step_down(void *, void *);
static void player_step_left(void *, void *);
static void player_step_right(void *, void *);
static void player_jump_up(void *, void *);
static void player_jump_down(void *, void *);
static void player_jump_left(void *, void *);
static void player_jump_right(void *, void *);
static void player_step(int xDelta, int yDelta);
static void term_next_mode(void *, void *);
static void camera_step_left(void *, void *);
static void camera_step_right(void *, void *);
static void camera_jump_left(void *, void *);
static void camera_jump_right(void *, void *);
static void toggle_inv_visible(void *, void *);
static void toggle_commands_allowed(void *, void *);
static void debug_memory_dumpcore_to_disk(void *, void *);
static void dbg_mem_set_search(void *, void *);
static void toggleInfoDialog(void *, void *);
static void other_cheat_with_inventory_objects(void *, void *); // was O
static void debug_memory_toggle(void *, void *);
static void dbg_pal_toggle(void *, void *);
static void f_io_report(void *, void *);
static void scale_editor_toggle(void *, void *);
static void teleport(void *, void *);
static void teleportOk(void *, void *);
static void teleportCancel(void *, void *);
static void changeGlobal(void *, void *);
static void changeGlobalCancel(void *, void *);
static void changeGlobalChange(void *, void *);
static void changeGlobalDoChange(void *, void *);
static void paint_walk_codes(void *, void *);
static void pal_override(void *a = nullptr, void *b = nullptr);
protected:
virtual void adv_enable_system_hot_keys();
public:
Hotkeys();
virtual ~Hotkeys() {}
virtual void add_hot_keys();
void disable_hot_keys();
static void saveGame(void *, void *);
static void loadGame(void *, void *);
virtual void toggle_through_cursors(CursorChange cursChange = CURSCHANGE_NEXT) = 0;
};
} // End of namespace M4
#endif