DIRECTOR: Add matte intersect/within checks

This commit is contained in:
Nathanael Gentry 2020-07-22 14:19:15 -04:00
parent 4dd7fb4c73
commit 45cd97c1c4
3 changed files with 67 additions and 3 deletions

View File

@ -166,8 +166,61 @@ bool Channel::isMouseIn(const Common::Point &pos) {
return true;
}
Common::Rect Channel::getBbox(bool unstretched) {
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();
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) {
Common::Rect result(unstretched ? _sprite->_width : _width,
unstretched ? _sprite->_height : _height);
result.moveTo(getPosition());

View File

@ -46,6 +46,8 @@ public:
bool isEmpty();
bool isActiveText();
bool isMouseIn(const Common::Point &pos);
bool isMatteIntersect(Channel *channel);
bool isMatteWithin(Channel *channel);
void setWidth(int w);
void setHeight(int h);

View File

@ -46,6 +46,7 @@
#include "director/director.h"
#include "director/movie.h"
#include "director/score.h"
#include "director/sprite.h"
#include "director/cursor.h"
#include "director/channel.h"
#include "director/util.h"
@ -903,7 +904,11 @@ void LC::c_intersects() {
return;
}
g_lingo->push(Datum(sprite1->getBbox().intersects(sprite2->getBbox())));
if (sprite1->_sprite->_ink == kInkTypeMatte && sprite2->_sprite->_ink == kInkTypeMatte) {
g_lingo->push(Datum(sprite2->isMatteIntersect(sprite1)));
} else {
g_lingo->push(Datum(sprite2->getBbox().intersects(sprite1->getBbox())));
}
}
void LC::c_within() {
@ -919,7 +924,11 @@ void LC::c_within() {
return;
}
g_lingo->push(Datum(sprite2->getBbox().contains(sprite1->getBbox())));
if (sprite1->_sprite->_ink == kInkTypeMatte && sprite2->_sprite->_ink == kInkTypeMatte) {
g_lingo->push(Datum(sprite2->isMatteWithin(sprite1)));
} else {
g_lingo->push(Datum(sprite1->getBbox().contains(sprite2->getBbox())));
}
}
void LC::c_of() {