Correct cell transformations without rotate/scale

OBJ positions are now transformed appropriately
This commit is contained in:
Garhoogin 2025-05-29 18:48:48 -05:00 committed by GitHub
parent 13351c005e
commit 458f9c74f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 24 deletions

View File

@ -1021,6 +1021,9 @@ static void AnmViewerPausePlayback(NANRVIEWERDATA *data) {
static void AnmViewerStopPlayback(NANRVIEWERDATA *data) { static void AnmViewerStopPlayback(NANRVIEWERDATA *data) {
AnmViewerPausePlayback(data); AnmViewerPausePlayback(data);
data->resetFlag = 1; // set the reset flag data->resetFlag = 1; // set the reset flag
//set anchor
AnmViewerSetDefaultAnchor(data);
} }
static void AnmViewerAdvanceSequence(NANRVIEWERDATA *data) { static void AnmViewerAdvanceSequence(NANRVIEWERDATA *data) {
@ -1573,7 +1576,7 @@ static void AnmViewerPreviewOnPaint(NANRVIEWERDATA *data) {
} }
//render bounds //render bounds
if (cell != NULL) { if (cell != NULL && !data->playing) {
int boxX, boxY, boxW, boxH; int boxX, boxY, boxW, boxH;
AnmViewerGetCellBounds(cell, &boxX, &boxY, &boxW, &boxH); AnmViewerGetCellBounds(cell, &boxX, &boxY, &boxW, &boxH);
@ -2098,6 +2101,12 @@ static LRESULT CALLBACK AnmViewerFrameListSubclassProc(HWND hWnd, UINT msg, WPAR
// ----- frame list procedures // ----- frame list procedures
static void AnmViewerPutCurrentAnimFrameResetAnchor(NANRVIEWERDATA *data, const ANIM_DATA_SRT *srt, const int *pDuration) {
AnmViewerPutCurrentAnimFrame(data, srt, pDuration);
AnmViewerSetDefaultAnchor(data);
InvalidateRect(data->hWndAnimList, NULL, FALSE);
}
static void AnmViewerCmdSetIndex(NANRVIEWERDATA *data) { static void AnmViewerCmdSetIndex(NANRVIEWERDATA *data) {
WCHAR buf[16] = { 0 }; WCHAR buf[16] = { 0 };
ANIM_DATA_SRT srt; ANIM_DATA_SRT srt;
@ -2106,7 +2115,7 @@ static void AnmViewerCmdSetIndex(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Cell Index", L"Cell Index:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Cell Index", L"Cell Index:", buf, sizeof(buf) / sizeof(buf[0]));
srt.index = (unsigned short) _wtol(buf); srt.index = (unsigned short) _wtol(buf);
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerCmdSetDuration(NANRVIEWERDATA *data) { static void AnmViewerCmdSetDuration(NANRVIEWERDATA *data) {
@ -2117,7 +2126,7 @@ static void AnmViewerCmdSetDuration(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter Duration", L"Duration:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter Duration", L"Duration:", buf, sizeof(buf) / sizeof(buf[0]));
duration = _wtol(buf); duration = _wtol(buf);
AnmViewerPutCurrentAnimFrame(data, NULL, &duration); AnmViewerPutCurrentAnimFrameResetAnchor(data, NULL, &duration);
} }
static void AnmViewerCmdSetX(NANRVIEWERDATA *data) { static void AnmViewerCmdSetX(NANRVIEWERDATA *data) {
@ -2128,7 +2137,7 @@ static void AnmViewerCmdSetX(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter X Translation", L"X:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter X Translation", L"X:", buf, sizeof(buf) / sizeof(buf[0]));
srt.px = (short) _wtol(buf); srt.px = (short) _wtol(buf);
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerCmdSetY(NANRVIEWERDATA *data) { static void AnmViewerCmdSetY(NANRVIEWERDATA *data) {
@ -2139,7 +2148,7 @@ static void AnmViewerCmdSetY(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter Y Translation", L"Y:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter Y Translation", L"Y:", buf, sizeof(buf) / sizeof(buf[0]));
srt.py = (short) _wtol(buf); srt.py = (short) _wtol(buf);
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerCmdSetScaleX(NANRVIEWERDATA *data) { static void AnmViewerCmdSetScaleX(NANRVIEWERDATA *data) {
@ -2150,7 +2159,7 @@ static void AnmViewerCmdSetScaleX(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter X Scale", L"X:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter X Scale", L"X:", buf, sizeof(buf) / sizeof(buf[0]));
srt.sx = FloatToInt(my_wtof(buf) * 4096.0f); srt.sx = FloatToInt(my_wtof(buf) * 4096.0f);
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerCmdSetScaleY(NANRVIEWERDATA *data) { static void AnmViewerCmdSetScaleY(NANRVIEWERDATA *data) {
@ -2161,7 +2170,7 @@ static void AnmViewerCmdSetScaleY(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter Y Scale", L"Y:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter Y Scale", L"Y:", buf, sizeof(buf) / sizeof(buf[0]));
srt.sy = FloatToInt(my_wtof(buf) * 4096.0f); srt.sy = FloatToInt(my_wtof(buf) * 4096.0f);
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerCmdSetRotation(NANRVIEWERDATA *data) { static void AnmViewerCmdSetRotation(NANRVIEWERDATA *data) {
@ -2172,7 +2181,7 @@ static void AnmViewerCmdSetRotation(NANRVIEWERDATA *data) {
PromptUserText(data->hWnd, L"Enter Rotation", L"Rotation:", buf, sizeof(buf) / sizeof(buf[0])); PromptUserText(data->hWnd, L"Enter Rotation", L"Rotation:", buf, sizeof(buf) / sizeof(buf[0]));
srt.rotZ = FloatToInt(my_wtof(buf) * 65536.0f / 360.0f) & 0xFFFF; srt.rotZ = FloatToInt(my_wtof(buf) * 65536.0f / 360.0f) & 0xFFFF;
AnmViewerPutCurrentAnimFrame(data, &srt, NULL); AnmViewerPutCurrentAnimFrameResetAnchor(data, &srt, NULL);
} }
static void AnmViewerInsertFrame(NANRVIEWERDATA *data, int i) { static void AnmViewerInsertFrame(NANRVIEWERDATA *data, int i) {
@ -2199,6 +2208,7 @@ static void AnmViewerInsertFrame(NANRVIEWERDATA *data, int i) {
AnmViewerPutCurrentAnimFrame(data, &frm, NULL); AnmViewerPutCurrentAnimFrame(data, &frm, NULL);
data->currentFrame = oldI; data->currentFrame = oldI;
AnmViewerSetCurrentFrame(data, i, TRUE); AnmViewerSetCurrentFrame(data, i, TRUE);
AnmViewerSetDefaultAnchor(data);
} }
static void AnmViewerCmdInsertFrameAbove(NANRVIEWERDATA *data) { static void AnmViewerCmdInsertFrameAbove(NANRVIEWERDATA *data) {
@ -2247,6 +2257,8 @@ static void AnmViewerCmdInterpolateBelow(NANRVIEWERDATA *data) {
AnmViewerPutCurrentAnimFrame(data, &setting.result[i], NULL); AnmViewerPutCurrentAnimFrame(data, &setting.result[i], NULL);
} }
AnmViewerSetCurrentFrame(data, frame0, TRUE); AnmViewerSetCurrentFrame(data, frame0, TRUE);
AnmViewerSetDefaultAnchor(data);
InvalidateRect(data->hWndAnimList, NULL, FALSE);
free(setting.result); free(setting.result);
free(setting.durations); free(setting.durations);

View File

@ -1040,6 +1040,7 @@ void CellViewerRenderCell(
//compute inverse matrix parameters. //compute inverse matrix parameters.
double invA = 1.0, invB = 0.0, invC = 0.0, invD = 1.0; double invA = 1.0, invB = 0.0, invC = 0.0, invD = 1.0;
int isMtxIdentity = 1;
if (a != 1.0 || b != 0.0 || c != 0.0 || d != 1.0) { if (a != 1.0 || b != 0.0 || c != 0.0 || d != 1.0) {
//not identity matrix //not identity matrix
double det = a * d - b * c; // DBCA double det = a * d - b * c; // DBCA
@ -1055,6 +1056,7 @@ void CellViewerRenderCell(
invC = 0.0; invC = 0.0;
invD = 127.99609375; invD = 127.99609375;
} }
isMtxIdentity = 0; // not identity
} }
COLOR32 *block = (COLOR32 *) calloc(64 * 64, sizeof(COLOR32)); COLOR32 *block = (COLOR32 *) calloc(64 * 64, sizeof(COLOR32));
@ -1089,8 +1091,24 @@ void CellViewerRenderCell(
} }
} }
//apply transformation matrix to OBJ position
int x = info.x; int x = info.x;
int y = info.y; int y = info.y;
if (!isMtxIdentity) {
//adjust sign of OBJ coordinates, since we rely on signed coordinates
if (x >= 256) x -= 512;
if (y >= 128) y -= 256;
//adjust coordinates by correction for double-size
int realWidth = info.width << info.doubleSize;
int realHeight = info.height << info.doubleSize;
int movedX = x + realWidth / 2;
int movedY = y + realHeight / 2;
//un-correct moved position from center to top-left, un-correct for double-size
x = FloatToInt(movedX * a + movedY * b) - realWidth / 2;
y = FloatToInt(movedX * c + movedY * d) - realHeight / 2;
}
//copy data //copy data
if (!info.rotateScale) { if (!info.rotateScale) {
@ -1113,30 +1131,16 @@ void CellViewerRenderCell(
} }
} }
} else { } else {
//adjust sign of OBJ coordinates, since we rely on signed coordinates
if (x >= 256) x -= 512;
if (y >= 128) y -= 256;
//transform about center //transform about center
int realWidth = info.width << info.doubleSize; int realWidth = info.width << info.doubleSize;
int realHeight = info.height << info.doubleSize; int realHeight = info.height << info.doubleSize;
double cx = (realWidth - 1) * 0.5; // rotation center X in OBJ double cx = (realWidth - 1) * 0.5; // rotation center X in OBJ
double cy = (realHeight - 1) * 0.5; // rotation center Y in OBJ double cy = (realHeight - 1) * 0.5; // rotation center Y in OBJ
//transform coordinate origin by matrix transform
int movedX = x + realWidth / 2;
int movedY = y + realHeight / 2;
int movedX2 = FloatToInt(movedX * a + movedY * b);
int movedY2 = FloatToInt(movedX * c + movedY * d);
//un-correct moved position from center to top-left
movedX = movedX2 - realWidth / 2;
movedY = movedY2 - realHeight / 2;
for (int j = 0; j < realHeight; j++) { for (int j = 0; j < realHeight; j++) {
int destY = (movedY + j + yOffs) & 0xFF; int destY = (y + j + yOffs) & 0xFF;
for (int k = 0; k < realWidth; k++) { for (int k = 0; k < realWidth; k++) {
int destX = (movedX + k + xOffs) & 0x1FF; int destX = (x + k + xOffs) & 0x1FF;
int srcX = FloatToInt(((((double) k) - cx) * invA + (((double) j) - cy) * invB) + cx); int srcX = FloatToInt(((((double) k) - cx) * invA + (((double) j) - cy) * invB) + cx);
int srcY = FloatToInt(((((double) k) - cx) * invC + (((double) j) - cy) * invD) + cy); int srcY = FloatToInt(((((double) k) - cx) * invC + (((double) j) - cy) * invD) + cy);