2010-02-02 16:25:35 +00:00
/* 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 2
* of the License , or ( at your option ) any later version .
2014-02-18 02:34:24 +01:00
*
2010-02-02 16:25:35 +00:00
* 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 .
2014-02-18 02:34:24 +01:00
*
2010-02-02 16:25:35 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
2011-04-24 11:34:27 +03:00
# include "common/algorithm.h"
2016-02-21 17:21:48 +01:00
# include "common/config-manager.h"
2011-04-24 11:34:27 +03:00
# include "common/events.h"
# include "common/keyboard.h"
2016-01-02 15:32:38 +02:00
# include "common/list.h"
2011-04-24 11:34:27 +03:00
# include "common/str.h"
# include "common/system.h"
# include "common/textconsole.h"
# include "engines/engine.h"
2016-07-28 14:49:13 -05:00
# include "engines/util.h"
2012-08-16 13:30:32 -04:00
# include "graphics/palette.h"
2011-04-24 11:34:27 +03:00
# include "graphics/surface.h"
2010-02-02 16:25:35 +00:00
# include "sci/sci.h"
2012-05-21 01:29:30 +03:00
# include "sci/console.h"
2010-06-23 15:23:37 +00:00
# include "sci/engine/kernel.h"
2010-02-02 16:25:35 +00:00
# include "sci/engine/state.h"
# include "sci/engine/selector.h"
# include "sci/engine/vm.h"
# include "sci/graphics/cache.h"
2011-10-19 20:27:43 +03:00
# include "sci/graphics/compare.h"
2016-07-31 13:41:05 -05:00
# include "sci/graphics/cursor32.h"
2010-02-03 01:36:53 +00:00
# include "sci/graphics/font.h"
2016-07-03 17:57:58 -05:00
# include "sci/graphics/frameout.h"
2010-02-04 17:57:44 +00:00
# include "sci/graphics/paint32.h"
2016-01-06 20:00:28 -06:00
# include "sci/graphics/palette32.h"
2016-01-18 00:12:47 -06:00
# include "sci/graphics/plane32.h"
2016-06-25 14:19:47 -05:00
# include "sci/graphics/remap32.h"
2016-07-03 17:57:58 -05:00
# include "sci/graphics/screen.h"
2016-01-18 00:12:47 -06:00
# include "sci/graphics/screen_item32.h"
2016-06-25 14:19:47 -05:00
# include "sci/graphics/text32.h"
2010-02-02 16:25:35 +00:00
# include "sci/graphics/frameout.h"
2016-07-25 11:06:27 -05:00
# include "sci/graphics/transitions32.h"
2016-07-03 17:57:58 -05:00
# include "sci/graphics/video32.h"
2010-02-02 16:25:35 +00:00
namespace Sci {
2016-08-19 11:53:04 -05:00
GfxFrameout : : GfxFrameout ( SegManager * segMan , GfxPalette32 * palette , GfxTransitions32 * transitions , GfxCursor32 * cursor ) :
2016-09-09 16:17:41 -05:00
_isHiRes ( gameIsHiRes ( ) ) ,
2016-01-18 00:12:47 -06:00
_palette ( palette ) ,
2016-07-31 13:41:05 -05:00
_cursor ( cursor ) ,
2016-02-18 21:09:15 -06:00
_segMan ( segMan ) ,
2016-07-25 11:06:27 -05:00
_transitions ( transitions ) ,
2016-06-14 17:43:57 -05:00
_benchmarkingFinished ( false ) ,
_throttleFrameOut ( true ) ,
2016-07-01 19:47:15 -05:00
_throttleState ( 0 ) ,
2016-02-18 21:09:15 -06:00
_remapOccurred ( false ) ,
_frameNowVisible ( false ) ,
_overdrawThreshold ( 0 ) ,
_palMorphIsOn ( false ) {
2016-01-18 00:12:47 -06:00
2016-07-28 14:49:13 -05:00
if ( g_sci - > getGameId ( ) = = GID_PHANTASMAGORIA ) {
_currentBuffer = Buffer ( 630 , 450 , nullptr ) ;
} else if ( _isHiRes ) {
_currentBuffer = Buffer ( 640 , 480 , nullptr ) ;
} else {
_currentBuffer = Buffer ( 320 , 200 , nullptr ) ;
}
_currentBuffer . setPixels ( calloc ( 1 , _currentBuffer . screenWidth * _currentBuffer . screenHeight ) ) ;
_screenRect = Common : : Rect ( _currentBuffer . screenWidth , _currentBuffer . screenHeight ) ;
initGraphics ( _currentBuffer . screenWidth , _currentBuffer . screenHeight , _isHiRes ) ;
2016-03-18 18:49:10 -05:00
switch ( g_sci - > getGameId ( ) ) {
2016-07-11 13:02:05 -05:00
case GID_HOYLE5 :
2016-03-18 18:49:10 -05:00
case GID_GK2 :
case GID_LIGHTHOUSE :
case GID_LSL7 :
case GID_PHANTASMAGORIA2 :
case GID_PQSWAT :
case GID_TORIN :
case GID_RAMA :
_currentBuffer . scriptWidth = 640 ;
_currentBuffer . scriptHeight = 480 ;
break ;
default :
// default script width for other games is 320x200
break ;
}
2010-02-02 16:25:35 +00:00
}
GfxFrameout : : ~ GfxFrameout ( ) {
2012-01-15 18:35:33 +02:00
clear ( ) ;
2016-03-06 16:40:23 -06:00
CelObj : : deinit ( ) ;
free ( _currentBuffer . getPixels ( ) ) ;
2010-02-02 16:25:35 +00:00
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : run ( ) {
CelObj : : init ( ) ;
Plane : : init ( ) ;
ScreenItem : : init ( ) ;
// NOTE: This happens in SCI::InitPlane in the actual engine,
// and is a background fill plane to ensure hidden planes
// (planes with a priority of -1) are never drawn
2016-02-18 00:07:28 -06:00
Plane * initPlane = new Plane ( Common : : Rect ( _currentBuffer . scriptWidth , _currentBuffer . scriptHeight ) ) ;
2016-01-18 00:12:47 -06:00
initPlane - > _priority = 0 ;
_planes . add ( initPlane ) ;
}
2016-02-21 17:21:48 +01:00
// SCI32 actually did not clear anything at all it seems on restore. The scripts actually cleared up
// planes + screen items right before restoring. And after restoring they sync'd its internal planes list
// as well.
2011-02-14 22:38:12 -05:00
void GfxFrameout : : clear ( ) {
_planes . clear ( ) ;
2016-02-21 01:44:28 +01:00
_visiblePlanes . clear ( ) ;
2016-01-18 00:12:47 -06:00
_showList . clear ( ) ;
}
2016-02-21 17:21:48 +01:00
// This is what Game::restore does, only needed when our ScummVM dialogs are patched in
// It actually does one pass before actual restore deleting screen items + planes
// And after restore it does another pass adding screen items + planes.
2016-02-21 17:30:25 +01:00
// Attention: at least Space Quest 6's option plane seems to stay in memory right from the start and is not re-created.
2016-02-21 17:21:48 +01:00
void GfxFrameout : : syncWithScripts ( bool addElements ) {
EngineState * engineState = g_sci - > getEngineState ( ) ;
SegManager * segMan = engineState - > _segMan ;
// In case original save/restore dialogs are active, don't do anything
if ( ConfMan . getBool ( " originalsaveload " ) )
return ;
// Get planes list object
2016-09-26 19:28:51 -05:00
reg_t planesListObject = engineState - > variables [ VAR_GLOBAL ] [ kGlobalVarPlanes ] ;
2016-02-21 17:21:48 +01:00
reg_t planesListElements = readSelector ( segMan , planesListObject , SELECTOR ( elements ) ) ;
List * planesList = segMan - > lookupList ( planesListElements ) ;
reg_t planesNodeObject = planesList - > first ;
// Go through all elements of planes::elements
while ( ! planesNodeObject . isNull ( ) ) {
Node * planesNode = segMan - > lookupNode ( planesNodeObject ) ;
reg_t planeObject = planesNode - > value ;
if ( addElements ) {
// Add this plane object
kernelAddPlane ( planeObject ) ;
}
reg_t planeCastsObject = readSelector ( segMan , planeObject , SELECTOR ( casts ) ) ;
reg_t setListElements = readSelector ( segMan , planeCastsObject , SELECTOR ( elements ) ) ;
// Now go through all elements of plane::casts::elements
List * planeCastsList = segMan - > lookupList ( setListElements ) ;
reg_t planeCastsNodeObject = planeCastsList - > first ;
while ( ! planeCastsNodeObject . isNull ( ) ) {
Node * castsNode = segMan - > lookupNode ( planeCastsNodeObject ) ;
2016-02-21 20:56:00 +01:00
reg_t castsObject = castsNode - > value ;
2016-02-21 17:21:48 +01:00
2016-02-21 20:56:00 +01:00
reg_t castsListElements = readSelector ( segMan , castsObject , SELECTOR ( elements ) ) ;
2016-02-21 17:21:48 +01:00
2016-02-21 20:56:00 +01:00
List * castsList = segMan - > lookupList ( castsListElements ) ;
reg_t castNodeObject = castsList - > first ;
2016-02-21 17:21:48 +01:00
while ( ! castNodeObject . isNull ( ) ) {
Node * castNode = segMan - > lookupNode ( castNodeObject ) ;
reg_t castObject = castNode - > value ;
// read selector "-info-" of this object
// TODO: Seems to have been changed for SCI3
2016-02-21 20:32:42 +01:00
// Do NOT use getInfoSelector in here. SCI3 games did not use infoToa, but an actual selector.
// Maybe that selector is just a straight copy, but it needs to get verified/checked.
2016-02-21 17:21:48 +01:00
uint16 castInfoSelector = readSelectorValue ( segMan , castObject , SELECTOR ( _info_ ) ) ;
if ( castInfoSelector & kInfoFlagViewInserted ) {
if ( addElements ) {
// Flag set, so add this screen item
kernelAddScreenItem ( castObject ) ;
} else {
// Flag set, so delete this screen item
kernelDeleteScreenItem ( castObject ) ;
}
}
castNodeObject = castNode - > succ ;
}
planeCastsNodeObject = castsNode - > succ ;
}
if ( ! addElements ) {
// Delete this plane object
kernelDeletePlane ( planeObject ) ;
}
planesNodeObject = planesNode - > succ ;
}
}
2016-09-09 16:17:41 -05:00
bool GfxFrameout : : gameIsHiRes ( ) const {
// QFG4 is always low resolution
if ( g_sci - > getGameId ( ) = = GID_QFG4 ) {
return false ;
}
// GK1 DOS floppy is low resolution only, but GK1 Mac floppy is high
// resolution only
if ( g_sci - > getGameId ( ) = = GID_GK1 & &
! g_sci - > isCD ( ) & &
g_sci - > getPlatform ( ) ! = Common : : kPlatformMacintosh ) {
return false ;
}
// All other games are either high resolution by default, or have a
// user-defined toggle
return ConfMan . getBool ( " enable_high_resolution_graphics " ) ;
}
2016-06-26 10:52:17 -05:00
# pragma mark -
# pragma mark Benchmarking
bool GfxFrameout : : checkForFred ( const reg_t object ) {
const int16 viewId = readSelectorValue ( _segMan , object , SELECTOR ( view ) ) ;
const SciGameId gameId = g_sci - > getGameId ( ) ;
if ( gameId = = GID_QFG4 & & viewId = = 9999 ) {
return true ;
}
if ( gameId ! = GID_QFG4 & & viewId = = - 556 ) {
return true ;
}
if ( Common : : String ( _segMan - > getObjectName ( object ) ) = = " fred " ) {
return true ;
}
return false ;
}
2016-01-18 00:12:47 -06:00
# pragma mark -
# pragma mark Screen items
2016-07-02 19:11:46 -05:00
void GfxFrameout : : addScreenItem ( ScreenItem & screenItem ) const {
Plane * plane = _planes . findByObject ( screenItem . _plane ) ;
if ( plane = = nullptr ) {
error ( " GfxFrameout::addScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x " , PRINT_REG ( screenItem . _plane ) , PRINT_REG ( screenItem . _object ) ) ;
}
plane - > _screenItemList . add ( & screenItem ) ;
}
void GfxFrameout : : updateScreenItem ( ScreenItem & screenItem ) const {
// TODO: In SCI3+ this will need to go through Plane
// Plane *plane = _planes.findByObject(screenItem._plane);
// if (plane == nullptr) {
// error("GfxFrameout::updateScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x", PRINT_REG(screenItem._plane), PRINT_REG(screenItem._object));
// }
screenItem . update ( ) ;
}
void GfxFrameout : : deleteScreenItem ( ScreenItem & screenItem ) {
Plane * plane = _planes . findByObject ( screenItem . _plane ) ;
if ( plane = = nullptr ) {
error ( " GfxFrameout::deleteScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x " , PRINT_REG ( screenItem . _plane ) , PRINT_REG ( screenItem . _object ) ) ;
}
if ( plane - > _screenItemList . findByObject ( screenItem . _object ) = = nullptr ) {
error ( " GfxFrameout::deleteScreenItem: Screen item %04x:%04x not found in plane %04x:%04x " , PRINT_REG ( screenItem . _object ) , PRINT_REG ( screenItem . _plane ) ) ;
}
deleteScreenItem ( screenItem , * plane ) ;
}
void GfxFrameout : : deleteScreenItem ( ScreenItem & screenItem , Plane & plane ) {
if ( screenItem . _created = = 0 ) {
screenItem . _created = 0 ;
screenItem . _updated = 0 ;
screenItem . _deleted = getScreenCount ( ) ;
2016-06-18 20:48:10 -05:00
} else {
2016-07-02 19:11:46 -05:00
plane . _screenItemList . erase ( & screenItem ) ;
plane . _screenItemList . pack ( ) ;
2016-06-18 20:48:10 -05:00
}
}
2016-07-02 19:11:46 -05:00
void GfxFrameout : : deleteScreenItem ( ScreenItem & screenItem , const reg_t planeObject ) {
2016-06-18 20:48:10 -05:00
Plane * plane = _planes . findByObject ( planeObject ) ;
2016-07-02 19:11:46 -05:00
if ( plane = = nullptr ) {
error ( " GfxFrameout::deleteScreenItem: Could not find plane %04x:%04x for screen item %04x:%04x " , PRINT_REG ( planeObject ) , PRINT_REG ( screenItem . _object ) ) ;
}
deleteScreenItem ( screenItem , * plane ) ;
2016-06-18 20:48:10 -05:00
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelAddScreenItem ( const reg_t object ) {
2016-06-14 17:43:57 -05:00
// The "fred" object is used to test graphics performance;
// it is impacted by framerate throttling, so disable the
// throttling when this item is on the screen for the
// performance check to pass.
2016-06-26 10:52:17 -05:00
if ( ! _benchmarkingFinished & & _throttleFrameOut & & checkForFred ( object ) ) {
2016-06-14 17:43:57 -05:00
_throttleFrameOut = false ;
}
2016-01-18 00:12:47 -06:00
const reg_t planeObject = readSelector ( _segMan , object , SELECTOR ( plane ) ) ;
_segMan - > getObject ( object ) - > setInfoSelectorFlag ( kInfoFlagViewInserted ) ;
Plane * plane = _planes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kAddScreenItem: Plane %04x:%04x not found for screen item %04x:%04x " , PRINT_REG ( planeObject ) , PRINT_REG ( object ) ) ;
2016-01-18 00:12:47 -06:00
}
ScreenItem * screenItem = plane - > _screenItemList . findByObject ( object ) ;
if ( screenItem ! = nullptr ) {
screenItem - > update ( object ) ;
2012-06-07 11:26:32 +03:00
} else {
2016-01-18 00:12:47 -06:00
screenItem = new ScreenItem ( object ) ;
plane - > _screenItemList . add ( screenItem ) ;
2012-06-07 11:26:32 +03:00
}
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelUpdateScreenItem ( const reg_t object ) {
const reg_t magnifierObject = readSelector ( _segMan , object , SELECTOR ( magnifier ) ) ;
if ( magnifierObject . isNull ( ) ) {
const reg_t planeObject = readSelector ( _segMan , object , SELECTOR ( plane ) ) ;
Plane * plane = _planes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kUpdateScreenItem: Plane %04x:%04x not found for screen item %04x:%04x " , PRINT_REG ( planeObject ) , PRINT_REG ( object ) ) ;
2016-01-18 00:12:47 -06:00
}
2012-06-07 11:26:32 +03:00
2016-01-18 00:12:47 -06:00
ScreenItem * screenItem = plane - > _screenItemList . findByObject ( object ) ;
if ( screenItem = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kUpdateScreenItem: Screen item %04x:%04x not found in plane %04x:%04x " , PRINT_REG ( object ) , PRINT_REG ( planeObject ) ) ;
2016-01-18 00:12:47 -06:00
}
2010-09-19 14:50:28 +00:00
2016-01-18 00:12:47 -06:00
screenItem - > update ( object ) ;
} else {
2016-03-07 17:27:38 -06:00
error ( " Magnifier view is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
2016-01-18 00:12:47 -06:00
}
}
2010-09-19 14:50:28 +00:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelDeleteScreenItem ( const reg_t object ) {
2016-06-14 17:43:57 -05:00
// The "fred" object is used to test graphics performance;
// it is impacted by framerate throttling, so disable the
// throttling when this item is on the screen for the
// performance check to pass.
2016-06-26 10:52:17 -05:00
if ( ! _benchmarkingFinished & & checkForFred ( object ) ) {
2016-06-14 17:43:57 -05:00
_benchmarkingFinished = true ;
_throttleFrameOut = true ;
}
2016-01-18 00:12:47 -06:00
_segMan - > getObject ( object ) - > clearInfoSelectorFlag ( kInfoFlagViewInserted ) ;
2012-09-26 04:17:31 +02:00
2016-01-18 00:12:47 -06:00
const reg_t planeObject = readSelector ( _segMan , object , SELECTOR ( plane ) ) ;
Plane * plane = _planes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
return ;
}
2011-10-14 13:51:59 +03:00
2016-01-18 00:12:47 -06:00
ScreenItem * screenItem = plane - > _screenItemList . findByObject ( object ) ;
if ( screenItem = = nullptr ) {
return ;
}
2010-09-19 14:50:28 +00:00
2016-07-02 19:11:46 -05:00
deleteScreenItem ( * screenItem , * plane ) ;
2016-01-18 00:12:47 -06:00
}
2010-09-19 14:50:28 +00:00
2016-01-18 00:12:47 -06:00
# pragma mark -
# pragma mark Planes
2010-10-23 19:23:07 +00:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelAddPlane ( const reg_t object ) {
Plane * plane = _planes . findByObject ( object ) ;
if ( plane ! = nullptr ) {
plane - > update ( object ) ;
updatePlane ( * plane ) ;
} else {
plane = new Plane ( object ) ;
addPlane ( * plane ) ;
}
}
2010-10-23 19:23:07 +00:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelUpdatePlane ( const reg_t object ) {
Plane * plane = _planes . findByObject ( object ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kUpdatePlane: Plane %04x:%04x not found " , PRINT_REG ( object ) ) ;
2010-07-24 16:47:12 +00:00
}
2016-01-18 00:12:47 -06:00
plane - > update ( object ) ;
updatePlane ( * plane ) ;
2010-02-02 16:25:35 +00:00
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : kernelDeletePlane ( const reg_t object ) {
Plane * plane = _planes . findByObject ( object ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kDeletePlane: Plane %04x:%04x not found " , PRINT_REG ( object ) ) ;
2016-01-18 00:12:47 -06:00
}
2012-01-14 14:22:23 +02:00
2016-01-18 00:12:47 -06:00
if ( plane - > _created ) {
// NOTE: The original engine calls some `AbortPlane` function that
// just ends up doing this anyway so we skip the extra indirection
_planes . erase ( plane ) ;
} else {
plane - > _created = 0 ;
plane - > _deleted = g_sci - > _gfxFrameout - > getScreenCount ( ) ;
}
}
2010-07-25 19:56:44 +00:00
2016-03-05 23:56:38 -06:00
void GfxFrameout : : deletePlane ( Plane & planeToFind ) {
Plane * plane = _planes . findByObject ( planeToFind . _object ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " deletePlane: Plane %04x:%04x not found " , PRINT_REG ( planeToFind . _object ) ) ;
2016-03-05 23:56:38 -06:00
}
if ( plane - > _created ) {
_planes . erase ( plane ) ;
} else {
plane - > _created = 0 ;
plane - > _moved = 0 ;
plane - > _deleted = getScreenCount ( ) ;
}
}
2016-03-10 15:48:48 -06:00
void GfxFrameout : : kernelMovePlaneItems ( const reg_t object , const int16 deltaX , const int16 deltaY , const bool scrollPics ) {
Plane * plane = _planes . findByObject ( object ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kMovePlaneItems: Plane %04x:%04x not found " , PRINT_REG ( object ) ) ;
2016-03-10 15:48:48 -06:00
}
plane - > scrollScreenItems ( deltaX , deltaY , scrollPics ) ;
for ( ScreenItemList : : iterator it = plane - > _screenItemList . begin ( ) ; it ! = plane - > _screenItemList . end ( ) ; + + it ) {
ScreenItem & screenItem = * * it ;
// If object is a number, the screen item from the
// engine, not a script, and should be ignored
if ( screenItem . _object . isNumber ( ) ) {
continue ;
}
if ( deltaX ! = 0 ) {
writeSelectorValue ( _segMan , screenItem . _object , SELECTOR ( x ) , readSelectorValue ( _segMan , screenItem . _object , SELECTOR ( x ) ) + deltaX ) ;
}
if ( deltaY ! = 0 ) {
writeSelectorValue ( _segMan , screenItem . _object , SELECTOR ( y ) , readSelectorValue ( _segMan , screenItem . _object , SELECTOR ( y ) ) + deltaY ) ;
}
}
}
2016-01-18 00:12:47 -06:00
int16 GfxFrameout : : kernelGetHighPlanePri ( ) {
return _planes . getTopSciPlanePriority ( ) ;
}
2012-06-22 09:31:51 +03:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : addPlane ( Plane & plane ) {
if ( _planes . findByObject ( plane . _object ) = = nullptr ) {
plane . clipScreenRect ( _screenRect ) ;
_planes . add ( & plane ) ;
} else {
plane . _deleted = 0 ;
if ( plane . _created = = 0 ) {
plane . _moved = g_sci - > _gfxFrameout - > getScreenCount ( ) ;
2010-02-02 16:25:35 +00:00
}
2016-01-18 00:12:47 -06:00
_planes . sort ( ) ;
2010-02-02 16:25:35 +00:00
}
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : updatePlane ( Plane & plane ) {
// NOTE: This assertion comes from SCI engine code.
assert ( _planes . findByObject ( plane . _object ) = = & plane ) ;
2012-06-09 12:12:44 +03:00
2016-01-18 00:12:47 -06:00
Plane * visiblePlane = _visiblePlanes . findByObject ( plane . _object ) ;
plane . sync ( visiblePlane , _screenRect ) ;
// NOTE: updateScreenRect was originally called a second time here,
// but it is already called at the end of the Plane::Update call
// in the original engine anyway.
_planes . sort ( ) ;
2010-07-26 14:41:19 +00:00
}
2016-01-18 00:12:47 -06:00
# pragma mark -
# pragma mark Pics
2012-01-15 18:35:33 +02:00
2016-07-25 13:40:51 -05:00
void GfxFrameout : : kernelAddPicAt ( const reg_t planeObject , const GuiResourceId pictureId , const int16 x , const int16 y , const bool mirrorX , const bool deleteDuplicate ) {
2016-01-18 00:12:47 -06:00
Plane * plane = _planes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kAddPicAt: Plane %04x:%04x not found " , PRINT_REG ( planeObject ) ) ;
2010-07-26 14:41:19 +00:00
}
2016-07-25 13:40:51 -05:00
plane - > addPic ( pictureId , Common : : Point ( x , y ) , mirrorX , deleteDuplicate ) ;
2010-07-26 14:41:19 +00:00
}
2016-01-18 00:12:47 -06:00
# pragma mark -
# pragma mark Rendering
2016-06-30 13:24:46 -05:00
void GfxFrameout : : frameOut ( const bool shouldShowBits , const Common : : Rect & eraseRect ) {
2016-07-03 17:57:58 -05:00
RobotDecoder & robotPlayer = g_sci - > _video32 - > getRobotPlayer ( ) ;
const bool robotIsActive = robotPlayer . getStatus ( ) ! = RobotDecoder : : kRobotStatusUninitialized ;
if ( robotIsActive ) {
robotPlayer . doRobot ( ) ;
}
2016-01-18 00:12:47 -06:00
// NOTE: The original engine allocated these as static arrays of 100
// pointers to ScreenItemList / RectList
ScreenItemListList screenItemLists ;
EraseListList eraseLists ;
screenItemLists . resize ( _planes . size ( ) ) ;
eraseLists . resize ( _planes . size ( ) ) ;
2016-03-11 07:54:45 +02:00
if ( g_sci - > _gfxRemap32 - > getRemapCount ( ) > 0 & & _remapOccurred ) {
2016-03-15 21:05:01 +02:00
remapMarkRedraw ( ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:24:46 -05:00
calcLists ( screenItemLists , eraseLists , eraseRect ) ;
2016-01-18 00:12:47 -06:00
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
list - > sort ( ) ;
}
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
for ( DrawList : : iterator drawItem = list - > begin ( ) ; drawItem ! = list - > end ( ) ; + + drawItem ) {
( * drawItem ) - > screenItem - > getCelObj ( ) . submitPalette ( ) ;
2012-06-09 15:36:36 +03:00
}
}
2016-01-18 00:12:47 -06:00
_remapOccurred = _palette - > updateForFrame ( ) ;
// NOTE: SCI engine set this to false on each loop through the
// planelist iterator below. Since that is a waste, we only set
// it once.
_frameNowVisible = false ;
for ( PlaneList : : size_type i = 0 ; i < _planes . size ( ) ; + + i ) {
drawEraseList ( eraseLists [ i ] , * _planes [ i ] ) ;
drawScreenItemList ( screenItemLists [ i ] ) ;
}
2016-07-03 17:57:58 -05:00
if ( robotIsActive ) {
robotPlayer . frameAlmostVisible ( ) ;
}
2016-01-18 00:12:47 -06:00
2016-07-12 14:14:01 -05:00
_palette - > updateHardware ( ! shouldShowBits ) ;
2016-01-18 00:12:47 -06:00
if ( shouldShowBits ) {
showBits ( ) ;
}
_frameNowVisible = true ;
2016-07-03 17:57:58 -05:00
if ( robotIsActive ) {
robotPlayer . frameNowVisible ( ) ;
}
2012-06-09 15:36:36 +03:00
}
2016-07-25 11:06:27 -05:00
void GfxFrameout : : palMorphFrameOut ( const int8 * styleRanges , PlaneShowStyle * showStyle ) {
Palette sourcePalette ( _palette - > getNextPalette ( ) ) ;
alterVmap ( sourcePalette , sourcePalette , - 1 , styleRanges ) ;
2016-09-26 19:28:51 -05:00
int16 prevRoom = g_sci - > getEngineState ( ) - > variables [ VAR_GLOBAL ] [ kGlobalVarPreviousRoomNo ] . toSint16 ( ) ;
2016-07-25 11:06:27 -05:00
2016-07-28 14:49:13 -05:00
Common : : Rect rect ( _currentBuffer . screenWidth , _currentBuffer . screenHeight ) ;
2016-07-25 11:06:27 -05:00
_showList . add ( rect ) ;
showBits ( ) ;
// NOTE: The original engine allocated these as static arrays of 100
// pointers to ScreenItemList / RectList
ScreenItemListList screenItemLists ;
EraseListList eraseLists ;
screenItemLists . resize ( _planes . size ( ) ) ;
eraseLists . resize ( _planes . size ( ) ) ;
if ( g_sci - > _gfxRemap32 - > getRemapCount ( ) > 0 & & _remapOccurred ) {
remapMarkRedraw ( ) ;
}
calcLists ( screenItemLists , eraseLists ) ;
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
list - > sort ( ) ;
}
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
for ( DrawList : : iterator drawItem = list - > begin ( ) ; drawItem ! = list - > end ( ) ; + + drawItem ) {
( * drawItem ) - > screenItem - > getCelObj ( ) . submitPalette ( ) ;
}
}
_remapOccurred = _palette - > updateForFrame ( ) ;
_frameNowVisible = false ;
for ( PlaneList : : size_type i = 0 ; i < _planes . size ( ) ; + + i ) {
drawEraseList ( eraseLists [ i ] , * _planes [ i ] ) ;
drawScreenItemList ( screenItemLists [ i ] ) ;
}
Palette nextPalette ( _palette - > getNextPalette ( ) ) ;
if ( prevRoom < 1000 ) {
for ( int i = 0 ; i < ARRAYSIZE ( sourcePalette . colors ) ; + + i ) {
if ( styleRanges [ i ] = = - 1 | | styleRanges [ i ] = = 0 ) {
sourcePalette . colors [ i ] = nextPalette . colors [ i ] ;
sourcePalette . colors [ i ] . used = true ;
}
}
} else {
for ( int i = 0 ; i < ARRAYSIZE ( sourcePalette . colors ) ; + + i ) {
if ( styleRanges [ i ] = = - 1 | | validZeroStyle ( styleRanges [ i ] , i ) ) {
sourcePalette . colors [ i ] = nextPalette . colors [ i ] ;
sourcePalette . colors [ i ] . used = true ;
}
}
}
_palette - > submit ( sourcePalette ) ;
_palette - > updateFFrame ( ) ;
_palette - > updateHardware ( ) ;
alterVmap ( nextPalette , sourcePalette , 1 , _transitions - > _styleRanges ) ;
if ( showStyle & & showStyle - > type ! = kShowStyleMorph ) {
_transitions - > processEffects ( * showStyle ) ;
} else {
showBits ( ) ;
}
_frameNowVisible = true ;
for ( PlaneList : : iterator plane = _planes . begin ( ) ; plane ! = _planes . end ( ) ; + + plane ) {
( * plane ) - > _redrawAllCount = getScreenCount ( ) ;
}
if ( g_sci - > _gfxRemap32 - > getRemapCount ( ) > 0 & & _remapOccurred ) {
remapMarkRedraw ( ) ;
}
calcLists ( screenItemLists , eraseLists ) ;
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
list - > sort ( ) ;
}
for ( ScreenItemListList : : iterator list = screenItemLists . begin ( ) ; list ! = screenItemLists . end ( ) ; + + list ) {
for ( DrawList : : iterator drawItem = list - > begin ( ) ; drawItem ! = list - > end ( ) ; + + drawItem ) {
( * drawItem ) - > screenItem - > getCelObj ( ) . submitPalette ( ) ;
}
}
_remapOccurred = _palette - > updateForFrame ( ) ;
// NOTE: During this second loop, `_frameNowVisible = false` is
// inside the next loop in SCI2.1mid
_frameNowVisible = false ;
for ( PlaneList : : size_type i = 0 ; i < _planes . size ( ) ; + + i ) {
drawEraseList ( eraseLists [ i ] , * _planes [ i ] ) ;
drawScreenItemList ( screenItemLists [ i ] ) ;
}
_palette - > submit ( nextPalette ) ;
_palette - > updateFFrame ( ) ;
_palette - > updateHardware ( false ) ;
showBits ( ) ;
_frameNowVisible = true ;
}
2016-06-30 13:50:10 -05:00
/**
* Determines the parts of ` r ` that aren ' t overlapped by ` other ` .
* Returns - 1 if ` r ` and ` other ` have no intersection .
* Returns number of returned parts ( in ` outRects ` ) otherwise .
* ( In particular , this returns 0 if ` r ` is contained in ` other ` . )
*/
2016-01-18 00:12:47 -06:00
int splitRects ( Common : : Rect r , const Common : : Rect & other , Common : : Rect ( & outRects ) [ 4 ] ) {
if ( ! r . intersects ( other ) ) {
return - 1 ;
}
2016-06-30 13:50:10 -05:00
int splitCount = 0 ;
2016-01-18 00:12:47 -06:00
if ( r . top < other . top ) {
2016-06-30 13:50:10 -05:00
Common : : Rect & t = outRects [ splitCount + + ] ;
2016-01-18 00:12:47 -06:00
t = r ;
t . bottom = other . top ;
r . top = other . top ;
}
if ( r . bottom > other . bottom ) {
2016-06-30 13:50:10 -05:00
Common : : Rect & t = outRects [ splitCount + + ] ;
2016-01-18 00:12:47 -06:00
t = r ;
t . top = other . bottom ;
r . bottom = other . bottom ;
}
if ( r . left < other . left ) {
2016-06-30 13:50:10 -05:00
Common : : Rect & t = outRects [ splitCount + + ] ;
2016-01-18 00:12:47 -06:00
t = r ;
t . right = other . left ;
r . left = other . left ;
}
if ( r . right > other . right ) {
2016-06-30 13:50:10 -05:00
Common : : Rect & t = outRects [ splitCount + + ] ;
2016-01-18 00:12:47 -06:00
t = r ;
t . left = other . right ;
}
2016-06-30 13:50:10 -05:00
return splitCount ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
/**
* Determines the parts of ` middleRect ` that aren ' t overlapped
* by ` showRect ` , optimised for contiguous memory writes .
* Returns - 1 if ` middleRect ` and ` showRect ` have no intersection .
* Returns number of returned parts ( in ` outRects ` ) otherwise .
* ( In particular , this returns 0 if ` middleRect ` is contained
* in ` other ` . )
*
* ` middleRect ` is modified directly to extend into the upper
* and lower rects .
*/
int splitRectsForRender ( Common : : Rect & middleRect , const Common : : Rect & showRect , Common : : Rect ( & outRects ) [ 2 ] ) {
if ( ! middleRect . intersects ( showRect ) ) {
return - 1 ;
}
const int16 minLeft = MIN ( middleRect . left , showRect . left ) ;
const int16 maxRight = MAX ( middleRect . right , showRect . right ) ;
int16 upperLeft , upperTop , upperRight , upperMaxTop ;
if ( middleRect . top < showRect . top ) {
upperLeft = middleRect . left ;
upperTop = middleRect . top ;
upperRight = middleRect . right ;
upperMaxTop = showRect . top ;
}
else {
upperLeft = showRect . left ;
upperTop = showRect . top ;
upperRight = showRect . right ;
upperMaxTop = middleRect . top ;
}
int16 lowerLeft , lowerRight , lowerBottom , lowerMinBottom ;
if ( middleRect . bottom > showRect . bottom ) {
lowerLeft = middleRect . left ;
lowerRight = middleRect . right ;
lowerBottom = middleRect . bottom ;
lowerMinBottom = showRect . bottom ;
} else {
lowerLeft = showRect . left ;
lowerRight = showRect . right ;
lowerBottom = showRect . bottom ;
lowerMinBottom = middleRect . bottom ;
}
int splitCount = 0 ;
middleRect . left = minLeft ;
middleRect . top = upperMaxTop ;
middleRect . right = maxRight ;
middleRect . bottom = lowerMinBottom ;
if ( upperTop ! = upperMaxTop ) {
Common : : Rect & upperRect = outRects [ 0 ] ;
upperRect . left = upperLeft ;
upperRect . top = upperTop ;
upperRect . right = upperRight ;
upperRect . bottom = upperMaxTop ;
// Merge upper rect into middle rect if possible
if ( upperRect . left = = middleRect . left & & upperRect . right = = middleRect . right ) {
middleRect . top = upperRect . top ;
} else {
+ + splitCount ;
}
}
if ( lowerBottom ! = lowerMinBottom ) {
Common : : Rect & lowerRect = outRects [ splitCount ] ;
lowerRect . left = lowerLeft ;
lowerRect . top = lowerMinBottom ;
lowerRect . right = lowerRight ;
lowerRect . bottom = lowerBottom ;
// Merge lower rect into middle rect if possible
if ( lowerRect . left = = middleRect . left & & lowerRect . right = = middleRect . right ) {
middleRect . bottom = lowerRect . bottom ;
} else {
+ + splitCount ;
}
}
assert ( splitCount < = 2 ) ;
return splitCount ;
}
2016-01-18 00:12:47 -06:00
2016-06-30 13:24:46 -05:00
// NOTE: The third rectangle parameter is only ever given a non-empty rect
// by VMD code, via `frameOut`
void GfxFrameout : : calcLists ( ScreenItemListList & drawLists , EraseListList & eraseLists , const Common : : Rect & eraseRect ) {
2016-06-30 13:50:10 -05:00
RectList eraseList ;
Common : : Rect outRects [ 4 ] ;
2016-01-18 00:12:47 -06:00
int deletedPlaneCount = 0 ;
2016-06-30 13:50:10 -05:00
bool addedToEraseList = false ;
2016-01-18 00:12:47 -06:00
bool foundTransparentPlane = false ;
2016-06-30 13:24:46 -05:00
if ( ! eraseRect . isEmpty ( ) ) {
addedToEraseList = true ;
2016-06-30 13:50:10 -05:00
eraseList . add ( eraseRect ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
PlaneList : : size_type planeCount = _planes . size ( ) ;
2016-07-01 15:54:52 -05:00
for ( PlaneList : : size_type outerPlaneIndex = 0 ; outerPlaneIndex < planeCount ; + + outerPlaneIndex ) {
2016-06-30 13:50:10 -05:00
const Plane * outerPlane = _planes [ outerPlaneIndex ] ;
const Plane * visiblePlane = _visiblePlanes . findByObject ( outerPlane - > _object ) ;
2016-01-18 00:12:47 -06:00
2016-06-27 20:58:22 -05:00
// NOTE: SSCI only ever checks for kPlaneTypeTransparent here, even
// though kPlaneTypeTransparentPicture is also a transparent plane
2016-01-18 00:12:47 -06:00
if ( outerPlane - > _type = = kPlaneTypeTransparent ) {
foundTransparentPlane = true ;
}
2012-07-05 13:42:00 +03:00
2016-01-18 00:12:47 -06:00
if ( outerPlane - > _deleted ) {
2016-06-30 13:50:10 -05:00
if ( visiblePlane ! = nullptr & & ! visiblePlane - > _screenRect . isEmpty ( ) ) {
eraseList . add ( visiblePlane - > _screenRect ) ;
addedToEraseList = true ;
2016-01-18 00:12:47 -06:00
}
+ + deletedPlaneCount ;
2016-06-30 13:50:10 -05:00
} else if ( visiblePlane ! = nullptr & & outerPlane - > _moved ) {
// _moved will be decremented in the final loop through the planes,
// at the end of this function
{
const int splitCount = splitRects ( visiblePlane - > _screenRect , outerPlane - > _screenRect , outRects ) ;
if ( splitCount ) {
if ( splitCount = = - 1 & & ! visiblePlane - > _screenRect . isEmpty ( ) ) {
eraseList . add ( visiblePlane - > _screenRect ) ;
2016-01-18 00:12:47 -06:00
} else {
2016-06-30 13:50:10 -05:00
for ( int i = 0 ; i < splitCount ; + + i ) {
eraseList . add ( outRects [ i ] ) ;
2016-01-18 00:12:47 -06:00
}
}
2016-06-30 13:50:10 -05:00
addedToEraseList = true ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
}
2016-01-18 00:12:47 -06:00
2016-06-30 13:50:10 -05:00
if ( ! outerPlane - > _redrawAllCount ) {
const int splitCount = splitRects ( outerPlane - > _screenRect , visiblePlane - > _screenRect , outRects ) ;
if ( splitCount ) {
for ( int i = 0 ; i < splitCount ; + + i ) {
eraseList . add ( outRects [ i ] ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
addedToEraseList = true ;
2012-06-09 15:36:36 +03:00
}
}
}
2016-06-30 13:50:10 -05:00
if ( addedToEraseList ) {
2016-07-01 15:54:52 -05:00
for ( RectList : : size_type rectIndex = 0 ; rectIndex < eraseList . size ( ) ; + + rectIndex ) {
2016-06-30 13:50:10 -05:00
const Common : : Rect & rect = * eraseList [ rectIndex ] ;
for ( int innerPlaneIndex = planeCount - 1 ; innerPlaneIndex > = 0 ; - - innerPlaneIndex ) {
const Plane & innerPlane = * _planes [ innerPlaneIndex ] ;
if (
! innerPlane . _deleted & &
innerPlane . _type ! = kPlaneTypeTransparent & &
innerPlane . _screenRect . intersects ( rect )
) {
if ( ! innerPlane . _redrawAllCount ) {
eraseLists [ innerPlaneIndex ] . add ( innerPlane . _screenRect . findIntersectingRect ( rect ) ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
const int splitCount = splitRects ( rect , innerPlane . _screenRect , outRects ) ;
2016-01-18 00:12:47 -06:00
for ( int i = 0 ; i < splitCount ; + + i ) {
2016-06-30 13:50:10 -05:00
eraseList . add ( outRects [ i ] ) ;
2016-01-18 00:12:47 -06:00
}
2012-07-05 13:42:00 +03:00
2016-06-30 13:50:10 -05:00
eraseList . erase_at ( rectIndex ) ;
2016-01-18 00:12:47 -06:00
break ;
}
2012-06-09 15:36:36 +03:00
}
}
2016-01-18 00:12:47 -06:00
2016-06-30 13:50:10 -05:00
eraseList . pack ( ) ;
2012-06-09 15:36:36 +03:00
}
}
2016-01-18 00:12:47 -06:00
// clean up deleted planes
if ( deletedPlaneCount ) {
for ( int planeIndex = planeCount - 1 ; planeIndex > = 0 ; - - planeIndex ) {
Plane * plane = _planes [ planeIndex ] ;
if ( plane - > _deleted ) {
- - plane - > _deleted ;
if ( plane - > _deleted < = 0 ) {
2016-06-30 13:50:10 -05:00
const int visiblePlaneIndex = _visiblePlanes . findIndexByObject ( plane - > _object ) ;
if ( visiblePlaneIndex ! = - 1 ) {
_visiblePlanes . remove_at ( visiblePlaneIndex ) ;
2016-01-18 00:12:47 -06:00
}
2013-01-11 00:45:10 +02:00
2016-01-18 00:12:47 -06:00
_planes . remove_at ( planeIndex ) ;
eraseLists . remove_at ( planeIndex ) ;
drawLists . remove_at ( planeIndex ) ;
}
2013-01-11 00:45:10 +02:00
2016-01-18 00:12:47 -06:00
if ( - - deletedPlaneCount < = 0 ) {
break ;
}
}
}
}
2013-01-11 00:45:10 +02:00
2016-06-30 13:50:10 -05:00
// Some planes may have been deleted, so re-retrieve count
2016-01-18 00:12:47 -06:00
planeCount = _planes . size ( ) ;
2016-06-30 13:50:10 -05:00
for ( PlaneList : : size_type outerIndex = 0 ; outerIndex < planeCount ; + + outerIndex ) {
2016-01-18 00:12:47 -06:00
// "outer" just refers to the outer loop
2016-06-30 13:50:10 -05:00
Plane & outerPlane = * _planes [ outerIndex ] ;
if ( outerPlane . _priorityChanged ) {
- - outerPlane . _priorityChanged ;
2016-01-18 00:12:47 -06:00
2016-06-30 13:50:10 -05:00
const Plane * visibleOuterPlane = _visiblePlanes . findByObject ( outerPlane . _object ) ;
2016-05-30 08:33:38 -05:00
if ( visibleOuterPlane = = nullptr ) {
2016-06-30 13:50:10 -05:00
warning ( " calcLists could not find visible plane for %04x:%04x " , PRINT_REG ( outerPlane . _object ) ) ;
2016-05-30 08:33:38 -05:00
continue ;
}
2016-01-18 00:12:47 -06:00
2016-06-30 13:50:10 -05:00
eraseList . add ( outerPlane . _screenRect . findIntersectingRect ( visibleOuterPlane - > _screenRect ) ) ;
2016-01-18 00:12:47 -06:00
2016-07-01 15:54:52 -05:00
for ( int innerIndex = ( int ) planeCount - 1 ; innerIndex > = 0 ; - - innerIndex ) {
2016-01-18 00:12:47 -06:00
// "inner" just refers to the inner loop
2016-06-30 13:50:10 -05:00
const Plane & innerPlane = * _planes [ innerIndex ] ;
const Plane * visibleInnerPlane = _visiblePlanes . findByObject ( innerPlane . _object ) ;
2016-01-18 00:12:47 -06:00
2016-06-30 13:50:10 -05:00
const RectList : : size_type rectCount = eraseList . size ( ) ;
for ( RectList : : size_type rectIndex = 0 ; rectIndex < rectCount ; + + rectIndex ) {
const int splitCount = splitRects ( * eraseList [ rectIndex ] , innerPlane . _screenRect , outRects ) ;
2016-01-18 00:12:47 -06:00
if ( splitCount = = 0 ) {
2016-05-30 08:33:38 -05:00
if ( visibleInnerPlane ! = nullptr ) {
2016-01-18 00:12:47 -06:00
// same priority, or relative priority between inner/outer changed
2016-06-30 13:50:10 -05:00
if ( ( visibleOuterPlane - > _priority - visibleInnerPlane - > _priority ) * ( outerPlane . _priority - innerPlane . _priority ) < = 0 ) {
if ( outerPlane . _priority < = innerPlane . _priority ) {
eraseLists [ innerIndex ] . add ( * eraseList [ rectIndex ] ) ;
2016-01-18 00:12:47 -06:00
} else {
2016-06-30 13:50:10 -05:00
eraseLists [ outerIndex ] . add ( * eraseList [ rectIndex ] ) ;
2016-01-18 00:12:47 -06:00
}
}
}
2016-06-30 13:50:10 -05:00
eraseList . erase_at ( rectIndex ) ;
2016-01-18 00:12:47 -06:00
} else if ( splitCount ! = - 1 ) {
for ( int i = 0 ; i < splitCount ; + + i ) {
2016-06-30 13:50:10 -05:00
eraseList . add ( outRects [ i ] ) ;
2016-01-18 00:12:47 -06:00
}
2016-05-30 08:33:38 -05:00
if ( visibleInnerPlane ! = nullptr ) {
2016-01-18 00:12:47 -06:00
// same priority, or relative priority between inner/outer changed
2016-06-30 13:50:10 -05:00
if ( ( visibleOuterPlane - > _priority - visibleInnerPlane - > _priority ) * ( outerPlane . _priority - innerPlane . _priority ) < = 0 ) {
* eraseList [ rectIndex ] = outerPlane . _screenRect . findIntersectingRect ( innerPlane . _screenRect ) ;
if ( outerPlane . _priority < = innerPlane . _priority ) {
eraseLists [ innerIndex ] . add ( * eraseList [ rectIndex ] ) ;
} else {
eraseLists [ outerIndex ] . add ( * eraseList [ rectIndex ] ) ;
2016-01-18 00:12:47 -06:00
}
}
}
2016-06-30 13:50:10 -05:00
eraseList . erase_at ( rectIndex ) ;
2016-01-18 00:12:47 -06:00
}
}
2016-06-30 13:50:10 -05:00
eraseList . pack ( ) ;
2016-01-18 00:12:47 -06:00
}
}
}
2013-01-11 00:45:10 +02:00
2016-06-30 13:50:10 -05:00
for ( PlaneList : : size_type planeIndex = 0 ; planeIndex < planeCount ; + + planeIndex ) {
Plane & plane = * _planes [ planeIndex ] ;
Plane * visiblePlane = _visiblePlanes . findByObject ( plane . _object ) ;
2013-01-11 00:45:10 +02:00
2016-06-30 13:50:10 -05:00
if ( ! plane . _screenRect . isEmpty ( ) ) {
if ( plane . _redrawAllCount ) {
plane . redrawAll ( visiblePlane , _planes , drawLists [ planeIndex ] , eraseLists [ planeIndex ] ) ;
} else {
if ( visiblePlane = = nullptr ) {
error ( " Missing visible plane for source plane %04x:%04x " , PRINT_REG ( plane . _object ) ) ;
}
2013-01-11 00:45:10 +02:00
2016-06-30 13:50:10 -05:00
plane . calcLists ( * visiblePlane , _planes , drawLists [ planeIndex ] , eraseLists [ planeIndex ] ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
} else {
plane . decrementScreenItemArrayCounts ( visiblePlane , false ) ;
}
2013-01-11 00:45:10 +02:00
2016-06-30 13:50:10 -05:00
if ( plane . _moved ) {
// the work for handling moved/resized planes was already done
// earlier in the function, we are just cleaning up now
- - plane . _moved ;
2016-01-18 00:12:47 -06:00
}
2016-06-30 13:50:10 -05:00
if ( plane . _created ) {
_visiblePlanes . add ( new Plane ( plane ) ) ;
- - plane . _created ;
} else if ( plane . _updated ) {
2016-10-10 09:27:49 -05:00
if ( visiblePlane = = nullptr ) {
error ( " [GfxFrameout::calcLists]: Attempt to update nonexistent visible plane " ) ;
}
2016-06-30 13:50:10 -05:00
* visiblePlane = plane ;
- - plane . _updated ;
2016-01-18 00:12:47 -06:00
}
2012-07-04 02:17:27 +03:00
}
2010-10-23 19:23:07 +00:00
2016-06-27 20:58:22 -05:00
// NOTE: SSCI only looks for kPlaneTypeTransparent, not
// kPlaneTypeTransparentPicture
2016-01-18 00:12:47 -06:00
if ( foundTransparentPlane ) {
2016-06-30 13:50:10 -05:00
for ( PlaneList : : size_type planeIndex = 0 ; planeIndex < planeCount ; + + planeIndex ) {
for ( PlaneList : : size_type i = planeIndex + 1 ; i < planeCount ; + + i ) {
2016-01-18 00:12:47 -06:00
if ( _planes [ i ] - > _type = = kPlaneTypeTransparent ) {
_planes [ i ] - > filterUpEraseRects ( drawLists [ i ] , eraseLists [ planeIndex ] ) ;
}
}
if ( _planes [ planeIndex ] - > _type = = kPlaneTypeTransparent ) {
2016-07-01 15:54:52 -05:00
for ( int i = ( int ) planeIndex - 1 ; i > = 0 ; - - i ) {
2016-01-18 00:12:47 -06:00
_planes [ i ] - > filterDownEraseRects ( drawLists [ i ] , eraseLists [ i ] , eraseLists [ planeIndex ] ) ;
}
if ( eraseLists [ planeIndex ] . size ( ) > 0 ) {
error ( " Transparent plane's erase list not absorbed " ) ;
}
}
2010-10-23 19:23:07 +00:00
2016-06-30 13:50:10 -05:00
for ( PlaneList : : size_type i = planeIndex + 1 ; i < planeCount ; + + i ) {
2016-01-18 00:12:47 -06:00
if ( _planes [ i ] - > _type = = kPlaneTypeTransparent ) {
_planes [ i ] - > filterUpDrawRects ( drawLists [ i ] , drawLists [ planeIndex ] ) ;
}
}
}
}
2010-02-02 16:25:35 +00:00
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : drawEraseList ( const RectList & eraseList , const Plane & plane ) {
if ( plane . _type ! = kPlaneTypeColored ) {
2010-10-23 19:23:07 +00:00
return ;
2012-07-04 02:17:27 +03:00
}
2010-10-23 19:23:07 +00:00
2016-06-30 13:50:10 -05:00
const RectList : : size_type eraseListSize = eraseList . size ( ) ;
for ( RectList : : size_type i = 0 ; i < eraseListSize ; + + i ) {
mergeToShowList ( * eraseList [ i ] , _showList , _overdrawThreshold ) ;
_currentBuffer . fillRect ( * eraseList [ i ] , plane . _back ) ;
2016-01-18 00:12:47 -06:00
}
}
void GfxFrameout : : drawScreenItemList ( const DrawList & screenItemList ) {
2016-06-30 13:50:10 -05:00
const DrawList : : size_type drawListSize = screenItemList . size ( ) ;
for ( DrawList : : size_type i = 0 ; i < drawListSize ; + + i ) {
const DrawItem & drawItem = * screenItemList [ i ] ;
2016-01-18 00:12:47 -06:00
mergeToShowList ( drawItem . rect , _showList , _overdrawThreshold ) ;
2016-06-30 13:50:10 -05:00
const ScreenItem & screenItem = * drawItem . screenItem ;
2016-01-18 00:12:47 -06:00
// TODO: Remove
2016-03-05 23:56:38 -06:00
// debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), PRINT_RECT(drawItem.rect));
2016-01-18 00:12:47 -06:00
CelObj & celObj = * screenItem . _celObj ;
celObj . draw ( _currentBuffer , screenItem , drawItem . rect , screenItem . _mirrorX ^ celObj . _mirrorX ) ;
}
}
2011-10-12 02:43:08 +03:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : mergeToShowList ( const Common : : Rect & drawRect , RectList & showList , const int overdrawThreshold ) {
2016-06-30 13:50:10 -05:00
RectList mergeList ;
Common : : Rect merged ;
mergeList . add ( drawRect ) ;
for ( RectList : : size_type i = 0 ; i < mergeList . size ( ) ; + + i ) {
bool didMerge = false ;
const Common : : Rect & r1 = * mergeList [ i ] ;
if ( ! r1 . isEmpty ( ) ) {
for ( RectList : : size_type j = 0 ; j < showList . size ( ) ; + + j ) {
const Common : : Rect & r2 = * showList [ j ] ;
if ( ! r2 . isEmpty ( ) ) {
merged = r1 ;
merged . extend ( r2 ) ;
int difference = merged . width ( ) * merged . height ( ) ;
difference - = r1 . width ( ) * r1 . height ( ) ;
difference - = r2 . width ( ) * r2 . height ( ) ;
if ( r1 . intersects ( r2 ) ) {
const Common : : Rect overlap = r1 . findIntersectingRect ( r2 ) ;
difference + = overlap . width ( ) * overlap . height ( ) ;
}
if ( difference < = overdrawThreshold ) {
mergeList . erase_at ( i ) ;
showList . erase_at ( j ) ;
mergeList . add ( merged ) ;
didMerge = true ;
break ;
} else {
Common : : Rect outRects [ 2 ] ;
int splitCount = splitRectsForRender ( * mergeList [ i ] , * showList [ j ] , outRects ) ;
if ( splitCount ! = - 1 ) {
mergeList . add ( * mergeList [ i ] ) ;
mergeList . erase_at ( i ) ;
showList . erase_at ( j ) ;
didMerge = true ;
while ( splitCount - - ) {
mergeList . add ( outRects [ splitCount ] ) ;
}
break ;
}
}
}
2016-01-18 00:12:47 -06:00
}
2013-01-13 17:28:09 +02:00
2016-06-30 13:50:10 -05:00
if ( didMerge ) {
showList . pack ( ) ;
}
}
2013-01-11 00:45:10 +02:00
}
2012-05-14 02:30:15 +03:00
2016-06-30 13:50:10 -05:00
mergeList . pack ( ) ;
for ( RectList : : size_type i = 0 ; i < mergeList . size ( ) ; + + i ) {
showList . add ( * mergeList [ i ] ) ;
}
2010-09-19 14:50:28 +00:00
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : showBits ( ) {
2016-07-31 13:41:05 -05:00
if ( ! _showList . size ( ) ) {
2016-08-26 19:50:13 -05:00
g_system - > updateScreen ( ) ;
2016-07-31 13:41:05 -05:00
return ;
}
2016-01-18 00:12:47 -06:00
for ( RectList : : const_iterator rect = _showList . begin ( ) ; rect ! = _showList . end ( ) ; + + rect ) {
Common : : Rect rounded ( * * rect ) ;
// NOTE: SCI engine used BR-inclusive rects so used slightly
// different masking here to ensure that the width of rects
// was always even.
rounded . left & = ~ 1 ;
rounded . right = ( rounded . right + 1 ) & ~ 1 ;
2016-07-31 13:41:05 -05:00
_cursor - > gonnaPaint ( rounded ) ;
2010-06-20 17:17:46 +00:00
}
2016-07-31 13:41:05 -05:00
_cursor - > paintStarting ( ) ;
2016-01-18 00:12:47 -06:00
for ( RectList : : const_iterator rect = _showList . begin ( ) ; rect ! = _showList . end ( ) ; + + rect ) {
Common : : Rect rounded ( * * rect ) ;
// NOTE: SCI engine used BR-inclusive rects so used slightly
// different masking here to ensure that the width of rects
// was always even.
rounded . left & = ~ 1 ;
rounded . right = ( rounded . right + 1 ) & ~ 1 ;
byte * sourceBuffer = ( byte * ) _currentBuffer . getPixels ( ) + rounded . top * _currentBuffer . screenWidth + rounded . left ;
2016-07-26 19:56:12 -05:00
// TODO: Sometimes transition screen items generate zero-dimension
// show rectangles. Is this a bug?
if ( rounded . width ( ) = = 0 | | rounded . height ( ) = = 0 ) {
warning ( " Zero-dimension show rectangle ignored " ) ;
continue ;
}
2016-01-18 00:12:47 -06:00
g_system - > copyRectToScreen ( sourceBuffer , _currentBuffer . screenWidth , rounded . left , rounded . top , rounded . width ( ) , rounded . height ( ) ) ;
}
2016-07-31 13:41:05 -05:00
_cursor - > donePainting ( ) ;
2016-01-18 00:12:47 -06:00
_showList . clear ( ) ;
2016-08-26 19:50:13 -05:00
g_system - > updateScreen ( ) ;
2010-06-20 17:17:46 +00:00
}
2010-06-14 16:58:15 +00:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : alterVmap ( const Palette & palette1 , const Palette & palette2 , const int8 style , const int8 * const styleRanges ) {
uint8 clut [ 256 ] ;
for ( int paletteIndex = 0 ; paletteIndex < ARRAYSIZE ( palette1 . colors ) ; + + paletteIndex ) {
int outerR = palette1 . colors [ paletteIndex ] . r ;
int outerG = palette1 . colors [ paletteIndex ] . g ;
int outerB = palette1 . colors [ paletteIndex ] . b ;
if ( styleRanges [ paletteIndex ] = = style ) {
int minDiff = 262140 ;
2016-05-28 11:02:40 -05:00
int minDiffIndex = paletteIndex ;
2016-01-18 00:12:47 -06:00
for ( int i = 0 ; i < 236 ; + + i ) {
if ( styleRanges [ i ] ! = style ) {
int r = palette1 . colors [ i ] . r ;
int g = palette1 . colors [ i ] . g ;
int b = palette1 . colors [ i ] . b ;
int diffSquared = ( outerR - r ) * ( outerR - r ) + ( outerG - g ) * ( outerG - g ) + ( outerB - b ) * ( outerB - b ) ;
if ( diffSquared < minDiff ) {
minDiff = diffSquared ;
minDiffIndex = i ;
}
}
}
2011-11-17 22:08:36 +02:00
2016-01-18 00:12:47 -06:00
clut [ paletteIndex ] = minDiffIndex ;
}
2011-11-17 22:08:36 +02:00
2016-01-18 00:12:47 -06:00
if ( style = = 1 & & styleRanges [ paletteIndex ] = = 0 ) {
int minDiff = 262140 ;
2016-05-28 11:02:40 -05:00
int minDiffIndex = paletteIndex ;
2011-11-17 22:08:36 +02:00
2016-01-18 00:12:47 -06:00
for ( int i = 0 ; i < 236 ; + + i ) {
int r = palette2 . colors [ i ] . r ;
int g = palette2 . colors [ i ] . g ;
int b = palette2 . colors [ i ] . b ;
2011-11-17 22:08:36 +02:00
2016-01-18 00:12:47 -06:00
int diffSquared = ( outerR - r ) * ( outerR - r ) + ( outerG - g ) * ( outerG - g ) + ( outerB - b ) * ( outerB - b ) ;
if ( diffSquared < minDiff ) {
minDiff = diffSquared ;
minDiffIndex = i ;
}
2011-02-07 12:24:09 +00:00
}
2016-01-18 00:12:47 -06:00
clut [ paletteIndex ] = minDiffIndex ;
2011-11-17 22:08:36 +02:00
}
2016-01-18 00:12:47 -06:00
}
2011-02-07 12:24:09 +00:00
2016-01-18 00:12:47 -06:00
byte * pixels = ( byte * ) _currentBuffer . getPixels ( ) ;
for ( int pixelIndex = 0 , numPixels = _currentBuffer . screenWidth * _currentBuffer . screenHeight ; pixelIndex < numPixels ; + + pixelIndex ) {
byte currentValue = pixels [ pixelIndex ] ;
int8 styleRangeValue = styleRanges [ currentValue ] ;
if ( styleRangeValue = = - 1 & & styleRangeValue = = style ) {
currentValue = pixels [ pixelIndex ] = clut [ currentValue ] ;
2016-03-18 09:10:10 -05:00
// NOTE: In original engine this assignment happens outside of the
// condition, but if the branch is not followed the value is just
// going to be the same as it was before
styleRangeValue = styleRanges [ currentValue ] ;
2011-11-17 22:08:36 +02:00
}
2016-01-18 00:12:47 -06:00
if (
( styleRangeValue = = 1 & & styleRangeValue = = style ) | |
( styleRangeValue = = 0 & & style = = 1 )
) {
pixels [ pixelIndex ] = clut [ currentValue ] ;
}
2011-11-17 22:08:36 +02:00
}
}
2016-03-02 14:02:15 -06:00
void GfxFrameout : : kernelFrameOut ( const bool shouldShowBits ) {
2016-07-25 11:06:27 -05:00
if ( _transitions - > hasShowStyles ( ) ) {
_transitions - > processShowStyles ( ) ;
2016-01-18 00:12:47 -06:00
} else if ( _palMorphIsOn ) {
2016-07-25 11:06:27 -05:00
palMorphFrameOut ( _transitions - > _styleRanges , nullptr ) ;
2016-01-18 00:12:47 -06:00
_palMorphIsOn = false ;
} else {
2016-07-25 11:06:27 -05:00
if ( _transitions - > hasScrolls ( ) ) {
_transitions - > processScrolls ( ) ;
}
2012-05-21 01:29:30 +03:00
2016-03-02 14:02:15 -06:00
frameOut ( shouldShowBits ) ;
2016-01-18 00:12:47 -06:00
}
2016-06-14 17:43:57 -05:00
2016-07-02 19:11:59 -05:00
throttle ( ) ;
}
void GfxFrameout : : throttle ( ) {
2016-06-14 17:43:57 -05:00
if ( _throttleFrameOut ) {
2016-07-01 19:47:15 -05:00
uint8 throttleTime ;
if ( _throttleState = = 2 ) {
2016-07-25 11:07:15 -05:00
throttleTime = 16 ;
2016-07-01 19:47:15 -05:00
_throttleState = 0 ;
} else {
2016-07-25 11:07:15 -05:00
throttleTime = 17 ;
2016-07-01 19:47:15 -05:00
+ + _throttleState ;
}
g_sci - > getEngineState ( ) - > speedThrottler ( throttleTime ) ;
2016-06-14 17:43:57 -05:00
g_sci - > getEngineState ( ) - > _throttleTrigger = true ;
}
2016-01-18 00:12:47 -06:00
}
2012-05-21 01:29:30 +03:00
2016-08-02 09:49:04 -05:00
void GfxFrameout : : shakeScreen ( int16 numShakes , const ShakeDirection direction ) {
if ( direction & kShakeHorizontal ) {
// Used by QFG4 room 750
warning ( " TODO: Horizontal shake not implemented " ) ;
return ;
}
while ( numShakes - - ) {
if ( direction & kShakeVertical ) {
g_system - > setShakePos ( _isHiRes ? 8 : 4 ) ;
}
g_system - > updateScreen ( ) ;
g_sci - > getEngineState ( ) - > wait ( 3 ) ;
if ( direction & kShakeVertical ) {
g_system - > setShakePos ( 0 ) ;
}
g_system - > updateScreen ( ) ;
g_sci - > getEngineState ( ) - > wait ( 3 ) ;
}
}
2016-03-08 10:27:15 -06:00
# pragma mark -
# pragma mark Mouse cursor
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
reg_t GfxFrameout : : kernelIsOnMe ( const reg_t object , const Common : : Point & position , bool checkPixel ) const {
2016-03-18 13:08:37 -05:00
const reg_t planeObject = readSelector ( _segMan , object , SELECTOR ( plane ) ) ;
2016-03-08 10:27:15 -06:00
Plane * plane = _visiblePlanes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
return make_reg ( 0 , 0 ) ;
2016-02-20 05:38:22 +01:00
}
2016-03-08 10:27:15 -06:00
ScreenItem * screenItem = plane - > _screenItemList . findByObject ( object ) ;
if ( screenItem = = nullptr ) {
return make_reg ( 0 , 0 ) ;
2016-02-20 05:38:22 +01:00
}
2016-03-18 13:08:37 -05:00
// NOTE: The original engine passed a copy of the ScreenItem into isOnMe
// as a hack around the fact that the screen items in `_visiblePlanes`
// did not have their `_celObj` pointers cleared when their CelInfo was
// updated by `Plane::decrementScreenItemArrayCounts`. We handle this
// this more intelligently by clearing `_celObj` in the copy assignment
// operator, which is only ever called by `decrementScreenItemArrayCounts`
// anyway.
2016-03-08 10:27:15 -06:00
return make_reg ( 0 , isOnMe ( * screenItem , * plane , position , checkPixel ) ) ;
2016-02-20 15:46:12 +01:00
}
2016-03-08 10:27:15 -06:00
bool GfxFrameout : : isOnMe ( const ScreenItem & screenItem , const Plane & plane , const Common : : Point & position , const bool checkPixel ) const {
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
Common : : Point scaledPosition ( position ) ;
mulru ( scaledPosition , Ratio ( _currentBuffer . screenWidth , _currentBuffer . scriptWidth ) , Ratio ( _currentBuffer . screenHeight , _currentBuffer . scriptHeight ) ) ;
scaledPosition . x + = plane . _planeRect . left ;
scaledPosition . y + = plane . _planeRect . top ;
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
if ( ! screenItem . _screenRect . contains ( scaledPosition ) ) {
return false ;
2016-02-20 05:38:22 +01:00
}
2016-03-08 10:27:15 -06:00
if ( checkPixel ) {
CelObj & celObj = screenItem . getCelObj ( ) ;
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
bool mirrorX = screenItem . _mirrorX ^ celObj . _mirrorX ;
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
scaledPosition . x - = screenItem . _scaledPosition . x ;
scaledPosition . y - = screenItem . _scaledPosition . y ;
2016-02-20 05:38:22 +01:00
2016-10-09 10:52:08 -05:00
mulru ( scaledPosition , Ratio ( celObj . _xResolution , _currentBuffer . screenWidth ) , Ratio ( celObj . _yResolution , _currentBuffer . screenHeight ) ) ;
2016-02-20 05:38:22 +01:00
2016-03-08 10:27:15 -06:00
if ( screenItem . _scale . signal ! = kScaleSignalNone & & screenItem . _scale . x & & screenItem . _scale . y ) {
scaledPosition . x = scaledPosition . x * 128 / screenItem . _scale . x ;
scaledPosition . y = scaledPosition . y * 128 / screenItem . _scale . y ;
2016-02-20 05:38:22 +01:00
}
2016-03-08 10:27:15 -06:00
uint8 pixel = celObj . readPixel ( scaledPosition . x , scaledPosition . y , mirrorX ) ;
2016-10-09 10:52:08 -05:00
return pixel ! = celObj . _skipColor ;
2016-02-20 05:38:22 +01:00
}
2016-03-08 10:27:15 -06:00
return true ;
2016-02-20 05:38:22 +01:00
}
2016-07-31 15:19:48 -05:00
bool GfxFrameout : : kernelSetNowSeen ( const reg_t screenItemObject ) const {
2016-03-10 14:05:27 -06:00
const reg_t planeObject = readSelector ( _segMan , screenItemObject , SELECTOR ( plane ) ) ;
Plane * plane = _planes . findByObject ( planeObject ) ;
if ( plane = = nullptr ) {
2016-03-10 17:31:51 -06:00
error ( " kSetNowSeen: Plane %04x:%04x not found for screen item %04x:%04x " , PRINT_REG ( planeObject ) , PRINT_REG ( screenItemObject ) ) ;
2016-03-10 14:05:27 -06:00
}
ScreenItem * screenItem = plane - > _screenItemList . findByObject ( screenItemObject ) ;
if ( screenItem = = nullptr ) {
2016-07-31 15:19:48 -05:00
return false ;
2016-03-10 14:05:27 -06:00
}
Common : : Rect result = screenItem - > getNowSeenRect ( * plane ) ;
writeSelectorValue ( _segMan , screenItemObject , SELECTOR ( nsLeft ) , result . left ) ;
writeSelectorValue ( _segMan , screenItemObject , SELECTOR ( nsTop ) , result . top ) ;
writeSelectorValue ( _segMan , screenItemObject , SELECTOR ( nsRight ) , result . right - 1 ) ;
writeSelectorValue ( _segMan , screenItemObject , SELECTOR ( nsBottom ) , result . bottom - 1 ) ;
2016-07-31 15:19:48 -05:00
return true ;
2016-03-10 14:05:27 -06:00
}
2016-03-15 21:05:01 +02:00
void GfxFrameout : : remapMarkRedraw ( ) {
for ( PlaneList : : const_iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
Plane * p = * it ;
p - > remapMarkRedraw ( ) ;
}
}
2016-01-18 00:12:47 -06:00
# pragma mark -
# pragma mark Debugging
2012-05-21 01:29:30 +03:00
2016-01-18 00:12:47 -06:00
void GfxFrameout : : printPlaneListInternal ( Console * con , const PlaneList & planeList ) const {
for ( PlaneList : : const_iterator it = planeList . begin ( ) ; it ! = planeList . end ( ) ; + + it ) {
Plane * p = * it ;
p - > printDebugInfo ( con ) ;
2012-05-21 01:29:30 +03:00
}
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : printPlaneList ( Console * con ) const {
printPlaneListInternal ( con , _planes ) ;
}
void GfxFrameout : : printVisiblePlaneList ( Console * con ) const {
printPlaneListInternal ( con , _visiblePlanes ) ;
}
2012-09-26 04:17:31 +02:00
2016-03-07 16:41:57 -06:00
void GfxFrameout : : printPlaneItemListInternal ( Console * con , const ScreenItemList & screenItemList ) const {
ScreenItemList : : size_type i = 0 ;
for ( ScreenItemList : : const_iterator sit = screenItemList . begin ( ) ; sit ! = screenItemList . end ( ) ; sit + + ) {
ScreenItem * screenItem = * sit ;
con - > debugPrintf ( " %2d: " , i + + ) ;
screenItem - > printDebugInfo ( con ) ;
}
}
2016-01-18 00:12:47 -06:00
void GfxFrameout : : printPlaneItemList ( Console * con , const reg_t planeObject ) const {
Plane * p = _planes . findByObject ( planeObject ) ;
2012-05-21 01:29:30 +03:00
2016-01-18 00:12:47 -06:00
if ( p = = nullptr ) {
con - > debugPrintf ( " Plane does not exist " ) ;
return ;
}
2016-03-07 16:41:57 -06:00
printPlaneItemListInternal ( con , p - > _screenItemList ) ;
}
void GfxFrameout : : printVisiblePlaneItemList ( Console * con , const reg_t planeObject ) const {
Plane * p = _visiblePlanes . findByObject ( planeObject ) ;
if ( p = = nullptr ) {
con - > debugPrintf ( " Plane does not exist " ) ;
return ;
2012-05-21 01:29:30 +03:00
}
2016-03-07 16:41:57 -06:00
printPlaneItemListInternal ( con , p - > _screenItemList ) ;
2012-05-21 01:29:30 +03:00
}
2011-10-28 22:18:10 +03:00
} // End of namespace Sci