scummvm/engines/sci/graphics/screen_item32.h
Colin Snover 0ac5d84062 SCI32: Clean up ScreenItem
* Rewrap comments to 80 columns
* Clarify comments where possible
* Use smart pointers where appropriate
2017-10-06 22:10:50 -05:00

372 lines
10 KiB
C++

/* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SCI_GRAPHICS_SCREEN_ITEM32_H
#define SCI_GRAPHICS_SCREEN_ITEM32_H
#include "common/rect.h"
#include "sci/graphics/celobj32.h"
#include "sci/graphics/lists32.h"
namespace Sci {
enum ScaleSignals32 {
kScaleSignalNone = 0,
kScaleSignalManual = 1,
kScaleSignalVanishingPoint = 2
};
struct ScaleInfo {
int x, y, max;
ScaleSignals32 signal;
ScaleInfo() : x(128), y(128), max(100), signal(kScaleSignalNone) {}
};
class CelObj;
class Plane;
class SegManager;
#pragma mark -
#pragma mark ScreenItem
/**
* A ScreenItem is the engine-side representation of a game script View.
*/
class ScreenItem {
private:
/**
* A serial used for screen items that are generated inside the graphics
* engine, rather than the interpreter.
*/
static uint16 _nextObjectId;
/**
* A serial used to identify the creation order of screen items, to ensure a
* stable sort order for screen items with identical priorities and
* z-indexes.
*/
static uint32 _nextCreationId;
public:
/**
* The parent plane of this screen item.
*/
reg_t _plane;
/**
* Scaling data used to calculate the final screen dimensions of the screen
* item as well as the scaling ratios used when drawing the item to screen.
*/
ScaleInfo _scale;
private:
/**
* The position & dimensions of the screen item in screen coordinates. This
* rect includes the offset of the parent plane, but is not clipped to the
* screen, so may include coordinates that are offscreen.
*/
Common::Rect _screenItemRect;
/**
* If true, the `_insetRect` rectangle will be used when calculating the
* dimensions of the screen item instead of the cel's intrinsic width and
* height.
*
* In other words, using an inset rect means that the cel is cropped to the
* dimensions given in `_insetRect`.
*/
bool _useInsetRect;
/**
* The cropping rectangle used when `_useInsetRect` is true.
*
* `_insetRect` is also used to describe the fill rectangle of a screen item
* with a CelObjColor cel.
*/
Common::Rect _insetRect;
/**
* The z-index of the screen item in pseudo-3D space. Higher values are
* drawn on top of lower values.
*/
int _z;
/**
* Sets the common properties of a screen item that must be set both during
* creation and update of a screen item.
*/
void setFromObject(SegManager *segMan, const reg_t object, const bool updateCel, const bool updateBitmap);
public:
/**
* The creation order number, which ensures a stable sort when screen items
* with identical priorities and z-indexes are added to the screen item
* list.
*/
uint32 _creationId;
/**
* A descriptor for the cel object represented by the screen item.
*/
CelInfo32 _celInfo;
/**
* The cel object used to actually render the screen item. This member is
* populated by calling `getCelObj`.
*/
mutable Common::ScopedPtr<CelObj> _celObj;
/**
* If set, the priority for this screen item is fixed in place. Otherwise,
* the priority of the screen item is calculated from its y-position +
* z-index.
*/
bool _fixedPriority;
/**
* The rendering priority of the screen item, relative only to the other
* screen items within the same plane. Higher priorities are drawn above
* lower priorities.
*/
int16 _priority;
/**
* The top-left corner of the screen item, in game script coordinates,
* relative to the parent plane.
*/
Common::Point _position;
/**
* The associated View script object that was used to create the ScreenItem,
* or a numeric value in the case of a ScreenItem that was generated by the
* kernel.
*/
reg_t _object;
/**
* For screen items representing picture resources, the resource ID of the
* picture.
*/
GuiResourceId _pictureId;
/**
* Flags indicating the state of the screen item.
* - `created` is set when the screen item is first created, either from a
* VM object or from within the kernel
* - `updated` is set when `created` is not already set and the screen item
* is updated from a VM object
* - `deleted` is set by the parent plane, if the parent plane is a pic type
* and its picture resource ID has changed
*/
int _created, _updated, _deleted;
/**
* For screen items that represent picture cels, this value is set to match
* the `_mirrorX` property of the parent plane and indicates that the cel
* should be
* drawn horizontally mirrored. For final drawing, it is XORed with the
* `_mirrorX` property of the cel object. The cel object's `_mirrorX`
* property comes from the resource data.
*/
bool _mirrorX;
/**
* The scaling ratios to use when drawing this screen item. These values are
* calculated according to the scale info whenever the screen item is
* updated.
*/
Ratio _ratioX, _ratioY;
/**
* The top-left corner of the screen item, in screen coordinates.
*/
Common::Point _scaledPosition;
/**
* The position & dimensions of the screen item in screen coordinates. This
* rect includes the offset of the parent plane and is clipped to the
* screen.
*/
Common::Rect _screenRect;
/**
* Whether or not the screen item should be drawn with black lines drawn
* every second line. This is used when pixel doubling videos to improve
* apparent sharpness at the cost of your eyesight.
*/
bool _drawBlackLines;
/**
* Initialises static Plane members.
*/
static void init();
ScreenItem(const reg_t screenItem);
ScreenItem(const reg_t plane, const CelInfo32 &celInfo);
ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect);
ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo);
ScreenItem(const ScreenItem &other);
void operator=(const ScreenItem &);
inline bool operator<(const ScreenItem &other) const {
if (_priority < other._priority) {
return true;
}
if (_priority == other._priority) {
if (_position.y + _z < other._position.y + other._z) {
return true;
}
if (_position.y + _z == other._position.y + other._z) {
// Synthetic object IDs (numeric IDs) are used for screen items
// generated by the kernel, like the screen items generated by
// plane pics. In SSCI, these synthetic IDs started at 20000 so
// would deterministically always sort higher than any
// script-generated view in SSCI at the same position and
// priority.
if (other._object.isNumber() && !_object.isNumber()) {
return true;
}
// SSCI's last resort comparison here is to compare the _object
// IDs, but this is wrong and randomly breaks (at least):
//
// (1) the death dialog at the end of Phant1, where the ID of
// the text is often higher than the ID of the border;
// (2) text-based buttons and dialogues in Hoyle5, where the ID
// of the text is often lower than the ID of the
// button/dialogue background.
//
// This occurs because object IDs (in both ScummVM and SSCI) are
// reused, so objects created later may receive a lower ID,
// which makes them sort lower when the programmer intended them
// to sort higher.
//
// To fix this problem, we give each ScreenItem a monotonically
// increasing insertion ID at construction time, and compare
// these insertion IDs instead. They are more stable and cause
// objects with identical priority and z-index to be rendered in
// the order that they were created.
//
// This also applies to ScreenItem::hasPriorityAbove.
return _creationId < other._creationId;
}
}
return false;
}
inline bool operator>(const ScreenItem &other) const {
if (_priority > other._priority) {
return true;
}
if (_priority == other._priority) {
if (_position.y + _z > other._position.y + other._z) {
return true;
}
if (_position.y + _z == other._position.y + other._z) {
if (_object.isNumber() && !other._object.isNumber()) {
return true;
}
// This is different than SSCI; see ScreenItem::operator< for an
// explanation
return _creationId > other._creationId;
}
}
return false;
}
inline bool hasPriorityAbove(const ScreenItem &other) const {
if (_priority > other._priority) {
return true;
}
if (_priority == other._priority) {
if (_object.isNumber() && !other._object.isNumber()) {
return true;
}
// This is different than SSCI; see ScreenItem::operator< for an
// explanation
return _creationId > other._creationId;
}
return false;
}
/**
* Calculates the dimensions and scaling parameters for the screen item,
* using the given plane as the parent plane for screen rect positioning.
*
* @note This method was called Update in SSCI.
*/
void calcRects(const Plane &plane);
/**
* Retrieves the corresponding cel object for this screen item. If a cel
* object does not already exist, one will be created and assigned.
*/
CelObj &getCelObj() const;
void printDebugInfo(Console *con) const;
/**
* Updates the properties of the screen item from a VM object.
*/
void update(const reg_t object);
/**
* Updates the properties of the screen item for one not belonging to a VM
* object. Originally GraphicsMgr::UpdateScreenItem.
*/
void update();
/**
* Gets the "now seen" rect for the screen item, which represents the
* current size and position of the screen item on the screen in script
* coordinates.
*/
Common::Rect getNowSeenRect(const Plane &plane) const;
};
#pragma mark -
#pragma mark ScreenItemList
typedef StablePointerArray<ScreenItem, 250> ScreenItemListBase;
class ScreenItemList : public ScreenItemListBase {
private:
size_type _unsorted[250];
public:
ScreenItem *findByObject(const reg_t object) const;
void sort();
void unsort();
};
} // End of namespace Sci
#endif