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"
# 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"
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"
2010-02-06 19:35:51 +00:00
# include "sci/graphics/coordadjuster.h"
2011-10-19 20:27:43 +03:00
# include "sci/graphics/compare.h"
2010-02-03 01:36:53 +00:00
# include "sci/graphics/font.h"
2010-02-02 16:25:35 +00:00
# include "sci/graphics/view.h"
# include "sci/graphics/screen.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"
2010-02-02 16:25:35 +00:00
# include "sci/graphics/picture.h"
2011-09-03 14:50:58 +03:00
# include "sci/graphics/text32.h"
2010-02-02 16:25:35 +00:00
# include "sci/graphics/frameout.h"
2011-02-07 12:24:09 +00:00
# include "sci/video/robot_decoder.h"
2010-02-02 16:25:35 +00:00
namespace Sci {
2010-10-31 01:45:24 +00:00
// TODO/FIXME: This is all guesswork
2012-06-09 12:12:44 +03:00
enum SciSpeciaPlanelPictureCodes {
kPlaneTranslucent = 0xfffe , // -2
kPlanePlainColored = 0xffff // -1
} ;
2016-01-06 20:00:28 -06:00
GfxFrameout : : GfxFrameout ( SegManager * segMan , ResourceManager * resMan , GfxCoordAdjuster * coordAdjuster , GfxCache * cache , GfxScreen * screen , GfxPalette32 * palette , GfxPaint32 * paint32 )
2010-02-04 17:57:44 +00:00
: _segMan ( segMan ) , _resMan ( resMan ) , _cache ( cache ) , _screen ( screen ) , _palette ( palette ) , _paint32 ( paint32 ) {
2010-02-05 19:33:39 +00:00
2010-02-06 19:35:51 +00:00
_coordAdjuster = ( GfxCoordAdjuster32 * ) coordAdjuster ;
2012-06-07 11:26:32 +03:00
_curScrollText = - 1 ;
_showScrollText = false ;
_maxScrollTexts = 0 ;
2010-02-02 16:25:35 +00:00
}
GfxFrameout : : ~ GfxFrameout ( ) {
2012-01-15 18:35:33 +02:00
clear ( ) ;
2010-02-02 16:25:35 +00:00
}
2011-02-14 22:38:12 -05:00
void GfxFrameout : : clear ( ) {
2012-01-15 18:35:33 +02:00
deletePlaneItems ( NULL_REG ) ;
2011-02-14 22:38:12 -05:00
_planes . clear ( ) ;
2012-01-15 18:35:33 +02:00
deletePlanePictures ( NULL_REG ) ;
2012-06-07 11:26:32 +03:00
clearScrollTexts ( ) ;
}
void GfxFrameout : : clearScrollTexts ( ) {
_scrollTexts . clear ( ) ;
_curScrollText = - 1 ;
}
void GfxFrameout : : addScrollTextEntry ( Common : : String & text , reg_t kWindow , uint16 x , uint16 y , bool replace ) {
//reg_t bitmapHandle = g_sci->_gfxText32->createScrollTextBitmap(text, kWindow);
// HACK: We set the container dimensions manually
reg_t bitmapHandle = g_sci - > _gfxText32 - > createScrollTextBitmap ( text , kWindow , 480 , 70 ) ;
ScrollTextEntry textEntry ;
textEntry . bitmapHandle = bitmapHandle ;
textEntry . kWindow = kWindow ;
textEntry . x = x ;
textEntry . y = y ;
if ( ! replace | | _scrollTexts . size ( ) = = 0 ) {
if ( _scrollTexts . size ( ) > _maxScrollTexts ) {
_scrollTexts . remove_at ( 0 ) ;
_curScrollText - - ;
}
_scrollTexts . push_back ( textEntry ) ;
_curScrollText + + ;
} else {
_scrollTexts . pop_back ( ) ;
_scrollTexts . push_back ( textEntry ) ;
}
}
void GfxFrameout : : showCurrentScrollText ( ) {
if ( ! _showScrollText | | _curScrollText < 0 )
return ;
uint16 size = ( uint16 ) _scrollTexts . size ( ) ;
if ( size > 0 ) {
assert ( _curScrollText < size ) ;
ScrollTextEntry textEntry = _scrollTexts [ _curScrollText ] ;
g_sci - > _gfxText32 - > drawScrollTextBitmap ( textEntry . kWindow , textEntry . bitmapHandle , textEntry . x , textEntry . y ) ;
}
2011-02-14 22:38:12 -05:00
}
2012-07-08 16:10:40 +03:00
extern void showScummVMDialog ( const Common : : String & message ) ;
2010-02-02 16:25:35 +00:00
void GfxFrameout : : kernelAddPlane ( reg_t object ) {
2010-07-24 16:47:12 +00:00
PlaneEntry newPlane ;
2010-07-25 04:45:28 +00:00
if ( _planes . empty ( ) ) {
// There has to be another way for sierra sci to do this or maybe script resolution is compiled into
// interpreter (TODO)
2012-07-26 11:05:50 +03:00
uint16 scriptWidth = readSelectorValue ( _segMan , object , SELECTOR ( resX ) ) ;
uint16 scriptHeight = readSelectorValue ( _segMan , object , SELECTOR ( resY ) ) ;
2010-11-20 00:20:05 +00:00
2012-07-26 11:05:50 +03:00
// Phantasmagoria 2 doesn't specify a script width/height
if ( g_sci - > getGameId ( ) = = GID_PHANTASMAGORIA2 ) {
scriptWidth = 640 ;
scriptHeight = 480 ;
2012-07-06 12:11:12 +03:00
}
2010-11-20 00:20:05 +00:00
2012-07-26 11:05:50 +03:00
assert ( scriptWidth > 0 & & scriptHeight > 0 ) ;
_coordAdjuster - > setScriptsResolution ( scriptWidth , scriptHeight ) ;
2010-07-25 04:45:28 +00:00
}
2012-07-08 16:10:40 +03:00
// Import of QfG character files dialog is shown in QFG4.
// Display additional popup information before letting user use it.
// For the SCI0-SCI1.1 version of this, check kDrawControl().
if ( g_sci - > inQfGImportRoom ( ) & & ! strcmp ( _segMan - > getObjectName ( object ) , " DSPlane " ) ) {
showScummVMDialog ( " Characters saved inside ScummVM are shown "
" automatically. Character files saved in the original "
" interpreter need to be put inside ScummVM's saved games "
" directory and a prefix needs to be added depending on which "
" game it was saved in: 'qfg1-' for Quest for Glory 1, 'qfg2-' "
" for Quest for Glory 2, 'qfg3-' for Quest for Glory 3. "
" Example: 'qfg2-thief.sav'. " ) ;
}
2010-07-24 16:47:12 +00:00
newPlane . object = object ;
2010-08-01 09:20:21 +00:00
newPlane . priority = readSelectorValue ( _segMan , object , SELECTOR ( priority ) ) ;
2012-07-16 11:49:50 +03:00
newPlane . lastPriority = - 1 ; // hidden
2010-09-19 14:50:28 +00:00
newPlane . planeOffsetX = 0 ;
2011-10-14 13:51:59 +03:00
newPlane . planeOffsetY = 0 ;
2012-06-09 12:12:44 +03:00
newPlane . pictureId = kPlanePlainColored ;
2011-03-30 13:33:39 +02:00
newPlane . planePictureMirrored = false ;
newPlane . planeBack = 0 ;
2010-07-24 16:47:12 +00:00
_planes . push_back ( newPlane ) ;
kernelUpdatePlane ( object ) ;
2010-02-02 16:25:35 +00:00
}
void GfxFrameout : : kernelUpdatePlane ( reg_t object ) {
2012-01-14 14:22:23 +02:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
2010-07-24 16:47:12 +00:00
if ( it - > object = = object ) {
// Read some information
it - > priority = readSelectorValue ( _segMan , object , SELECTOR ( priority ) ) ;
GuiResourceId lastPictureId = it - > pictureId ;
it - > pictureId = readSelectorValue ( _segMan , object , SELECTOR ( picture ) ) ;
if ( lastPictureId ! = it - > pictureId ) {
// picture got changed, load new picture
2010-07-26 14:41:19 +00:00
deletePlanePictures ( object ) ;
2012-06-09 12:12:44 +03:00
// Draw the plane's picture if it's not a translucent/plane colored frame
if ( ( it - > pictureId ! = kPlanePlainColored ) & & ( it - > pictureId ! = kPlaneTranslucent ) ) {
2010-07-25 04:45:28 +00:00
// SQ6 gives us a bad picture number for the control menu
if ( _resMan - > testResource ( ResourceId ( kResourceTypePic , it - > pictureId ) ) )
2010-07-26 14:41:19 +00:00
addPlanePicture ( object , it - > pictureId , 0 ) ;
2010-07-24 16:47:12 +00:00
}
}
2010-09-19 14:50:28 +00:00
it - > planeRect . top = readSelectorValue ( _segMan , object , SELECTOR ( top ) ) ;
it - > planeRect . left = readSelectorValue ( _segMan , object , SELECTOR ( left ) ) ;
2011-11-10 11:37:56 +02:00
it - > planeRect . bottom = readSelectorValue ( _segMan , object , SELECTOR ( bottom ) ) ;
it - > planeRect . right = readSelectorValue ( _segMan , object , SELECTOR ( right ) ) ;
2010-09-19 14:50:28 +00:00
2012-06-22 09:31:51 +03:00
_coordAdjuster - > fromScriptToDisplay ( it - > planeRect . top , it - > planeRect . left ) ;
_coordAdjuster - > fromScriptToDisplay ( it - > planeRect . bottom , it - > planeRect . right ) ;
2010-09-19 14:50:28 +00:00
// We get negative left in kq7 in scrolling rooms
if ( it - > planeRect . left < 0 ) {
it - > planeOffsetX = - it - > planeRect . left ;
it - > planeRect . left = 0 ;
2011-03-25 07:41:55 +02:00
} else {
it - > planeOffsetX = 0 ;
2010-09-19 14:50:28 +00:00
}
2012-09-26 04:17:31 +02:00
2011-10-14 13:51:59 +03:00
if ( it - > planeRect . top < 0 ) {
it - > planeOffsetY = - it - > planeRect . top ;
2010-09-19 14:50:28 +00:00
it - > planeRect . top = 0 ;
2011-10-14 13:51:59 +03:00
} else {
it - > planeOffsetY = 0 ;
}
2010-09-19 14:50:28 +00:00
// We get bad plane-bottom in sq6
if ( it - > planeRect . right > _screen - > getWidth ( ) )
it - > planeRect . right = _screen - > getWidth ( ) ;
if ( it - > planeRect . bottom > _screen - > getHeight ( ) )
it - > planeRect . bottom = _screen - > getHeight ( ) ;
it - > planeClipRect = Common : : Rect ( it - > planeRect . width ( ) , it - > planeRect . height ( ) ) ;
it - > upscaledPlaneRect = it - > planeRect ;
it - > upscaledPlaneClipRect = it - > planeClipRect ;
if ( _screen - > getUpscaledHires ( ) ) {
_screen - > adjustToUpscaledCoordinates ( it - > upscaledPlaneRect . top , it - > upscaledPlaneRect . left ) ;
_screen - > adjustToUpscaledCoordinates ( it - > upscaledPlaneRect . bottom , it - > upscaledPlaneRect . right ) ;
_screen - > adjustToUpscaledCoordinates ( it - > upscaledPlaneClipRect . top , it - > upscaledPlaneClipRect . left ) ;
_screen - > adjustToUpscaledCoordinates ( it - > upscaledPlaneClipRect . bottom , it - > upscaledPlaneClipRect . right ) ;
}
it - > planePictureMirrored = readSelectorValue ( _segMan , object , SELECTOR ( mirrored ) ) ;
it - > planeBack = readSelectorValue ( _segMan , object , SELECTOR ( back ) ) ;
2010-07-24 16:47:12 +00:00
sortPlanes ( ) ;
2010-10-23 19:23:07 +00:00
// Update the items in the plane
for ( FrameoutList : : iterator listIterator = _screenItems . begin ( ) ; listIterator ! = _screenItems . end ( ) ; listIterator + + ) {
reg_t itemPlane = readSelector ( _segMan , ( * listIterator ) - > object , SELECTOR ( plane ) ) ;
if ( object = = itemPlane ) {
kernelUpdateScreenItem ( ( * listIterator ) - > object ) ;
}
}
2010-07-24 16:47:12 +00:00
return ;
}
}
error ( " kUpdatePlane called on plane that wasn't added before " ) ;
2010-02-02 16:25:35 +00:00
}
void GfxFrameout : : kernelDeletePlane ( reg_t object ) {
2012-01-14 14:22:23 +02:00
deletePlaneItems ( object ) ;
2010-07-26 14:41:19 +00:00
deletePlanePictures ( object ) ;
2012-01-14 14:22:23 +02:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
2010-07-24 16:47:12 +00:00
if ( it - > object = = object ) {
2010-06-20 17:17:46 +00:00
_planes . erase ( it ) ;
2010-07-25 19:56:44 +00:00
Common : : Rect planeRect ;
planeRect . top = readSelectorValue ( _segMan , object , SELECTOR ( top ) ) ;
planeRect . left = readSelectorValue ( _segMan , object , SELECTOR ( left ) ) ;
2011-11-10 11:37:56 +02:00
planeRect . bottom = readSelectorValue ( _segMan , object , SELECTOR ( bottom ) ) ;
planeRect . right = readSelectorValue ( _segMan , object , SELECTOR ( right ) ) ;
2010-07-25 19:56:44 +00:00
2012-06-22 09:31:51 +03:00
_coordAdjuster - > fromScriptToDisplay ( planeRect . top , planeRect . left ) ;
_coordAdjuster - > fromScriptToDisplay ( planeRect . bottom , planeRect . right ) ;
2010-07-25 19:56:44 +00:00
// Blackout removed plane rect
_paint32 - > fillRect ( planeRect , 0 ) ;
2010-06-20 17:17:46 +00:00
return ;
2010-02-02 16:25:35 +00:00
}
}
}
2011-09-23 18:53:52 +03:00
void GfxFrameout : : addPlanePicture ( reg_t object , GuiResourceId pictureId , uint16 startX , uint16 startY ) {
2012-06-09 12:12:44 +03:00
if ( pictureId = = kPlanePlainColored | | pictureId = = kPlaneTranslucent ) // sanity check
return ;
2010-07-26 14:41:19 +00:00
PlanePictureEntry newPicture ;
newPicture . object = object ;
newPicture . pictureId = pictureId ;
newPicture . picture = new GfxPicture ( _resMan , _coordAdjuster , 0 , _screen , _palette , pictureId , false ) ;
newPicture . startX = startX ;
2011-09-23 18:53:52 +03:00
newPicture . startY = startY ;
2010-08-01 01:00:30 +00:00
newPicture . pictureCels = 0 ;
2010-07-26 14:41:19 +00:00
_planePictures . push_back ( newPicture ) ;
}
void GfxFrameout : : deletePlanePictures ( reg_t object ) {
2012-01-15 18:35:33 +02:00
PlanePictureList : : iterator it = _planePictures . begin ( ) ;
while ( it ! = _planePictures . end ( ) ) {
if ( it - > object = = object | | object . isNull ( ) ) {
delete it - > pictureCels ;
2010-07-26 14:41:19 +00:00
delete it - > picture ;
2012-01-15 18:35:33 +02:00
it = _planePictures . erase ( it ) ;
} else {
+ + it ;
2010-07-26 14:41:19 +00:00
}
}
}
2012-06-09 15:36:36 +03:00
// Provides the same functionality as kGraph(DrawLine)
reg_t GfxFrameout : : addPlaneLine ( reg_t object , Common : : Point startPoint , Common : : Point endPoint , byte color , byte priority , byte control ) {
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
if ( it - > object = = object ) {
PlaneLineEntry line ;
line . hunkId = _segMan - > allocateHunkEntry ( " PlaneLine() " , 1 ) ; // we basically use this for a unique ID
line . startPoint = startPoint ;
line . endPoint = endPoint ;
line . color = color ;
line . priority = priority ;
line . control = control ;
it - > lines . push_back ( line ) ;
return line . hunkId ;
}
}
return NULL_REG ;
}
void GfxFrameout : : updatePlaneLine ( reg_t object , reg_t hunkId , Common : : Point startPoint , Common : : Point endPoint , byte color , byte priority , byte control ) {
2012-07-05 13:42:00 +03:00
// Check if we're asked to update a line that was never added
2012-07-05 14:05:26 +03:00
if ( hunkId . isNull ( ) )
2012-07-05 13:42:00 +03:00
return ;
2012-06-09 15:36:36 +03:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
if ( it - > object = = object ) {
for ( PlaneLineList : : iterator it2 = it - > lines . begin ( ) ; it2 ! = it - > lines . end ( ) ; + + it2 ) {
if ( it2 - > hunkId = = hunkId ) {
it2 - > startPoint = startPoint ;
it2 - > endPoint = endPoint ;
it2 - > color = color ;
it2 - > priority = priority ;
it2 - > control = control ;
return ;
}
}
}
}
}
void GfxFrameout : : deletePlaneLine ( reg_t object , reg_t hunkId ) {
2012-07-05 13:42:00 +03:00
// Check if we're asked to delete a line that was never added (happens during the intro of LSL6)
2012-07-05 14:05:26 +03:00
if ( hunkId . isNull ( ) )
2012-07-05 13:42:00 +03:00
return ;
2012-06-09 15:36:36 +03:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
if ( it - > object = = object ) {
for ( PlaneLineList : : iterator it2 = it - > lines . begin ( ) ; it2 ! = it - > lines . end ( ) ; + + it2 ) {
if ( it2 - > hunkId = = hunkId ) {
_segMan - > freeHunkEntry ( hunkId ) ;
it2 = it - > lines . erase ( it2 ) ;
return ;
}
}
}
}
}
2013-01-11 00:45:10 +02:00
// Adapted from GfxAnimate::applyGlobalScaling()
void GfxFrameout : : applyGlobalScaling ( FrameoutEntry * itemEntry , Common : : Rect planeRect , int16 celHeight ) {
// Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY
int16 maxScale = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( maxScale ) ) ;
int16 maxCelHeight = ( maxScale * celHeight ) > > 7 ;
reg_t globalVar2 = g_sci - > getEngineState ( ) - > variables [ VAR_GLOBAL ] [ 2 ] ; // current room object
int16 vanishingY = readSelectorValue ( _segMan , globalVar2 , SELECTOR ( vanishingY ) ) ;
int16 fixedPortY = planeRect . bottom - vanishingY ;
int16 fixedEntryY = itemEntry - > y - vanishingY ;
if ( ! fixedEntryY )
fixedEntryY = 1 ;
if ( ( celHeight = = 0 ) | | ( fixedPortY = = 0 ) )
error ( " global scaling panic " ) ;
itemEntry - > scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY ;
itemEntry - > scaleY = ( itemEntry - > scaleY * maxScale ) / celHeight ;
// Make sure that the calculated value is sane
if ( itemEntry - > scaleY < 1 /*|| itemEntry->scaleY > 128*/ )
itemEntry - > scaleY = 128 ;
itemEntry - > scaleX = itemEntry - > scaleY ;
// and set objects scale selectors
//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleX), itemEntry->scaleX);
//writeSelectorValue(_segMan, itemEntry->object, SELECTOR(scaleY), itemEntry->scaleY);
}
2010-02-02 16:25:35 +00:00
void GfxFrameout : : kernelAddScreenItem ( reg_t object ) {
2010-10-23 19:23:07 +00:00
// Ignore invalid items
2012-07-04 02:17:27 +03:00
if ( ! _segMan - > isObject ( object ) ) {
warning ( " kernelAddScreenItem: Attempt to add an invalid object (%04x:%04x) " , PRINT_REG ( object ) ) ;
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
FrameoutEntry * itemEntry = new FrameoutEntry ( ) ;
2010-12-06 19:37:19 +00:00
memset ( itemEntry , 0 , sizeof ( FrameoutEntry ) ) ;
2010-10-23 19:23:07 +00:00
itemEntry - > object = object ;
itemEntry - > givenOrderNr = _screenItems . size ( ) ;
2012-05-14 02:30:15 +03:00
itemEntry - > visible = true ;
2010-10-23 19:23:07 +00:00
_screenItems . push_back ( itemEntry ) ;
kernelUpdateScreenItem ( object ) ;
2010-02-02 16:25:35 +00:00
}
2010-09-19 14:50:28 +00:00
void GfxFrameout : : kernelUpdateScreenItem ( reg_t object ) {
2010-10-23 19:23:07 +00:00
// Ignore invalid items
2012-07-04 02:17:27 +03:00
if ( ! _segMan - > isObject ( object ) ) {
warning ( " kernelUpdateScreenItem: Attempt to update an invalid object (%04x:%04x) " , PRINT_REG ( object ) ) ;
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
2011-10-12 02:43:08 +03:00
FrameoutEntry * itemEntry = findScreenItem ( object ) ;
if ( ! itemEntry ) {
warning ( " kernelUpdateScreenItem: invalid object %04x:%04x " , PRINT_REG ( object ) ) ;
return ;
2010-10-23 19:23:07 +00:00
}
2011-10-12 02:43:08 +03:00
itemEntry - > viewId = readSelectorValue ( _segMan , object , SELECTOR ( view ) ) ;
itemEntry - > loopNo = readSelectorValue ( _segMan , object , SELECTOR ( loop ) ) ;
itemEntry - > celNo = readSelectorValue ( _segMan , object , SELECTOR ( cel ) ) ;
itemEntry - > x = readSelectorValue ( _segMan , object , SELECTOR ( x ) ) ;
itemEntry - > y = readSelectorValue ( _segMan , object , SELECTOR ( y ) ) ;
itemEntry - > z = readSelectorValue ( _segMan , object , SELECTOR ( z ) ) ;
itemEntry - > priority = readSelectorValue ( _segMan , object , SELECTOR ( priority ) ) ;
if ( readSelectorValue ( _segMan , object , SELECTOR ( fixPriority ) ) = = 0 )
itemEntry - > priority = itemEntry - > y ;
itemEntry - > signal = readSelectorValue ( _segMan , object , SELECTOR ( signal ) ) ;
2013-01-11 00:45:10 +02:00
itemEntry - > scaleSignal = readSelectorValue ( _segMan , object , SELECTOR ( scaleSignal ) ) ;
2013-01-13 17:28:09 +02:00
if ( itemEntry - > scaleSignal & kScaleSignalDoScaling32 ) {
2013-01-11 00:45:10 +02:00
itemEntry - > scaleX = readSelectorValue ( _segMan , object , SELECTOR ( scaleX ) ) ;
itemEntry - > scaleY = readSelectorValue ( _segMan , object , SELECTOR ( scaleY ) ) ;
} else {
itemEntry - > scaleX = 128 ;
itemEntry - > scaleY = 128 ;
}
2012-05-14 02:30:15 +03:00
itemEntry - > visible = true ;
// Check if the entry can be hidden
if ( lookupSelector ( _segMan , object , SELECTOR ( visible ) , NULL , NULL ) ! = kSelectorNone )
itemEntry - > visible = readSelectorValue ( _segMan , object , SELECTOR ( visible ) ) ;
2010-09-19 14:50:28 +00:00
}
2010-02-02 16:25:35 +00:00
void GfxFrameout : : kernelDeleteScreenItem ( reg_t object ) {
2011-10-12 02:43:08 +03:00
FrameoutEntry * itemEntry = findScreenItem ( object ) ;
2012-07-04 02:17:27 +03:00
// If the item could not be found, it may already have been deleted
if ( ! itemEntry )
2011-10-12 02:43:08 +03:00
return ;
_screenItems . remove ( itemEntry ) ;
2012-01-15 18:35:33 +02:00
delete itemEntry ;
2011-10-12 02:43:08 +03:00
}
2012-01-14 14:22:23 +02:00
void GfxFrameout : : deletePlaneItems ( reg_t planeObject ) {
FrameoutList : : iterator listIterator = _screenItems . begin ( ) ;
while ( listIterator ! = _screenItems . end ( ) ) {
2012-01-15 18:35:33 +02:00
bool objectMatches = false ;
if ( ! planeObject . isNull ( ) ) {
reg_t itemPlane = readSelector ( _segMan , ( * listIterator ) - > object , SELECTOR ( plane ) ) ;
objectMatches = ( planeObject = = itemPlane ) ;
} else {
objectMatches = true ;
}
2012-09-26 04:17:31 +02:00
2012-01-15 18:35:33 +02:00
if ( objectMatches ) {
FrameoutEntry * itemEntry = * listIterator ;
2012-01-14 14:22:23 +02:00
listIterator = _screenItems . erase ( listIterator ) ;
2012-01-15 18:35:33 +02:00
delete itemEntry ;
} else {
2012-01-14 14:22:23 +02:00
+ + listIterator ;
2012-01-15 18:35:33 +02:00
}
2012-01-14 14:22:23 +02:00
}
}
2011-10-12 02:43:08 +03:00
FrameoutEntry * GfxFrameout : : findScreenItem ( reg_t object ) {
2010-10-23 19:23:07 +00:00
for ( FrameoutList : : iterator listIterator = _screenItems . begin ( ) ; listIterator ! = _screenItems . end ( ) ; listIterator + + ) {
FrameoutEntry * itemEntry = * listIterator ;
2011-10-12 02:43:08 +03:00
if ( itemEntry - > object = = object )
return itemEntry ;
2010-02-02 16:25:35 +00:00
}
2011-10-12 02:43:08 +03:00
return NULL ;
2010-02-02 16:25:35 +00:00
}
int16 GfxFrameout : : kernelGetHighPlanePri ( ) {
2010-06-20 17:17:46 +00:00
sortPlanes ( ) ;
2010-07-24 16:47:12 +00:00
return readSelectorValue ( g_sci - > getEngineState ( ) - > _segMan , _planes . back ( ) . object , SELECTOR ( priority ) ) ;
2010-02-02 16:25:35 +00:00
}
2011-09-23 18:53:52 +03:00
void GfxFrameout : : kernelAddPicAt ( reg_t planeObj , GuiResourceId pictureId , int16 pictureX , int16 pictureY ) {
addPlanePicture ( planeObj , pictureId , pictureX , pictureY ) ;
2010-07-25 20:41:23 +00:00
}
2010-02-02 16:25:35 +00:00
bool sortHelper ( const FrameoutEntry * entry1 , const FrameoutEntry * entry2 ) {
2010-07-24 18:06:49 +00:00
if ( entry1 - > priority = = entry2 - > priority ) {
if ( entry1 - > y = = entry2 - > y )
return ( entry1 - > givenOrderNr < entry2 - > givenOrderNr ) ;
return ( entry1 - > y < entry2 - > y ) ;
}
return ( entry1 - > priority < entry2 - > priority ) ;
2010-02-02 16:25:35 +00:00
}
2010-07-24 16:47:12 +00:00
bool planeSortHelper ( const PlaneEntry & entry1 , const PlaneEntry & entry2 ) {
2012-07-16 11:49:50 +03:00
if ( entry1 . priority < 0 )
2010-06-20 17:17:46 +00:00
return true ;
2010-02-02 16:25:35 +00:00
2012-07-16 11:49:50 +03:00
if ( entry2 . priority < 0 )
2010-06-20 17:17:46 +00:00
return false ;
2010-06-14 16:58:15 +00:00
2010-07-24 16:47:12 +00:00
return entry1 . priority < entry2 . priority ;
2010-06-20 17:17:46 +00:00
}
void GfxFrameout : : sortPlanes ( ) {
// First, remove any invalid planes
2010-07-24 16:47:12 +00:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; ) {
if ( ! _segMan - > isObject ( it - > object ) )
2010-06-20 17:17:46 +00:00
it = _planes . erase ( it ) ;
else
it + + ;
}
// Sort the rest of them
Common : : sort ( _planes . begin ( ) , _planes . end ( ) , planeSortHelper ) ;
}
2010-06-14 16:58:15 +00:00
2011-11-17 22:08:36 +02:00
void GfxFrameout : : showVideo ( ) {
bool skipVideo = false ;
RobotDecoder * videoDecoder = g_sci - > _robotDecoder ;
uint16 x = videoDecoder - > getPos ( ) . x ;
uint16 y = videoDecoder - > getPos ( ) . y ;
2014-11-09 17:33:17 +01:00
uint16 screenWidth = _screen - > getWidth ( ) ;
uint16 screenHeight = _screen - > getHeight ( ) ;
uint16 outputWidth ;
uint16 outputHeight ;
2011-11-17 22:08:36 +02:00
if ( videoDecoder - > hasDirtyPalette ( ) )
2012-08-16 13:30:32 -04:00
g_system - > getPaletteManager ( ) - > setPalette ( videoDecoder - > getPalette ( ) , 0 , 256 ) ;
2011-11-17 22:08:36 +02:00
while ( ! g_engine - > shouldQuit ( ) & & ! videoDecoder - > endOfVideo ( ) & & ! skipVideo ) {
if ( videoDecoder - > needsUpdate ( ) ) {
const Graphics : : Surface * frame = videoDecoder - > decodeNextFrame ( ) ;
if ( frame ) {
2014-11-09 17:33:17 +01:00
// We need to clip here
// At least Phantasmagoria shows a 640x390 video on a 630x450 screen during the intro
outputWidth = frame - > w > screenWidth ? screenWidth : frame - > w ;
outputHeight = frame - > h > screenHeight ? screenHeight : frame - > h ;
g_system - > copyRectToScreen ( frame - > getPixels ( ) , frame - > pitch , x , y , outputWidth , outputHeight ) ;
2011-11-17 22:08:36 +02:00
if ( videoDecoder - > hasDirtyPalette ( ) )
2012-08-16 13:30:32 -04:00
g_system - > getPaletteManager ( ) - > setPalette ( videoDecoder - > getPalette ( ) , 0 , 256 ) ;
2011-11-17 22:08:36 +02:00
g_system - > updateScreen ( ) ;
2011-02-07 12:24:09 +00:00
}
2011-11-17 22:08:36 +02:00
}
2011-02-07 12:24:09 +00:00
2011-11-17 22:08:36 +02:00
Common : : Event event ;
while ( g_system - > getEventManager ( ) - > pollEvent ( event ) ) {
if ( ( event . type = = Common : : EVENT_KEYDOWN & & event . kbd . keycode = = Common : : KEYCODE_ESCAPE ) | | event . type = = Common : : EVENT_LBUTTONUP )
skipVideo = true ;
}
g_system - > delayMillis ( 10 ) ;
}
}
void GfxFrameout : : createPlaneItemList ( reg_t planeObject , FrameoutList & itemList ) {
// Copy screen items of the current frame to the list of items to be drawn
for ( FrameoutList : : iterator listIterator = _screenItems . begin ( ) ; listIterator ! = _screenItems . end ( ) ; listIterator + + ) {
reg_t itemPlane = readSelector ( _segMan , ( * listIterator ) - > object , SELECTOR ( plane ) ) ;
if ( planeObject = = itemPlane ) {
kernelUpdateScreenItem ( ( * listIterator ) - > object ) ; // TODO: Why is this necessary?
itemList . push_back ( * listIterator ) ;
}
}
for ( PlanePictureList : : iterator pictureIt = _planePictures . begin ( ) ; pictureIt ! = _planePictures . end ( ) ; pictureIt + + ) {
if ( pictureIt - > object = = planeObject ) {
GfxPicture * planePicture = pictureIt - > picture ;
// Allocate memory for picture cels
pictureIt - > pictureCels = new FrameoutEntry [ planePicture - > getSci32celCount ( ) ] ;
// Add following cels to the itemlist
FrameoutEntry * picEntry = pictureIt - > pictureCels ;
int planePictureCels = planePicture - > getSci32celCount ( ) ;
for ( int pictureCelNr = 0 ; pictureCelNr < planePictureCels ; pictureCelNr + + ) {
picEntry - > celNo = pictureCelNr ;
picEntry - > object = NULL_REG ;
picEntry - > picture = planePicture ;
picEntry - > y = planePicture - > getSci32celY ( pictureCelNr ) ;
picEntry - > x = planePicture - > getSci32celX ( pictureCelNr ) ;
picEntry - > picStartX = pictureIt - > startX ;
picEntry - > picStartY = pictureIt - > startY ;
2012-05-14 02:30:15 +03:00
picEntry - > visible = true ;
2011-11-17 22:08:36 +02:00
picEntry - > priority = planePicture - > getSci32celPriority ( pictureCelNr ) ;
itemList . push_back ( picEntry ) ;
picEntry + + ;
2011-02-07 12:24:09 +00:00
}
2011-11-17 22:08:36 +02:00
}
}
// Now sort our itemlist
Common : : sort ( itemList . begin ( ) , itemList . end ( ) , sortHelper ) ;
}
bool GfxFrameout : : isPictureOutOfView ( FrameoutEntry * itemEntry , Common : : Rect planeRect , int16 planeOffsetX , int16 planeOffsetY ) {
// Out of view horizontally (sanity checks)
int16 pictureCelStartX = itemEntry - > picStartX + itemEntry - > x ;
int16 pictureCelEndX = pictureCelStartX + itemEntry - > picture - > getSci32celWidth ( itemEntry - > celNo ) ;
int16 planeStartX = planeOffsetX ;
int16 planeEndX = planeStartX + planeRect . width ( ) ;
if ( pictureCelEndX < planeStartX )
return true ;
if ( pictureCelStartX > planeEndX )
return true ;
2011-02-07 12:24:09 +00:00
2011-11-17 22:08:36 +02:00
// Out of view vertically (sanity checks)
int16 pictureCelStartY = itemEntry - > picStartY + itemEntry - > y ;
int16 pictureCelEndY = pictureCelStartY + itemEntry - > picture - > getSci32celHeight ( itemEntry - > celNo ) ;
int16 planeStartY = planeOffsetY ;
int16 planeEndY = planeStartY + planeRect . height ( ) ;
if ( pictureCelEndY < planeStartY )
return true ;
if ( pictureCelStartY > planeEndY )
return true ;
return false ;
}
void GfxFrameout : : drawPicture ( FrameoutEntry * itemEntry , int16 planeOffsetX , int16 planeOffsetY , bool planePictureMirrored ) {
int16 pictureOffsetX = planeOffsetX ;
int16 pictureX = itemEntry - > x ;
if ( ( planeOffsetX ) | | ( itemEntry - > picStartX ) ) {
if ( planeOffsetX < = itemEntry - > picStartX ) {
pictureX + = itemEntry - > picStartX - planeOffsetX ;
pictureOffsetX = 0 ;
} else {
pictureOffsetX = planeOffsetX - itemEntry - > picStartX ;
}
}
int16 pictureOffsetY = planeOffsetY ;
int16 pictureY = itemEntry - > y ;
if ( ( planeOffsetY ) | | ( itemEntry - > picStartY ) ) {
if ( planeOffsetY < = itemEntry - > picStartY ) {
pictureY + = itemEntry - > picStartY - planeOffsetY ;
pictureOffsetY = 0 ;
} else {
pictureOffsetY = planeOffsetY - itemEntry - > picStartY ;
2011-02-07 12:24:09 +00:00
}
2011-11-17 22:08:36 +02:00
}
itemEntry - > picture - > drawSci32Vga ( itemEntry - > celNo , pictureX , itemEntry - > y , pictureOffsetX , pictureOffsetY , planePictureMirrored ) ;
// warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);
}
void GfxFrameout : : kernelFrameout ( ) {
if ( g_sci - > _robotDecoder - > isVideoLoaded ( ) ) {
showVideo ( ) ;
2011-01-22 13:01:10 +00:00
return ;
2011-02-07 12:24:09 +00:00
}
2011-01-22 13:01:10 +00:00
2010-06-20 17:17:46 +00:00
_palette - > palVaryUpdate ( ) ;
2016-01-06 20:00:28 -06:00
_palette - > applyCycles ( ) ;
_palette - > applyFade ( ) ;
// TODO: This should probably not require screen pic invalidation
_screen - > _picNotValid = 1 ;
_palette - > setOnScreen ( ) ;
2010-02-02 16:25:35 +00:00
2010-07-24 16:47:12 +00:00
for ( PlaneList : : iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; it + + ) {
reg_t planeObject = it - > object ;
2012-06-09 15:36:36 +03:00
// Draw any plane lines, if they exist
// These are drawn on invisible planes as well. (e.g. "invisiblePlane" in LSL6 hires)
// FIXME: Lines aren't always drawn (e.g. when the narrator speaks in LSL6 hires).
// Perhaps something is painted over them?
for ( PlaneLineList : : iterator it2 = it - > lines . begin ( ) ; it2 ! = it - > lines . end ( ) ; + + it2 ) {
Common : : Point startPoint = it2 - > startPoint ;
Common : : Point endPoint = it2 - > endPoint ;
_coordAdjuster - > kernelLocalToGlobal ( startPoint . x , startPoint . y , it - > object ) ;
_coordAdjuster - > kernelLocalToGlobal ( endPoint . x , endPoint . y , it - > object ) ;
_screen - > drawLine ( startPoint , endPoint , it2 - > color , it2 - > priority , it2 - > control ) ;
}
2012-07-16 11:49:50 +03:00
int16 planeLastPriority = it - > lastPriority ;
2010-06-20 17:17:46 +00:00
2010-07-25 04:45:28 +00:00
// Update priority here, sq6 sets it w/o UpdatePlane
2012-07-16 11:49:50 +03:00
int16 planePriority = it - > priority = readSelectorValue ( _segMan , planeObject , SELECTOR ( priority ) ) ;
2010-07-25 04:45:28 +00:00
2010-07-24 16:47:12 +00:00
it - > lastPriority = planePriority ;
2012-07-16 11:49:50 +03:00
if ( planePriority < 0 ) { // Plane currently not meant to be shown
2010-07-24 16:47:12 +00:00
// If plane was shown before, delete plane rect
if ( planePriority ! = planeLastPriority )
2010-09-19 14:50:28 +00:00
_paint32 - > fillRect ( it - > planeRect , 0 ) ;
2010-07-24 15:25:29 +00:00
continue ;
}
2011-10-08 12:23:24 +02:00
// There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX.
// Since I first wrote the patch, the race has stopped occurring for me though.
// I'll leave this for investigation later, when someone can reproduce.
2012-06-09 12:12:44 +03:00
//if (it->pictureId == kPlanePlainColored) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes)
2012-06-15 11:33:28 +03:00
if ( it - > pictureId = = kPlanePlainColored & & ( it - > planeBack | | g_sci - > getGameId ( ) ! = GID_GK1 ) )
2010-09-19 14:50:28 +00:00
_paint32 - > fillRect ( it - > planeRect , it - > planeBack ) ;
2010-02-04 17:57:44 +00:00
2010-09-19 14:50:28 +00:00
_coordAdjuster - > pictureSetDisplayArea ( it - > planeRect ) ;
2013-01-11 00:49:34 +02:00
// Invoking drewPicture() with an invalid picture ID in SCI32 results in
// invalidating the palVary palette when a palVary effect is active. This
// is quite obvious in QFG4, where the day time palette is incorrectly
// shown when exiting the caves, and the correct night time palette
// flashes briefly each time that kPalVaryInit is called.
if ( it - > pictureId ! = 0xFFFF )
_palette - > drewPicture ( it - > pictureId ) ;
2010-02-04 17:57:44 +00:00
2010-06-20 17:17:46 +00:00
FrameoutList itemList ;
2011-11-17 22:08:36 +02:00
createPlaneItemList ( planeObject , itemList ) ;
2010-02-02 16:25:35 +00:00
2010-06-20 17:17:46 +00:00
for ( FrameoutList : : iterator listIterator = itemList . begin ( ) ; listIterator ! = itemList . end ( ) ; listIterator + + ) {
2010-10-23 19:23:07 +00:00
FrameoutEntry * itemEntry = * listIterator ;
2010-06-20 17:17:46 +00:00
2012-05-14 02:30:15 +03:00
if ( ! itemEntry - > visible )
continue ;
2012-09-26 04:17:31 +02:00
2010-07-22 10:24:08 +00:00
if ( itemEntry - > object . isNull ( ) ) {
// Picture cel data
2012-06-22 09:31:51 +03:00
_coordAdjuster - > fromScriptToDisplay ( itemEntry - > y , itemEntry - > x ) ;
_coordAdjuster - > fromScriptToDisplay ( itemEntry - > picStartY , itemEntry - > picStartX ) ;
2010-07-22 10:24:08 +00:00
2011-11-17 22:08:36 +02:00
if ( ! isPictureOutOfView ( itemEntry , it - > planeRect , it - > planeOffsetX , it - > planeOffsetY ) )
drawPicture ( itemEntry , it - > planeOffsetX , it - > planeOffsetY , it - > planePictureMirrored ) ;
2011-10-29 01:39:37 +03:00
} else {
GfxView * view = ( itemEntry - > viewId ! = 0xFFFF ) ? _cache - > getView ( itemEntry - > viewId ) : NULL ;
2012-06-22 09:43:44 +03:00
int16 dummyX = 0 ;
2011-10-29 01:39:37 +03:00
if ( view & & view - > isSci2Hires ( ) ) {
2011-03-30 21:26:48 +02:00
view - > adjustToUpscaledCoordinates ( itemEntry - > y , itemEntry - > x ) ;
view - > adjustToUpscaledCoordinates ( itemEntry - > z , dummyX ) ;
2015-12-29 01:44:11 +01:00
} else if ( getSciVersion ( ) > = SCI_VERSION_2_1_EARLY ) {
2012-06-22 09:31:51 +03:00
_coordAdjuster - > fromScriptToDisplay ( itemEntry - > y , itemEntry - > x ) ;
2012-06-22 09:43:44 +03:00
_coordAdjuster - > fromScriptToDisplay ( itemEntry - > z , dummyX ) ;
2010-07-24 21:18:07 +00:00
}
2011-02-02 22:29:14 +00:00
2010-07-26 12:20:07 +00:00
// Adjust according to current scroll position
2010-09-19 14:50:28 +00:00
itemEntry - > x - = it - > planeOffsetX ;
2011-10-14 13:51:59 +03:00
itemEntry - > y - = it - > planeOffsetY ;
2010-07-24 21:18:07 +00:00
2010-07-24 17:43:56 +00:00
uint16 useInsetRect = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( useInsetRect ) ) ;
if ( useInsetRect ) {
itemEntry - > celRect . top = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( inTop ) ) ;
itemEntry - > celRect . left = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( inLeft ) ) ;
2011-11-10 11:37:56 +02:00
itemEntry - > celRect . bottom = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( inBottom ) ) ;
itemEntry - > celRect . right = readSelectorValue ( _segMan , itemEntry - > object , SELECTOR ( inRight ) ) ;
2011-10-29 01:39:37 +03:00
if ( view & & view - > isSci2Hires ( ) ) {
2011-03-30 21:26:48 +02:00
view - > adjustToUpscaledCoordinates ( itemEntry - > celRect . top , itemEntry - > celRect . left ) ;
view - > adjustToUpscaledCoordinates ( itemEntry - > celRect . bottom , itemEntry - > celRect . right ) ;
2010-07-24 21:18:07 +00:00
}
2010-07-24 17:43:56 +00:00
itemEntry - > celRect . translate ( itemEntry - > x , itemEntry - > y ) ;
// TODO: maybe we should clip the cels rect with this, i'm not sure
// the only currently known usage is game menu of gk1
2011-10-29 01:39:37 +03:00
} else if ( view ) {
2013-01-11 00:45:10 +02:00
// Process global scaling, if needed.
// TODO: Seems like SCI32 always processes global scaling for scaled objects
// TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
2013-07-14 19:01:47 +02:00
if ( ( itemEntry - > scaleSignal & kScaleSignalDoScaling32 ) & &
2013-01-13 17:28:09 +02:00
! ( itemEntry - > scaleSignal & kScaleSignalDisableGlobalScaling32 ) & &
2013-04-25 02:36:03 +03:00
( itemEntry - > scaleX = = itemEntry - > scaleY ) & &
itemEntry - > scaleX ! = 128 )
2013-01-11 00:45:10 +02:00
applyGlobalScaling ( itemEntry , it - > planeRect , view - > getHeight ( itemEntry - > loopNo , itemEntry - > celNo ) ) ;
2012-07-26 11:05:50 +03:00
if ( ( itemEntry - > scaleX = = 128 ) & & ( itemEntry - > scaleY = = 128 ) )
view - > getCelRect ( itemEntry - > loopNo , itemEntry - > celNo ,
itemEntry - > x , itemEntry - > y , itemEntry - > z , itemEntry - > celRect ) ;
else
2012-09-26 04:17:31 +02:00
view - > getCelScaledRect ( itemEntry - > loopNo , itemEntry - > celNo ,
2012-07-26 11:05:50 +03:00
itemEntry - > x , itemEntry - > y , itemEntry - > z , itemEntry - > scaleX ,
itemEntry - > scaleY , itemEntry - > celRect ) ;
2010-07-24 17:43:56 +00:00
Common : : Rect nsRect = itemEntry - > celRect ;
2010-07-27 09:17:57 +00:00
// Translate back to actual coordinate within scrollable plane
2011-10-14 13:51:59 +03:00
nsRect . translate ( it - > planeOffsetX , it - > planeOffsetY ) ;
2011-02-02 22:29:14 +00:00
2011-10-18 03:10:19 +03:00
if ( g_sci - > getGameId ( ) = = GID_PHANTASMAGORIA2 ) {
// HACK: Some (?) objects in Phantasmagoria 2 have no NS rect. Skip them for now.
// TODO: Remove once we figure out how Phantasmagoria 2 draws objects on screen.
if ( lookupSelector ( _segMan , itemEntry - > object , SELECTOR ( nsLeft ) , NULL , NULL ) ! = kSelectorVariable )
continue ;
}
2013-03-28 20:27:35 +02:00
if ( view & & view - > isSci2Hires ( ) ) {
view - > adjustBackUpscaledCoordinates ( nsRect . top , nsRect . left ) ;
view - > adjustBackUpscaledCoordinates ( nsRect . bottom , nsRect . right ) ;
g_sci - > _gfxCompare - > setNSRect ( itemEntry - > object , nsRect ) ;
2015-12-29 01:44:11 +01:00
} else if ( getSciVersion ( ) > = SCI_VERSION_2_1_EARLY & & _resMan - > detectHires ( ) ) {
2013-03-28 20:27:35 +02:00
_coordAdjuster - > fromDisplayToScript ( nsRect . top , nsRect . left ) ;
_coordAdjuster - > fromDisplayToScript ( nsRect . bottom , nsRect . right ) ;
g_sci - > _gfxCompare - > setNSRect ( itemEntry - > object , nsRect ) ;
}
2013-07-30 04:21:51 +03:00
// TODO: For some reason, the top left nsRect coordinates get
// swapped in the GK1 inventory screen, investigate why.
2014-08-08 02:07:57 +03:00
// This is also needed for GK1 rooms 710 and 720 (catacombs, inner and
// outer circle), for handling the tiles and talking to Wolfgang.
2014-10-13 12:21:02 +03:00
// HACK: Fix the coordinates by explicitly setting them here for GK1.
2014-10-13 12:26:21 +03:00
// Also check bug #6729, for another case where this is needed.
2014-10-13 12:21:02 +03:00
if ( g_sci - > getGameId ( ) = = GID_GK1 )
2013-07-30 04:21:51 +03:00
g_sci - > _gfxCompare - > setNSRect ( itemEntry - > object , nsRect ) ;
2010-07-22 19:20:26 +00:00
}
2012-08-21 11:55:21 +03:00
// Don't attempt to draw sprites that are outside the visible
// screen area. An example is the random people walking in
// Jackson Square in GK1.
2012-06-22 09:43:44 +03:00
if ( itemEntry - > celRect . bottom < 0 | | itemEntry - > celRect . top > = _screen - > getDisplayHeight ( ) | |
itemEntry - > celRect . right < 0 | | itemEntry - > celRect . left > = _screen - > getDisplayWidth ( ) )
2010-02-02 16:25:35 +00:00
continue ;
2010-07-22 19:20:26 +00:00
Common : : Rect clipRect , translatedClipRect ;
2010-02-04 16:12:47 +00:00
clipRect = itemEntry - > celRect ;
2011-10-29 01:39:37 +03:00
if ( view & & view - > isSci2Hires ( ) ) {
2010-09-19 14:50:28 +00:00
clipRect . clip ( it - > upscaledPlaneClipRect ) ;
2010-07-22 19:20:26 +00:00
translatedClipRect = clipRect ;
2010-09-19 14:50:28 +00:00
translatedClipRect . translate ( it - > upscaledPlaneRect . left , it - > upscaledPlaneRect . top ) ;
2010-06-30 14:26:47 +00:00
} else {
2012-07-04 02:20:39 +03:00
// QFG4 passes invalid rectangles when a battle is starting
if ( ! clipRect . isValidRect ( ) )
continue ;
2010-09-19 14:50:28 +00:00
clipRect . clip ( it - > planeClipRect ) ;
2010-07-22 19:20:26 +00:00
translatedClipRect = clipRect ;
2010-09-19 14:50:28 +00:00
translatedClipRect . translate ( it - > planeRect . left , it - > planeRect . top ) ;
2010-06-30 14:26:47 +00:00
}
2010-02-04 16:12:47 +00:00
2011-10-29 01:39:37 +03:00
if ( view ) {
if ( ! clipRect . isEmpty ( ) ) {
if ( ( itemEntry - > scaleX = = 128 ) & & ( itemEntry - > scaleY = = 128 ) )
2012-09-26 04:17:31 +02:00
view - > draw ( itemEntry - > celRect , clipRect , translatedClipRect ,
2011-10-29 01:39:37 +03:00
itemEntry - > loopNo , itemEntry - > celNo , 255 , 0 , view - > isSci2Hires ( ) ) ;
else
2012-09-26 04:17:31 +02:00
view - > drawScaled ( itemEntry - > celRect , clipRect , translatedClipRect ,
2011-10-29 01:39:37 +03:00
itemEntry - > loopNo , itemEntry - > celNo , 255 , itemEntry - > scaleX , itemEntry - > scaleY ) ;
}
2010-07-22 19:20:26 +00:00
}
2011-10-28 22:04:27 +03:00
2011-10-29 01:39:37 +03:00
// Draw text, if it exists
2010-07-02 08:55:12 +00:00
if ( lookupSelector ( _segMan , itemEntry - > object , SELECTOR ( text ) , NULL , NULL ) = = kSelectorVariable ) {
2011-10-29 01:39:37 +03:00
g_sci - > _gfxText32 - > drawTextBitmap ( itemEntry - > x , itemEntry - > y , it - > planeRect , itemEntry - > object ) ;
2010-02-03 01:36:53 +00:00
}
2010-02-02 16:25:35 +00:00
}
}
2010-06-20 17:17:46 +00:00
2010-07-26 14:41:19 +00:00
for ( PlanePictureList : : iterator pictureIt = _planePictures . begin ( ) ; pictureIt ! = _planePictures . end ( ) ; pictureIt + + ) {
if ( pictureIt - > object = = planeObject ) {
delete [ ] pictureIt - > pictureCels ;
2010-12-22 13:52:25 +00:00
pictureIt - > pictureCels = 0 ;
2010-07-26 14:41:19 +00:00
}
2010-02-02 16:25:35 +00:00
}
}
2010-06-20 17:17:46 +00:00
2012-06-07 11:26:32 +03:00
showCurrentScrollText ( ) ;
2010-02-05 16:03:14 +00:00
_screen - > copyToScreen ( ) ;
2010-07-24 16:52:08 +00:00
2010-07-29 01:05:11 +00:00
g_sci - > getEngineState ( ) - > _throttleTrigger = true ;
2010-02-02 16:25:35 +00:00
}
2012-05-21 01:29:30 +03:00
void GfxFrameout : : printPlaneList ( Console * con ) {
for ( PlaneList : : const_iterator it = _planes . begin ( ) ; it ! = _planes . end ( ) ; + + it ) {
PlaneEntry p = * it ;
Common : : String curPlaneName = _segMan - > getObjectName ( p . object ) ;
Common : : Rect r = p . upscaledPlaneRect ;
Common : : Rect cr = p . upscaledPlaneClipRect ;
2014-05-27 02:04:07 +02:00
con - > debugPrintf ( " %04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d \n " ,
2012-05-21 01:29:30 +03:00
PRINT_REG ( p . object ) , curPlaneName . c_str ( ) ,
( int16 ) p . priority , ( int16 ) p . lastPriority ,
p . planeOffsetX , p . planeOffsetY , p . pictureId ,
p . planePictureMirrored , p . planeBack ) ;
2014-05-27 02:04:07 +02:00
con - > debugPrintf ( " rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d) \n " ,
2012-05-21 01:29:30 +03:00
r . left , r . top , r . right , r . bottom ,
cr . left , cr . top , cr . right , cr . bottom ) ;
if ( p . pictureId ! = 0xffff & & p . pictureId ! = 0xfffe ) {
2014-05-27 02:04:07 +02:00
con - > debugPrintf ( " Pictures: \n " ) ;
2012-05-21 01:29:30 +03:00
for ( PlanePictureList : : iterator pictureIt = _planePictures . begin ( ) ; pictureIt ! = _planePictures . end ( ) ; pictureIt + + ) {
if ( pictureIt - > object = = p . object ) {
2014-05-27 02:04:07 +02:00
con - > debugPrintf ( " Picture %d: x %d, y %d \n " , pictureIt - > pictureId , pictureIt - > startX , pictureIt - > startY ) ;
2012-05-21 01:29:30 +03:00
}
}
}
}
}
void GfxFrameout : : printPlaneItemList ( Console * con , reg_t planeObject ) {
for ( FrameoutList : : iterator listIterator = _screenItems . begin ( ) ; listIterator ! = _screenItems . end ( ) ; listIterator + + ) {
FrameoutEntry * e = * listIterator ;
reg_t itemPlane = readSelector ( _segMan , e - > object , SELECTOR ( plane ) ) ;
2012-09-26 04:17:31 +02:00
2012-05-21 01:29:30 +03:00
if ( planeObject = = itemPlane ) {
Common : : String curItemName = _segMan - > getObjectName ( e - > object ) ;
Common : : Rect icr = e - > celRect ;
GuiResourceId picId = e - > picture ? e - > picture - > getResourceId ( ) : 0 ;
2014-05-27 02:04:07 +02:00
con - > debugPrintf ( " %d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, "
2012-05-21 01:29:30 +03:00
" signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), "
" pic %d, picX %d, picY %d, visible %d \n " ,
e - > givenOrderNr , PRINT_REG ( e - > object ) , curItemName . c_str ( ) ,
e - > viewId , e - > loopNo , e - > celNo , e - > x , e - > y , e - > z ,
e - > signal , e - > scaleSignal , e - > scaleX , e - > scaleY ,
icr . left , icr . top , icr . right , icr . bottom ,
picId , e - > picStartX , e - > picStartY , e - > visible ) ;
}
}
}
2011-10-28 22:18:10 +03:00
} // End of namespace Sci