Initial commit
This commit is contained in:
437
engines/m4/gui/game_menu.cpp
Normal file
437
engines/m4/gui/game_menu.cpp
Normal 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
|
||||
90
engines/m4/gui/game_menu.h
Normal file
90
engines/m4/gui/game_menu.h
Normal 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
77
engines/m4/gui/gui.h
Normal 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
|
||||
145
engines/m4/gui/gui_buffer.cpp
Normal file
145
engines/m4/gui/gui_buffer.cpp
Normal 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
|
||||
72
engines/m4/gui/gui_buffer.h
Normal file
72
engines/m4/gui/gui_buffer.h
Normal 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
|
||||
530
engines/m4/gui/gui_cheapo.cpp
Normal file
530
engines/m4/gui/gui_cheapo.cpp
Normal 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
164
engines/m4/gui/gui_cheapo.h
Normal 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
|
||||
1551
engines/m4/gui/gui_dialog.cpp
Normal file
1551
engines/m4/gui/gui_dialog.cpp
Normal file
File diff suppressed because it is too large
Load Diff
185
engines/m4/gui/gui_dialog.h
Normal file
185
engines/m4/gui/gui_dialog.h
Normal 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
|
||||
36
engines/m4/gui/gui_event.h
Normal file
36
engines/m4/gui/gui_event.h
Normal 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
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
160
engines/m4/gui/gui_item.h
Normal 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
|
||||
2247
engines/m4/gui/gui_menu_items.cpp
Normal file
2247
engines/m4/gui/gui_menu_items.cpp
Normal file
File diff suppressed because it is too large
Load Diff
395
engines/m4/gui/gui_menu_items.h
Normal file
395
engines/m4/gui/gui_menu_items.h
Normal 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
|
||||
306
engines/m4/gui/gui_mouse.cpp
Normal file
306
engines/m4/gui/gui_mouse.cpp
Normal 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
|
||||
80
engines/m4/gui/gui_mouse.h
Normal file
80
engines/m4/gui/gui_mouse.h
Normal 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
252
engines/m4/gui/gui_sys.cpp
Normal 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
62
engines/m4/gui/gui_sys.h
Normal 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
69
engines/m4/gui/gui_univ.h
Normal 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
67
engines/m4/gui/gui_vmng.h
Normal 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
|
||||
325
engines/m4/gui/gui_vmng_core.cpp
Normal file
325
engines/m4/gui/gui_vmng_core.cpp
Normal 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
|
||||
122
engines/m4/gui/gui_vmng_core.h
Normal file
122
engines/m4/gui/gui_vmng_core.h
Normal 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
|
||||
503
engines/m4/gui/gui_vmng_rectangles.cpp
Normal file
503
engines/m4/gui/gui_vmng_rectangles.cpp
Normal 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
|
||||
42
engines/m4/gui/gui_vmng_rectangles.h
Normal file
42
engines/m4/gui/gui_vmng_rectangles.h
Normal 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
|
||||
362
engines/m4/gui/gui_vmng_screen.cpp
Normal file
362
engines/m4/gui/gui_vmng_screen.cpp
Normal 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
|
||||
108
engines/m4/gui/gui_vmng_screen.h
Normal file
108
engines/m4/gui/gui_vmng_screen.h
Normal 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
406
engines/m4/gui/hotkeys.cpp
Normal 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
108
engines/m4/gui/hotkeys.h
Normal 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
|
||||
Reference in New Issue
Block a user