mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-17 07:07:10 +00:00
MADS: Properly implement drawing to a subset of the screen
This commit is contained in:
parent
4be8aa8906
commit
82b2b2d65d
@ -546,8 +546,7 @@ void TextDisplayList::draw(MSurface *s) {
|
||||
for (uint idx = 0; idx < size(); ++idx) {
|
||||
TextDisplay &td = (*this)[idx];
|
||||
if (td._active && (td._expire >= 0)) {
|
||||
Common::Point destPos(td._bounds.left + _vm->_screen._offset.x,
|
||||
td._bounds.top + _vm->_screen._offset.y);
|
||||
Common::Point destPos(td._bounds.left, td._bounds.top);
|
||||
td._font->setColors(0xFF, td._color1, td._color2, 0);
|
||||
td._font->writeString(s, td._msg, destPos, td._spacing, td._bounds.width());
|
||||
}
|
||||
|
@ -51,10 +51,9 @@ struct SpriteInfo {
|
||||
* MADS graphics surface
|
||||
*/
|
||||
class MSurface : public Graphics::Surface {
|
||||
private:
|
||||
bool _freeFlag;
|
||||
protected:
|
||||
static MADSEngine *_vm;
|
||||
bool _freeFlag;
|
||||
public:
|
||||
/**
|
||||
* Sets the engine refrence used all surfaces
|
||||
|
@ -346,7 +346,6 @@ void DialogsNebular::showScummVMSaveDialog() {
|
||||
}
|
||||
|
||||
scene->_spriteSlots.reset();
|
||||
_vm->_screen._offset.y = 0;
|
||||
scene->loadScene(scene->_currentSceneId, game._aaName, true);
|
||||
scene->_userInterface.noInventoryAnim();
|
||||
game._scene.drawElements(kTransitionFadeIn, false);
|
||||
@ -560,7 +559,8 @@ FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
|
||||
}
|
||||
|
||||
FullScreenDialog::~FullScreenDialog() {
|
||||
_vm->_screen._offset.y = 0;
|
||||
_vm->_screen.resetClipBounds();
|
||||
_vm->_game->_scene.restrictScene();
|
||||
}
|
||||
|
||||
void FullScreenDialog::display() {
|
||||
@ -577,7 +577,6 @@ void FullScreenDialog::display() {
|
||||
scene._currentSceneId = currentSceneId;
|
||||
scene._nextSceneId = nextSceneId;
|
||||
|
||||
_vm->_screen._offset.y = 22;
|
||||
_vm->_events->initVars();
|
||||
game._kernelMode = KERNEL_ROOM_INIT;
|
||||
|
||||
@ -590,11 +589,7 @@ void FullScreenDialog::display() {
|
||||
_vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16);
|
||||
}
|
||||
|
||||
_vm->_screen.empty();
|
||||
_vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
|
||||
_vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
|
||||
game._scene._spriteSlots.fullRefresh();
|
||||
|
||||
// Set Fx state and palette entries
|
||||
game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition;
|
||||
game._trigger = 0;
|
||||
|
||||
@ -604,6 +599,18 @@ void FullScreenDialog::display() {
|
||||
_vm->_palette->setEntry(13, 45, 45, 0);
|
||||
_vm->_palette->setEntry(14, 63, 63, 63);
|
||||
_vm->_palette->setEntry(15, 45, 45, 45);
|
||||
|
||||
|
||||
// Clear the screen and draw the upper and lower horizontal lines
|
||||
_vm->_screen.empty();
|
||||
_vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
|
||||
_vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
|
||||
_vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
|
||||
|
||||
// Restrict the screen to the area between the two lines
|
||||
_vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
|
||||
DIALOG_TOP + MADS_SCENE_HEIGHT));
|
||||
_vm->_game->_scene.restrictScene();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -667,7 +674,7 @@ void GameDialog::display() {
|
||||
}
|
||||
|
||||
GameDialog::~GameDialog() {
|
||||
_vm->_screen._offset.y = 0;
|
||||
_vm->_screen.resetClipBounds();
|
||||
}
|
||||
|
||||
void GameDialog::clearLines() {
|
||||
@ -868,10 +875,11 @@ void GameDialog::handleEvents() {
|
||||
_vm->_events->pollEvents();
|
||||
|
||||
// Scan for objects in the dialog
|
||||
int objIndex = screenObjects.scan(events.currentPos() - _vm->_screen._offset, LAYER_GUI);
|
||||
Common::Point mousePos = events.currentPos() - Common::Point(0, DIALOG_TOP);
|
||||
int objIndex = screenObjects.scan(mousePos, LAYER_GUI);
|
||||
|
||||
if (_movedFlag) {
|
||||
int yp = events.currentPos().y - _vm->_screen._offset.y;
|
||||
int yp = mousePos.y;
|
||||
if (yp < screenObjects[1]._bounds.top) {
|
||||
if (!events._mouseReleased)
|
||||
_lines[1]._state = DLGSTATE_SELECTED;
|
||||
|
@ -31,6 +31,8 @@ namespace MADS {
|
||||
|
||||
namespace Nebular {
|
||||
|
||||
#define DIALOG_TOP 22
|
||||
|
||||
enum CapitalizationMode { kUppercase = 0, kLowercase = 1, kUpperAndLower = 2 };
|
||||
|
||||
class DialogsNebular : public Dialogs {
|
||||
|
@ -35,7 +35,6 @@ namespace Nebular {
|
||||
#define NEBULAR_MENUSCREEN 990
|
||||
#define MADS_MENU_Y ((MADS_SCREEN_HEIGHT - MADS_SCENE_HEIGHT) / 2)
|
||||
#define MADS_MENU_ANIM_DELAY 70
|
||||
#define DIALOG_TOP 22
|
||||
|
||||
MenuView::MenuView(MADSEngine *vm) : FullScreenDialog(vm) {
|
||||
_breakFlag = false;
|
||||
@ -57,7 +56,6 @@ void MenuView::show() {
|
||||
while (!_breakFlag && !_vm->shouldQuit()) {
|
||||
if (_redrawFlag) {
|
||||
_vm->_game->_scene.drawElements(_vm->_game->_fx, _vm->_game->_fx);
|
||||
_vm->_screen.copyRectToScreen(Common::Rect(0, 0, 320, 200));
|
||||
_redrawFlag = false;
|
||||
}
|
||||
|
||||
@ -111,10 +109,10 @@ void MainMenu::display() {
|
||||
// Register the menu item area in the screen objects
|
||||
MSprite *frame0 = _menuItems[i]->getFrame(0);
|
||||
Common::Point pt(frame0->_offset.x - (frame0->w / 2),
|
||||
frame0->_offset.y - frame0->h + _vm->_screen._offset.y);
|
||||
frame0->_offset.y - frame0->h);
|
||||
screenObjects.add(
|
||||
Common::Rect(pt.x, pt.y, pt.x + frame0->w, pt.y + frame0->h),
|
||||
LAYER_GUI, CAT_COMMAND, i);
|
||||
Common::Rect(pt.x, pt.y + DIALOG_TOP, pt.x + frame0->w,
|
||||
pt.y + frame0->h + DIALOG_TOP), LAYER_GUI, CAT_COMMAND, i);
|
||||
}
|
||||
|
||||
// Set the cursor for when it's shown
|
||||
|
@ -63,8 +63,7 @@ Scene::Scene(MADSEngine *vm)
|
||||
_paletteUsageF.push_back(PaletteUsage::UsageEntry(0xF));
|
||||
|
||||
// Set up a scene surface that maps to our physical screen drawing surface
|
||||
_sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
|
||||
_vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
|
||||
restrictScene();
|
||||
|
||||
// Set up the verb list
|
||||
_verbList.push_back(VerbInit(VERB_LOOK, VERB_THAT, PREP_NONE));
|
||||
@ -85,6 +84,11 @@ Scene::~Scene() {
|
||||
delete _animationData;
|
||||
}
|
||||
|
||||
void Scene::restrictScene() {
|
||||
_sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
|
||||
_vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
|
||||
}
|
||||
|
||||
void Scene::clearVocab() {
|
||||
_activeVocabs.clear();
|
||||
}
|
||||
@ -511,7 +515,7 @@ void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
|
||||
_vm->_sound->startQueuedCommands();
|
||||
} else {
|
||||
// Copy dirty areas to the screen
|
||||
_dirtyAreas.copyToScreen(_vm->_screen._offset);
|
||||
_dirtyAreas.copyToScreen();
|
||||
}
|
||||
|
||||
_spriteSlots.cleanUp();
|
||||
|
@ -142,6 +142,8 @@ public:
|
||||
*/
|
||||
~Scene();
|
||||
|
||||
void restrictScene();
|
||||
|
||||
/**
|
||||
* Clear the vocabulary list
|
||||
*/
|
||||
|
@ -212,8 +212,7 @@ void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common:
|
||||
|
||||
Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
|
||||
srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
|
||||
Common::Point destPos(bounds.left + _vm->_screen._offset.x,
|
||||
bounds.top + _vm->_screen._offset.y);
|
||||
Common::Point destPos(bounds.left, bounds.top);
|
||||
|
||||
if ((*this)[i]._active && bounds.isValidRect()) {
|
||||
srcSurface->copyTo(destSurface, bounds, destPos);
|
||||
@ -221,17 +220,14 @@ void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common:
|
||||
}
|
||||
}
|
||||
|
||||
void DirtyAreas::copyToScreen(const Common::Point &posAdjust) {
|
||||
void DirtyAreas::copyToScreen() {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
const Common::Rect &srcBounds = (*this)[i]._bounds;
|
||||
const Common::Rect &bounds = (*this)[i]._bounds;
|
||||
|
||||
// Check if this is a sane rectangle before attempting to create it
|
||||
if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom)
|
||||
if (bounds.left >= bounds.right || bounds.top >= bounds.bottom)
|
||||
continue;
|
||||
|
||||
Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
|
||||
srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
|
||||
|
||||
if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) {
|
||||
_vm->_screen.copyRectToScreen(bounds);
|
||||
}
|
||||
@ -561,23 +557,32 @@ void ScreenObjects::synchronize(Common::Serializer &s) {
|
||||
ScreenSurface::ScreenSurface() {
|
||||
_shakeCountdown = -1;
|
||||
_random = 0x4D2;
|
||||
_surfacePixels = nullptr;
|
||||
}
|
||||
|
||||
void ScreenSurface::init() {
|
||||
setSize(g_system->getWidth(), g_system->getHeight());
|
||||
// Set the size for the screen
|
||||
setSize(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
|
||||
|
||||
// Store a copy of the raw pixels pointer for the screen, since the surface
|
||||
// itself may be later changed to only a subset of the screen
|
||||
_surfacePixels = (byte *)getPixels();
|
||||
_freeFlag = false;
|
||||
}
|
||||
|
||||
void ScreenSurface::copyRectToScreen(const Common::Point &destPos,
|
||||
const Common::Rect &bounds) {
|
||||
const byte *buf = getBasePtr(destPos.x, destPos.y);
|
||||
|
||||
if (bounds.width() != 0 && bounds.height() != 0)
|
||||
g_system->copyRectToScreen(buf, this->pitch, bounds.left, bounds.top,
|
||||
bounds.width(), bounds.height());
|
||||
ScreenSurface::~ScreenSurface() {
|
||||
delete[] _surfacePixels;
|
||||
}
|
||||
|
||||
void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) {
|
||||
copyRectToScreen(Common::Point(bounds.left, bounds.top), bounds);
|
||||
const byte *buf = getBasePtr(bounds.left, bounds.top);
|
||||
|
||||
Common::Rect destBounds = bounds;
|
||||
destBounds.translate(_clipBounds.left, _clipBounds.top);
|
||||
|
||||
if (bounds.width() != 0 && bounds.height() != 0)
|
||||
g_system->copyRectToScreen(buf, this->pitch, destBounds.left, destBounds.top,
|
||||
destBounds.width(), destBounds.height());
|
||||
}
|
||||
|
||||
void ScreenSurface::updateScreen() {
|
||||
@ -659,4 +664,15 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenSurface::setClipBounds(const Common::Rect &r) {
|
||||
_clipBounds = r;
|
||||
setPixels(_surfacePixels + pitch * r.top + r.left, r.width(), r.height());
|
||||
this->pitch = MADS_SCREEN_WIDTH;
|
||||
}
|
||||
|
||||
void ScreenSurface::resetClipBounds() {
|
||||
setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace MADS
|
||||
|
@ -117,8 +117,8 @@ public:
|
||||
/**
|
||||
* Use the lsit of dirty areas to copy areas of the screen surface to
|
||||
* the physical screen
|
||||
* @param posAdjust Position adjustment */
|
||||
void copyToScreen(const Common::Point &posAdjust);
|
||||
*/
|
||||
void copyToScreen();
|
||||
|
||||
void reset();
|
||||
};
|
||||
@ -205,8 +205,9 @@ public:
|
||||
class ScreenSurface : public MSurface {
|
||||
private:
|
||||
uint16 _random;
|
||||
byte *_surfacePixels;
|
||||
Common::Rect _clipBounds;
|
||||
public:
|
||||
Common::Point _offset;
|
||||
int _shakeCountdown;
|
||||
public:
|
||||
/**
|
||||
@ -214,19 +215,16 @@ public:
|
||||
*/
|
||||
ScreenSurface();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ScreenSurface();
|
||||
|
||||
/**
|
||||
* Initialize the surface
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Copys an area of the screen surface to a given destination position on
|
||||
* the ScummVM physical screen buffer
|
||||
* @param destPos Destination position
|
||||
* @param bounds Area of screen surface to copy
|
||||
*/
|
||||
void copyRectToScreen(const Common::Point &destPos, const Common::Rect &bounds);
|
||||
|
||||
/**
|
||||
* Copys an area of the screen surface to the ScmmVM physical screen buffer
|
||||
* @param bounds Area of screen surface to copy
|
||||
@ -239,6 +237,12 @@ public:
|
||||
void updateScreen();
|
||||
|
||||
void transition(ScreenTransition transitionType, bool surfaceFlag);
|
||||
|
||||
void setClipBounds(const Common::Rect &r);
|
||||
|
||||
void resetClipBounds();
|
||||
|
||||
const Common::Rect &getClipBounds() { return _clipBounds; }
|
||||
};
|
||||
|
||||
} // End of namespace MADS
|
||||
|
@ -331,8 +331,6 @@ void SpriteSlots::drawSprites(MSurface *s) {
|
||||
xp = slot._position.x - (sprite->w / 2) - scene._posAdjust.x;
|
||||
yp = slot._position.y - sprite->h - scene._posAdjust.y + 1;
|
||||
}
|
||||
xp += _vm->_screen._offset.x;
|
||||
yp += _vm->_screen._offset.y;
|
||||
|
||||
if (slot._depth > 1) {
|
||||
// Draw the frame with depth processing
|
||||
|
Loading…
Reference in New Issue
Block a user