SCUMM: HE: Relabel Polygon functions

This commit is contained in:
AndywinXp 2024-03-14 14:40:57 +01:00 committed by Eugene Sandulenko
parent 4bcfff35bd
commit 483ac31ced
6 changed files with 115 additions and 127 deletions

View File

@ -28,7 +28,7 @@
namespace Scumm {
void Wiz::polygonClear() {
void Wiz::deleteLocalPolygons() {
for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
if (_polygons[i].flag == 1)
_polygons[i].reset();
@ -56,11 +56,11 @@ void Wiz::polygonLoad(const uint8 *polData) {
vert4y = READ_LE_UINT32(polData + 36);
polData += 40;
polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
set4Polygon(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
}
}
void Wiz::polygonStore(int id, bool localFlag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y) {
void Wiz::set4Polygon(int id, bool localFlag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y) {
for (int i = 0; i < ARRAYSIZE(_polygons); ++i) {
if (_polygons[i].id == 0) {
_polygons[i].points[0].x = vert1x;
@ -83,7 +83,7 @@ void Wiz::polygonStore(int id, bool localFlag, int vert1x, int vert1y, int vert2
}
}
error("Wiz::polygonStore: out of polygon slot, max = %d", ARRAYSIZE(_polygons));
error("Wiz::set4Polygon: out of polygon slot, max = %d", ARRAYSIZE(_polygons));
}
void Wiz::polyRotatePoints(Common::Point *pts, int num, int angle) {
@ -99,42 +99,6 @@ void Wiz::polyRotatePoints(Common::Point *pts, int num, int angle) {
}
}
void Wiz::polygonTransform(int resNum, int state, int po_x, int po_y, int angle, int scale, Common::Point *pts) {
int32 w, h;
getWizImageDim(resNum, state, w, h);
// set the transformation origin to the center of the image
if (_vm->_game.heversion >= 99) {
pts[0].x = pts[3].x = -(w / 2);
pts[1].x = pts[2].x = w / 2 - 1;
pts[0].y = pts[1].y = -(h / 2);
pts[2].y = pts[3].y = h / 2 - 1;
} else {
pts[1].x = pts[2].x = w / 2 - 1;
pts[0].x = pts[0].y = pts[1].y = pts[3].x = -(w / 2);
pts[2].y = pts[3].y = h / 2 - 1;
}
// scale
if (scale != 0 && scale != 256) {
for (int i = 0; i < 4; ++i) {
pts[i].x = pts[i].x * scale / 256;
pts[i].y = pts[i].y * scale / 256;
}
}
// rotate
if (angle != 0)
polyRotatePoints(pts, 4, angle);
// translate
for (int i = 0; i < 4; ++i) {
pts[i].x += po_x;
pts[i].y += po_y;
}
}
void Wiz::polyMovePolygonPoints(Common::Point *listOfPoints, int numverts, int deltaX, int deltaY) {
for (int i = 0; i < numverts; i++) {
listOfPoints->x += deltaX;
@ -187,28 +151,51 @@ void Wiz::polyBuildBoundingRect(Common::Point *points, int numVerts, Common::Rec
}
}
void Wiz::polygonErase(int fromId, int toId) {
void Wiz::deletePolygon(int fromId, int toId) {
for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
if (_polygons[i].id >= fromId && _polygons[i].id <= toId)
_polygons[i].reset();
}
}
int Wiz::polygonTestForObjectHit(int id, int x, int y) {
int Wiz::findPolygon(int x, int y) {
Common::Point checkPoint((int16)x, (int16)y);
for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
if ((id == 0 || _polygons[i].id == id) && _polygons[i].boundingRect.contains(x, y)) {
if (isPointInRect(&_polygons[i].boundingRect, &checkPoint)) {
if (polyIsPointInsidePoly(_polygons[i], x, y)) {
return _polygons[i].id;
}
}
}
return 0;
}
int Wiz::testForObjectPolygon(int object, int x, int y) {
Common::Point checkPoint((int16)x, (int16)y);
if (object == 0)
return 0;
for (int i = 0; i < ARRAYSIZE(_polygons); i++) {
if (_polygons[i].id == object) {
if (isPointInRect(&_polygons[i].boundingRect, &checkPoint)) {
if (polyIsPointInsidePoly(_polygons[i], x, y)) {
return 1;
}
}
}
}
return 0;
}
bool Wiz::polygonDefined(int id) {
bool Wiz::doesObjectHavePolygon(int object) {
if (object == 0)
return false;
for (int i = 0; i < ARRAYSIZE(_polygons); i++)
if (_polygons[i].id == id)
if (_polygons[i].id == object)
return true;
return false;
}

View File

@ -418,13 +418,13 @@ void ScummEngine_v71he::o71_polygonOps() {
vert1x = pop();
flag = (subOp == ScummEngine_v100he::SO_SET_POLYGON_LOCAL || subOp == SO_SET_POLYGON_LOCAL);
id = pop();
_wiz->polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
_wiz->set4Polygon(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
break;
case ScummEngine_v100he::SO_DELETE_POLYGON: // HE 100
case SO_DELETE_POLYGON:
toId = pop();
fromId = pop();
_wiz->polygonErase(fromId, toId);
_wiz->deletePolygon(fromId, toId);
break;
default:
error("o71_polygonOps: default case %d", subOp);
@ -434,7 +434,7 @@ void ScummEngine_v71he::o71_polygonOps() {
void ScummEngine_v71he::o71_polygonHit() {
int y = pop();
int x = pop();
push(_wiz->polygonTestForObjectHit(0, x, y));
push(_wiz->findPolygon(x, y));
}
} // End of namespace Scumm

View File

@ -417,8 +417,8 @@ int ScummEngine_v72he::findObject(int x, int y, int num, int *args) {
continue;
// Check polygon bounds
if (_wiz->polygonDefined(_objs[i].obj_nr)) {
if (_wiz->polygonTestForObjectHit(_objs[i].obj_nr, x, y))
if (_wiz->doesObjectHavePolygon(_objs[i].obj_nr)) {
if (_wiz->testForObjectPolygon(_objs[i].obj_nr, x, y))
result = _objs[i].obj_nr;
else if (VAR_POLYGONS_ONLY != 0xFF && VAR(VAR_POLYGONS_ONLY))
continue;

View File

@ -1206,7 +1206,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
_sprite->setGroupMembersShadow(_curSpriteGroupId, value1);
break;
default:
error("o90_setSpriteGroupInfo subOp 0: Unknown case %d", subOp);
error("o90_setSpriteGroupInfo checkType 0: Unknown case %d", subOp);
}
break;
case SO_PROPERTY: // 42
@ -1229,7 +1229,7 @@ void ScummEngine_v90he::o90_setSpriteGroupInfo() {
_sprite->setGroupYDiv(_curSpriteGroupId, value1);
break;
default:
error("o90_setSpriteGroupInfo subOp 5: Unknown case %d", subOp);
error("o90_setSpriteGroupInfo checkType 5: Unknown case %d", subOp);
}
break;
case SO_PRIORITY: // 43
@ -1536,7 +1536,7 @@ void ScummEngine_v90he::o90_getVideoData() {
push(_moviePlay->getImageNum());
break;
case SO_NEW_GENERAL_PROPERTY: // 139
debug(0, "o90_getVideoData: subOp 107 stub (%d, %d)", pop(), pop());
debug(0, "o90_getVideoData: checkType 107 stub (%d, %d)", pop(), pop());
push(0);
break;
default:
@ -1637,71 +1637,72 @@ void ScummEngine_v90he::o90_findAllObjectsWithClassOf() {
}
void ScummEngine_v90he::o90_getPolygonOverlap() {
int args1[32];
int args2[32];
int lastList[32];
int firstList[32];
int n1 = getStackList(args1, ARRAYSIZE(args1));
int n2 = getStackList(args2, ARRAYSIZE(args2));
int lastCount = getStackList(lastList, ARRAYSIZE(lastList));
int firstCount = getStackList(firstList, ARRAYSIZE(firstList));
int subOp = pop();
int checkType = pop();
switch (subOp) {
switch (checkType) {
case OVERLAP_POINT_TO_RECT: // 1
{
Common::Rect r(args1[0], args1[1], args1[2] + 1, args1[3] + 1);
Common::Point p(args2[0], args2[1]);
push(r.contains(p) ? 1 : 0);
Common::Rect r(lastList[0], lastList[1], lastList[2], lastList[3]);
Common::Point p(firstList[0], firstList[1]);
push(_wiz->isPointInRect(&r, &p) ? 1 : 0);
}
break;
case OVERLAP_POINT_TO_CIRCLE: // 2
{
int dx = args2[0] - args1[0];
int dy = args2[1] - args1[1];
int dx = firstList[0] - lastList[0];
int dy = firstList[1] - lastList[1];
int dist = dx * dx + dy * dy;
if (dist >= 2) {
dist = (int)sqrt((double)(dist + 1));
}
if (_game.heversion >= 98) {
push((dist <= args1[2]) ? 1 : 0);
push((dist <= lastList[2]) ? 1 : 0);
} else {
push((dist > args1[2]) ? 1 : 0);
push((dist > lastList[2]) ? 1 : 0);
}
}
break;
case OVERLAP_RECT_TO_RECT: // 3
{
Common::Rect r1(args1[0], args1[1], args1[2] + 1, args1[3] + 1);
Common::Rect r2(args2[0], args2[1], args2[2] + 1, args2[3] + 1);
Common::Rect r1(lastList[0], lastList[1], lastList[2] + 1, lastList[3] + 1);
Common::Rect r2(firstList[0], firstList[1], firstList[2] + 1, firstList[3] + 1);
push(r2.intersects(r1) ? 1 : 0);
}
break;
case OVERLAP_CIRCLE_TO_CIRCLE: // 4
{
int dx = args2[0] - args1[0];
int dy = args2[1] - args1[1];
int dx = firstList[0] - lastList[0];
int dy = firstList[1] - lastList[1];
int dist = dx * dx + dy * dy;
if (dist >= 2) {
dist = (int)sqrt((double)(dist + 1));
}
push((dist < args1[2] && dist < args2[2]) ? 1 : 0);
push((dist < lastList[2] && dist < firstList[2]) ? 1 : 0);
}
break;
case OVERLAP_POINT_N_SIDED_POLYGON: // 5
{
assert((n1 & 1) == 0);
n1 /= 2;
if (n1 == 0) {
assert((lastCount & 1) == 0);
lastCount /= 2;
if (lastCount == 0) {
push(0);
} else {
WizPolygon wp;
wp.reset();
wp.numPoints = n1;
assert(n1 < ARRAYSIZE(wp.points));
for (int i = 0; i < n1; ++i) {
wp.points[i].x = args1[i * 2 + 0];
wp.points[i].y = args1[i * 2 + 1];
wp.numPoints = lastCount;
assert(lastCount < ARRAYSIZE(wp.points));
for (int i = 0; i < lastCount; ++i) {
wp.points[i].x = lastList[i * 2 + 0];
wp.points[i].y = lastList[i * 2 + 1];
}
push(_wiz->polyIsPointInsidePoly(wp, args2[0], args2[1]) ? 1 : 0);
push(_wiz->polyIsPointInsidePoly(wp, firstList[0], firstList[1]) ? 1 : 0);
}
}
break;
@ -1709,24 +1710,24 @@ void ScummEngine_v90he::o90_getPolygonOverlap() {
case OVERLAP_SPRITE_TO_SPRITE: // 6
{
Common::Rect r1, r2;
_sprite->getSpriteLogicalRect(args2[0], false, r2);
_sprite->getSpriteLogicalRect(args1[0], false, r1);
_sprite->getSpriteLogicalRect(firstList[0], false, r2);
_sprite->getSpriteLogicalRect(lastList[0], false, r1);
if (r2.isValidRect() == false) {
push(0);
break;
}
if (n2 == 3) {
r2.left += args2[1];
r2.right += args2[1];
r2.top += args2[2];
r2.bottom += args2[2];
if (firstCount == 3) {
r2.left += firstList[1];
r2.right += firstList[1];
r2.top += firstList[2];
r2.bottom += firstList[2];
}
if (n1 == 3) {
r1.left += args1[1];
r1.right += args1[1];
r1.top += args1[2];
r1.bottom += args1[2];
if (lastCount == 3) {
r1.left += lastList[1];
r1.right += lastList[1];
r1.top += lastList[2];
r1.bottom += lastList[2];
}
push(r2.intersects(r1) ? 1 : 0);
}
@ -1734,18 +1735,18 @@ void ScummEngine_v90he::o90_getPolygonOverlap() {
case OVERLAP_SPRITE_TO_RECT: // 7
{
Common::Rect r2;
_sprite->getSpriteLogicalRect(args2[0], false, r2);
Common::Rect r1(args1[0], args1[1], args1[2] + 1, args1[3] + 1);
_sprite->getSpriteLogicalRect(firstList[0], false, r2);
Common::Rect r1(lastList[0], lastList[1], lastList[2] + 1, lastList[3] + 1);
if (r2.isValidRect() == false) {
push(0);
break;
}
if (n2 == 3) {
r2.left += args2[1];
r2.right += args2[1];
r2.top += args2[2];
r2.bottom += args2[2];
if (firstCount == 3) {
r2.left += firstList[1];
r2.right += firstList[1];
r2.top += firstList[2];
r2.bottom += firstList[2];
}
push(r2.intersects(r1) ? 1 : 0);
}
@ -1755,24 +1756,24 @@ void ScummEngine_v90he::o90_getPolygonOverlap() {
// TODO: Draw sprites to buffer and compare.
{
Common::Rect r1, r2;
_sprite->getSpriteLogicalRect(args2[0], true, r2);
_sprite->getSpriteLogicalRect(args1[0], true, r1);
_sprite->getSpriteLogicalRect(firstList[0], true, r2);
_sprite->getSpriteLogicalRect(lastList[0], true, r1);
if (r2.isValidRect() == false) {
push(0);
break;
}
if (n2 == 3) {
r2.left += args2[1];
r2.right += args2[1];
r2.top += args2[2];
r2.bottom += args2[2];
if (firstCount == 3) {
r2.left += firstList[1];
r2.right += firstList[1];
r2.top += firstList[2];
r2.bottom += firstList[2];
}
if (n1 == 3) {
r1.left += args1[1];
r1.right += args1[1];
r1.top += args1[2];
r1.bottom += args1[2];
if (lastCount == 3) {
r1.left += lastList[1];
r1.right += lastList[1];
r1.top += lastList[2];
r1.bottom += lastList[2];
}
push(r2.intersects(r1) ? 1 : 0);
}
@ -1780,24 +1781,24 @@ void ScummEngine_v90he::o90_getPolygonOverlap() {
case OVERLAP_DRAW_POS_SPRITE_TO_RECT: // 9
{
Common::Rect r2;
_sprite->getSpriteLogicalRect(args2[0], true, r2);
Common::Rect r1(args1[0], args1[1], args1[2] + 1, args1[3] + 1);
_sprite->getSpriteLogicalRect(firstList[0], true, r2);
Common::Rect r1(lastList[0], lastList[1], lastList[2] + 1, lastList[3] + 1);
if (r2.isValidRect() == false) {
push(0);
break;
}
if (n2 == 3) {
r2.left += args2[1];
r2.right += args2[1];
r2.top += args2[2];
r2.bottom += args2[2];
if (firstCount == 3) {
r2.left += firstList[1];
r2.right += firstList[1];
r2.top += firstList[2];
r2.bottom += firstList[2];
}
push(r2.intersects(r1) ? 1 : 0);
}
break;
default:
error("o90_getPolygonOverlap: default case %d", subOp);
error("o90_getPolygonOverlap: default case %d", checkType);
}
}

View File

@ -520,16 +520,16 @@ public:
bool _uses16BitColor = false;
int _lWizActiveShadow = 0;
void polygonClear();
void deleteLocalPolygons();
void polygonLoad(const uint8 *polData);
void polygonStore(int id, bool flag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y);
void set4Polygon(int id, bool flag, int vert1x, int vert1y, int vert2x, int vert2y, int vert3x, int vert3y, int vert4x, int vert4y);
void polyBuildBoundingRect(Common::Point *vert, int numVerts, Common::Rect & bound);
void polygonErase(int fromId, int toId);
int polygonTestForObjectHit(int id, int x, int y);
bool polygonDefined(int id);
void deletePolygon(int fromId, int toId);
int testForObjectPolygon(int id, int x, int y);
int findPolygon(int x, int y);
bool doesObjectHavePolygon(int id);
bool polyIsPointInsidePoly(const WizPolygon &pol, int x, int y);
void polyRotatePoints(Common::Point *pts, int num, int alpha);
void polygonTransform(int resNum, int state, int po_x, int po_y, int angle, int zoom, Common::Point *vert);
void polyMovePolygonPoints(Common::Point *listOfPoints, int numverts, int deltaX, int deltaY);
bool polyIsRectangle(const Common::Point *points, int numverts);

View File

@ -569,7 +569,7 @@ int ScummEngine::findObject(int x, int y) {
if (b == 0) {
#ifdef ENABLE_HE
if (_game.heversion >= 71) {
if (((ScummEngine_v71he *)this)->_wiz->polygonTestForObjectHit(_objs[i].obj_nr, x, y))
if (((ScummEngine_v71he *)this)->_wiz->testForObjectPolygon(_objs[i].obj_nr, x, y))
return _objs[i].obj_nr;
}
#endif
@ -1213,7 +1213,7 @@ void ScummEngine_v6::clearDrawQueues() {
void ScummEngine_v71he::clearDrawQueues() {
ScummEngine_v6::clearDrawQueues();
_wiz->polygonClear();
_wiz->deleteLocalPolygons();
}
void ScummEngine_v80he::clearDrawQueues() {