2020-07-08 13:27:41 -04: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.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "director/director.h"
|
|
|
|
#include "director/movie.h"
|
|
|
|
#include "director/score.h"
|
2020-07-17 23:27:52 -04:00
|
|
|
#include "director/cursor.h"
|
2020-07-08 13:27:41 -04:00
|
|
|
#include "director/channel.h"
|
|
|
|
#include "director/sprite.h"
|
|
|
|
#include "director/castmember.h"
|
|
|
|
|
|
|
|
#include "graphics/macgui/mactext.h"
|
|
|
|
|
|
|
|
namespace Director {
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
Channel::Channel(Sprite *sp, int priority) {
|
2020-07-08 13:27:41 -04:00
|
|
|
_sprite = sp;
|
2020-07-26 04:32:29 +00:00
|
|
|
_widget = nullptr;
|
2020-07-08 13:27:41 -04:00
|
|
|
_currentPoint = sp->_startPoint;
|
|
|
|
_delta = Common::Point(0, 0);
|
|
|
|
_constraint = 0;
|
2020-07-26 04:32:29 +00:00
|
|
|
_mask = nullptr;
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
_priority = priority;
|
2020-07-15 11:40:10 -04:00
|
|
|
_width = _sprite->_width;
|
|
|
|
_height = _sprite->_height;
|
2020-07-09 19:06:30 -04:00
|
|
|
|
2020-08-01 23:14:37 +08:00
|
|
|
_movieRate = 0;
|
|
|
|
_movieTime = 0;
|
|
|
|
_startTime = 0;
|
|
|
|
_stopTime = 0;
|
|
|
|
|
2020-07-08 13:27:41 -04:00
|
|
|
_visible = true;
|
|
|
|
_dirty = true;
|
|
|
|
|
|
|
|
_sprite->updateCast();
|
|
|
|
}
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
Channel::~Channel() {
|
|
|
|
if (_widget)
|
|
|
|
delete _widget;
|
|
|
|
if (_mask)
|
|
|
|
delete _mask;
|
|
|
|
}
|
|
|
|
|
2020-07-09 11:08:15 -04:00
|
|
|
DirectorPlotData Channel::getPlotData() {
|
2020-07-29 00:11:28 -04:00
|
|
|
DirectorPlotData pd(g_director->_wm, _sprite->_spriteType, _sprite->_ink, _sprite->_blend, getBackColor(), getForeColor());
|
2020-07-09 15:33:03 -04:00
|
|
|
pd.colorWhite = pd._wm->_colorWhite;
|
|
|
|
pd.colorBlack = pd._wm->_colorBlack;
|
2020-07-13 11:19:07 +02:00
|
|
|
pd.dst = nullptr;
|
2020-07-09 11:08:15 -04:00
|
|
|
|
2020-07-09 15:33:03 -04:00
|
|
|
pd.srf = getSurface();
|
2020-08-10 11:59:06 -04:00
|
|
|
if (!pd.srf && _sprite->_spriteType != kBitmapSprite) {
|
2020-07-09 15:33:03 -04:00
|
|
|
// Shapes come colourized from macDrawPixel
|
|
|
|
pd.ms = getShape();
|
|
|
|
pd.applyColor = false;
|
2020-07-09 11:08:15 -04:00
|
|
|
} else {
|
2020-07-09 15:33:03 -04:00
|
|
|
pd.setApplyColor();
|
2020-07-09 11:08:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return pd;
|
|
|
|
}
|
|
|
|
|
2020-07-08 13:27:41 -04:00
|
|
|
Graphics::ManagedSurface *Channel::getSurface() {
|
2020-07-26 04:32:29 +00:00
|
|
|
if (_widget) {
|
|
|
|
return _widget->getSurface();
|
2020-07-08 13:27:41 -04:00
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const Graphics::Surface *Channel::getMask(bool forceMatte) {
|
2020-07-09 09:29:57 -04:00
|
|
|
if (!_sprite->_cast || _sprite->_spriteType == kTextSprite)
|
2020-07-08 13:27:41 -04:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
bool needsMatte = _sprite->_ink == kInkTypeMatte ||
|
|
|
|
_sprite->_ink == kInkTypeNotCopy ||
|
|
|
|
_sprite->_ink == kInkTypeNotTrans ||
|
|
|
|
_sprite->_ink == kInkTypeNotReverse ||
|
2020-07-29 00:11:28 -04:00
|
|
|
_sprite->_ink == kInkTypeNotGhost ||
|
|
|
|
_sprite->_blend > 0;
|
2020-07-08 13:27:41 -04:00
|
|
|
|
|
|
|
if (needsMatte || forceMatte) {
|
|
|
|
// Mattes are only supported in bitmaps for now. Shapes don't need mattes,
|
|
|
|
// as they already have all non-enclosed white pixels transparent.
|
|
|
|
// Matte on text has a trivial enough effect to not worry about implementing.
|
|
|
|
if (_sprite->_cast->_type == kCastBitmap) {
|
|
|
|
return ((BitmapCastMember *)_sprite->_cast)->getMatte();
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
} else if (_sprite->_ink == kInkTypeMask) {
|
|
|
|
CastMember *member = g_director->getCurrentMovie()->getCastMember(_sprite->_castId + 1);
|
|
|
|
|
|
|
|
if (member && member->_initialRect == _sprite->_cast->_initialRect) {
|
2020-07-26 04:32:29 +00:00
|
|
|
Common::Rect bbox(getBbox());
|
2020-08-12 13:54:01 +02:00
|
|
|
Graphics::MacWidget *widget = member->createWidget(bbox, this);
|
2020-07-26 04:32:29 +00:00
|
|
|
if (_mask)
|
|
|
|
delete _mask;
|
|
|
|
_mask = new Graphics::ManagedSurface();
|
|
|
|
_mask->copyFrom(*widget->getSurface());
|
|
|
|
delete widget;
|
|
|
|
return &_mask->rawSurface();
|
2020-07-08 13:27:41 -04:00
|
|
|
} else {
|
|
|
|
warning("Channel::getMask(): Requested cast mask, but no matching mask was found");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Channel::isDirty(Sprite *nextSprite) {
|
|
|
|
// When a sprite is puppeted setTheSprite ensures that the dirty flag here is
|
|
|
|
// set. Otherwise, we need to rerender when the position, bounding box, or
|
|
|
|
// cast of the sprite changes.
|
2020-07-09 23:56:08 -04:00
|
|
|
if (!nextSprite)
|
|
|
|
return false;
|
|
|
|
|
2020-07-08 13:27:41 -04:00
|
|
|
bool isDirty = _dirty ||
|
|
|
|
_delta != Common::Point(0, 0) ||
|
|
|
|
(_sprite->_cast && _sprite->_cast->isModified());
|
|
|
|
|
2020-07-09 23:56:08 -04:00
|
|
|
if (!_sprite->_puppet) {
|
2020-07-21 20:19:32 -04:00
|
|
|
// When puppet is set, the overall dirty flag should be set when sprite is
|
|
|
|
// modified.
|
|
|
|
isDirty |= _sprite->_castId != nextSprite->_castId ||
|
|
|
|
_sprite->_ink != nextSprite->_ink;
|
2020-07-09 23:56:08 -04:00
|
|
|
if (!_sprite->_moveable)
|
|
|
|
isDirty |= _currentPoint != nextSprite->_startPoint;
|
|
|
|
if (!_sprite->_stretch)
|
|
|
|
isDirty |= _width != nextSprite->_width || _height != nextSprite->_height;
|
2020-07-08 13:27:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return isDirty;
|
|
|
|
}
|
|
|
|
|
2020-07-09 19:12:33 -04:00
|
|
|
bool Channel::isStretched() {
|
|
|
|
return _sprite->_puppet && _sprite->_stretch &&
|
|
|
|
(_sprite->_width != _width || _sprite->_height != _height);
|
|
|
|
}
|
|
|
|
|
2020-07-14 09:28:19 -04:00
|
|
|
bool Channel::isEmpty() {
|
|
|
|
return (_sprite->_spriteType == kInactiveSprite);
|
|
|
|
}
|
|
|
|
|
2020-07-19 17:04:59 +02:00
|
|
|
bool Channel::isActiveText() {
|
|
|
|
if (_sprite->_spriteType != kTextSprite)
|
|
|
|
return false;
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
if (_widget && _widget->hasAllFocus())
|
2020-07-19 17:04:59 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-21 23:08:53 -04:00
|
|
|
bool Channel::isMouseIn(const Common::Point &pos) {
|
2020-07-21 15:05:52 -04:00
|
|
|
Common::Rect bbox = getBbox();
|
|
|
|
|
|
|
|
if (!bbox.contains(pos))
|
|
|
|
return false;
|
|
|
|
|
2020-07-21 23:08:53 -04:00
|
|
|
if (_sprite->_ink == kInkTypeMatte) {
|
2020-07-21 16:21:56 -04:00
|
|
|
if (_sprite->_cast && _sprite->_cast->_type == kCastBitmap) {
|
2020-07-21 15:05:52 -04:00
|
|
|
Graphics::Surface *matte = ((BitmapCastMember *)_sprite->_cast)->getMatte();
|
|
|
|
return matte ? !(*(byte *)(matte->getBasePtr(pos.x - bbox.left, pos.y - bbox.top))) : true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-07-22 14:19:15 -04:00
|
|
|
bool Channel::isMatteIntersect(Channel *channel) {
|
|
|
|
Common::Rect myBbox = getBbox();
|
|
|
|
Common::Rect yourBbox = channel->getBbox();
|
|
|
|
Common::Rect intersectRect = myBbox.findIntersectingRect(yourBbox);
|
|
|
|
|
|
|
|
if (intersectRect.isEmpty() || !_sprite->_cast || _sprite->_cast->_type != kCastBitmap ||
|
|
|
|
!channel->_sprite->_cast || channel->_sprite->_cast->_type != kCastBitmap)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Graphics::Surface *myMatte = ((BitmapCastMember *)_sprite->_cast)->getMatte();
|
|
|
|
Graphics::Surface *yourMatte = ((BitmapCastMember *)channel->_sprite->_cast)->getMatte();
|
2020-07-09 22:45:58 -04:00
|
|
|
|
2020-07-22 14:19:15 -04:00
|
|
|
if (myMatte && yourMatte) {
|
|
|
|
for (int i = intersectRect.top; i < intersectRect.bottom; i++) {
|
|
|
|
const byte *my = (const byte *)myMatte->getBasePtr(intersectRect.left - myBbox.left, i - myBbox.top);
|
|
|
|
const byte *your = (const byte *)yourMatte->getBasePtr(intersectRect.left - yourBbox.left, i - yourBbox.top);
|
|
|
|
|
|
|
|
for (int j = intersectRect.left; j < intersectRect.right; j++, my++, your++)
|
|
|
|
if (!*my && !*your)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Channel::isMatteWithin(Channel *channel) {
|
|
|
|
Common::Rect myBbox = getBbox();
|
|
|
|
Common::Rect yourBbox = channel->getBbox();
|
|
|
|
Common::Rect intersectRect = myBbox.findIntersectingRect(yourBbox);
|
|
|
|
|
|
|
|
if (!myBbox.contains(yourBbox) || !_sprite->_cast || _sprite->_cast->_type != kCastBitmap ||
|
|
|
|
!channel->_sprite->_cast || channel->_sprite->_cast->_type != kCastBitmap)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Graphics::Surface *myMatte = ((BitmapCastMember *)_sprite->_cast)->getMatte();
|
|
|
|
Graphics::Surface *yourMatte = ((BitmapCastMember *)channel->_sprite->_cast)->getMatte();
|
|
|
|
|
|
|
|
if (myMatte && yourMatte) {
|
|
|
|
for (int i = intersectRect.top; i < intersectRect.bottom; i++) {
|
|
|
|
const byte *my = (const byte *)myMatte->getBasePtr(intersectRect.left - myBbox.left, i - myBbox.top);
|
|
|
|
const byte *your = (const byte *)yourMatte->getBasePtr(intersectRect.left - yourBbox.left, i - yourBbox.top);
|
|
|
|
|
|
|
|
for (int j = intersectRect.left; j < intersectRect.right; j++, my++, your++)
|
|
|
|
if (*my && !*your)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Rect Channel::getBbox(bool unstretched) {
|
2020-07-09 22:45:58 -04:00
|
|
|
Common::Rect result(unstretched ? _sprite->_width : _width,
|
|
|
|
unstretched ? _sprite->_height : _height);
|
2020-07-09 19:06:30 -04:00
|
|
|
result.moveTo(getPosition());
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-07-09 19:06:30 -04:00
|
|
|
return result;
|
2020-07-08 13:27:41 -04:00
|
|
|
}
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
void Channel::setCast(uint16 castId) {
|
|
|
|
_sprite->setCast(castId);
|
|
|
|
_width = _sprite->_width;
|
|
|
|
_height = _sprite->_height;
|
|
|
|
replaceWidget();
|
|
|
|
}
|
|
|
|
|
2020-07-16 18:19:25 -04:00
|
|
|
void Channel::setClean(Sprite *nextSprite, int spriteId, bool partial) {
|
2020-07-08 13:27:41 -04:00
|
|
|
if (!nextSprite)
|
|
|
|
return;
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
bool replace = isDirty(nextSprite);
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-07-16 18:19:25 -04:00
|
|
|
if (nextSprite) {
|
2020-07-27 16:28:47 -04:00
|
|
|
if (_sprite->_puppet || partial) {
|
|
|
|
// Updating scripts, etc. does not require a full re-render
|
|
|
|
_sprite->_scriptId = nextSprite->_scriptId;
|
|
|
|
} else {
|
2020-07-29 12:39:37 -04:00
|
|
|
replaceSprite(nextSprite);
|
2020-07-09 19:06:30 -04:00
|
|
|
}
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-07-16 18:19:25 -04:00
|
|
|
_currentPoint += _delta;
|
|
|
|
_delta = Common::Point(0, 0);
|
|
|
|
}
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
if (replace) {
|
2020-07-16 18:19:25 -04:00
|
|
|
_sprite->updateCast();
|
2020-07-26 04:32:29 +00:00
|
|
|
replaceWidget();
|
2020-07-08 13:27:41 -04:00
|
|
|
}
|
2020-07-26 04:32:29 +00:00
|
|
|
_dirty = false;
|
2020-07-08 13:27:41 -04:00
|
|
|
}
|
|
|
|
|
2020-07-29 12:39:37 -04:00
|
|
|
void Channel::replaceSprite(Sprite *nextSprite) {
|
|
|
|
if (!nextSprite)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool newSprite = (_sprite->_spriteType == kInactiveSprite && nextSprite->_spriteType != kInactiveSprite);
|
|
|
|
_sprite = nextSprite;
|
|
|
|
|
|
|
|
// Sprites marked moveable are constrained to the same bounding box until
|
|
|
|
// the moveable is disabled
|
2020-07-31 10:37:05 -04:00
|
|
|
if (!_sprite->_moveable || newSprite)
|
2020-07-29 12:39:37 -04:00
|
|
|
_currentPoint = _sprite->_startPoint;
|
|
|
|
|
2020-07-31 10:37:05 -04:00
|
|
|
if (!_sprite->_stretch) {
|
|
|
|
_width = _sprite->_width;
|
|
|
|
_height = _sprite->_height;
|
2020-07-29 12:39:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-09 22:45:58 -04:00
|
|
|
void Channel::setWidth(int w) {
|
|
|
|
if (_sprite->_puppet && _sprite->_stretch) {
|
|
|
|
_width = w;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Channel::setHeight(int h) {
|
|
|
|
if (_sprite->_puppet && _sprite->_stretch) {
|
|
|
|
_height = h;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-09 23:27:05 -04:00
|
|
|
void Channel::setBbox(int l, int t, int r, int b) {
|
|
|
|
if (_sprite->_puppet && _sprite->_stretch) {
|
|
|
|
_width = r - l;
|
|
|
|
_height = b - t;
|
|
|
|
|
|
|
|
_currentPoint.x = l;
|
|
|
|
_currentPoint.y = t;
|
|
|
|
|
|
|
|
addRegistrationOffset(_currentPoint, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-26 04:32:29 +00:00
|
|
|
void Channel::replaceWidget() {
|
|
|
|
if (_widget) {
|
|
|
|
delete _widget;
|
|
|
|
_widget = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_sprite && _sprite->_cast) {
|
|
|
|
Common::Rect bbox(getBbox());
|
|
|
|
_sprite->_cast->_modified = false;
|
|
|
|
|
2020-08-12 13:54:01 +02:00
|
|
|
_widget = _sprite->_cast->createWidget(bbox, this);
|
2020-07-26 04:32:29 +00:00
|
|
|
if (_widget) {
|
|
|
|
_widget->_priority = _priority;
|
|
|
|
_widget->draw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Channel::updateWidget() {
|
2020-08-07 10:07:32 +02:00
|
|
|
if (_widget && _widget->needsRedraw()) {
|
2020-07-26 04:32:29 +00:00
|
|
|
if (_sprite->_cast) {
|
|
|
|
_sprite->_cast->updateFromWidget(_widget);
|
|
|
|
}
|
|
|
|
_widget->draw();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-09 23:27:05 -04:00
|
|
|
void Channel::addRegistrationOffset(Common::Point &pos, bool subtract) {
|
2020-08-14 00:42:00 +02:00
|
|
|
if (!_sprite->_cast)
|
|
|
|
return;
|
2020-07-08 13:27:41 -04:00
|
|
|
|
2020-08-14 00:42:00 +02:00
|
|
|
switch (_sprite->_cast->_type) {
|
|
|
|
case kCastBitmap:
|
|
|
|
{
|
|
|
|
BitmapCastMember *bc = (BitmapCastMember *)(_sprite->_cast);
|
|
|
|
|
|
|
|
if (subtract)
|
|
|
|
pos -= Common::Point(bc->_initialRect.left - bc->_regX,
|
|
|
|
bc->_initialRect.top - bc->_regY);
|
|
|
|
else
|
|
|
|
pos += Common::Point(bc->_initialRect.left - bc->_regX,
|
|
|
|
bc->_initialRect.top - bc->_regY);
|
2020-07-09 23:27:05 -04:00
|
|
|
}
|
2020-08-14 00:42:00 +02:00
|
|
|
break;
|
|
|
|
case kCastDigitalVideo:
|
|
|
|
pos -= Common::Point(_sprite->_cast->_initialRect.width() >> 1, _sprite->_cast->_initialRect.height() >> 1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2020-07-08 13:27:41 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Channel::addDelta(Common::Point pos) {
|
|
|
|
// TODO: Channel should have a pointer to its score
|
|
|
|
if (_sprite->_moveable &&
|
|
|
|
_constraint > 0 &&
|
|
|
|
_constraint < g_director->getCurrentMovie()->getScore()->_channels.size()) {
|
|
|
|
Common::Rect constraintBbox = g_director->getCurrentMovie()->getScore()->_channels[_constraint]->getBbox();
|
|
|
|
|
|
|
|
Common::Rect currentBbox = getBbox();
|
|
|
|
currentBbox.translate(_delta.x + pos.x, _delta.y + pos.y);
|
|
|
|
|
|
|
|
Common::Point regPoint;
|
|
|
|
addRegistrationOffset(regPoint);
|
|
|
|
|
|
|
|
constraintBbox.top += regPoint.y;
|
|
|
|
constraintBbox.bottom -= regPoint.y;
|
|
|
|
|
|
|
|
constraintBbox.left += regPoint.x;
|
|
|
|
constraintBbox.right -= regPoint.x;
|
|
|
|
|
|
|
|
if (!constraintBbox.contains(currentBbox)) {
|
|
|
|
if (currentBbox.top < constraintBbox.top) {
|
|
|
|
pos.y += constraintBbox.top - currentBbox.top;
|
|
|
|
} else if (currentBbox.bottom > constraintBbox.bottom) {
|
|
|
|
pos.y += constraintBbox.bottom - currentBbox.bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentBbox.left < constraintBbox.left) {
|
|
|
|
pos.x += constraintBbox.left - currentBbox.left;
|
|
|
|
} else if (currentBbox.right > constraintBbox.right) {
|
|
|
|
pos.x += constraintBbox.right - currentBbox.right;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_delta += pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::Point Channel::getPosition() {
|
|
|
|
Common::Point res = _currentPoint;
|
|
|
|
addRegistrationOffset(res);
|
2020-07-24 10:25:27 -04:00
|
|
|
|
|
|
|
res.x += (_sprite->_width - _width) / 2;
|
|
|
|
res.y += (_sprite->_height - _height) / 2;
|
|
|
|
|
2020-07-08 13:27:41 -04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
MacShape *Channel::getShape() {
|
2020-07-09 09:29:57 -04:00
|
|
|
if (!_sprite->isQDShape() && (_sprite->_cast && _sprite->_cast->_type != kCastShape))
|
2020-07-08 13:27:41 -04:00
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
MacShape *shape = new MacShape();
|
|
|
|
|
|
|
|
shape->ink = _sprite->_ink;
|
|
|
|
shape->spriteType = _sprite->_spriteType;
|
|
|
|
shape->foreColor = _sprite->_foreColor;
|
|
|
|
shape->backColor = _sprite->_backColor;
|
|
|
|
shape->lineSize = _sprite->_thickness & 0x3;
|
|
|
|
shape->pattern = _sprite->getPattern();
|
|
|
|
|
2020-08-10 13:32:24 -04:00
|
|
|
if (g_director->getVersion() >= 300 && shape->spriteType == kCastMemberSprite) {
|
2020-07-08 13:27:41 -04:00
|
|
|
if (!_sprite->_cast) {
|
|
|
|
warning("Channel::getShape(): kCastMemberSprite has no cast defined");
|
|
|
|
delete shape;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ShapeCastMember *sc = (ShapeCastMember *)_sprite->_cast;
|
|
|
|
switch (sc->_shapeType) {
|
|
|
|
case kShapeRectangle:
|
|
|
|
shape->spriteType = sc->_fillType ? kRectangleSprite : kOutlinedRectangleSprite;
|
|
|
|
break;
|
|
|
|
case kShapeRoundRect:
|
|
|
|
shape->spriteType = sc->_fillType ? kRoundedRectangleSprite : kOutlinedRoundedRectangleSprite;
|
|
|
|
break;
|
|
|
|
case kShapeOval:
|
|
|
|
shape->spriteType = sc->_fillType ? kOvalSprite : kOutlinedOvalSprite;
|
|
|
|
break;
|
|
|
|
case kShapeLine:
|
|
|
|
shape->spriteType = sc->_lineDirection == 6 ? kLineBottomTopSprite : kLineTopBottomSprite;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-08-10 13:32:24 -04:00
|
|
|
if (g_director->getVersion() >= 400) {
|
2020-07-08 15:44:40 -04:00
|
|
|
shape->foreColor = sc->getForeColor();
|
|
|
|
shape->backColor = sc->getBackColor();
|
2020-07-08 13:27:41 -04:00
|
|
|
shape->lineSize = sc->_lineThickness;
|
|
|
|
shape->ink = sc->_ink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// for outlined shapes, line thickness of 1 means invisible.
|
|
|
|
shape->lineSize -= 1;
|
|
|
|
|
|
|
|
return shape;
|
|
|
|
}
|
|
|
|
|
2020-07-09 08:45:55 -04:00
|
|
|
uint Channel::getBackColor() {
|
|
|
|
if (!_sprite->_cast)
|
|
|
|
return _sprite->_backColor;
|
|
|
|
|
|
|
|
switch (_sprite->_cast->_type) {
|
|
|
|
case kCastText:
|
|
|
|
case kCastButton:
|
|
|
|
case kCastShape: {
|
|
|
|
return _sprite->_cast->getBackColor();
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return _sprite->_backColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint Channel::getForeColor() {
|
|
|
|
if (!_sprite->_cast)
|
|
|
|
return _sprite->_foreColor;
|
|
|
|
|
|
|
|
switch (_sprite->_cast->_type) {
|
|
|
|
case kCastText:
|
|
|
|
case kCastButton:
|
|
|
|
case kCastShape: {
|
|
|
|
return _sprite->_cast->getForeColor();
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return _sprite->_foreColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-08 13:27:41 -04:00
|
|
|
} // End of namespace Director
|