Add force affine+double size to NANR viewer

This commit is contained in:
Garhoogin 2025-05-30 13:55:13 -05:00 committed by GitHub
parent acb3ff1ac8
commit ca3b10a615
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 76 additions and 23 deletions

View File

@ -737,7 +737,8 @@ static void AnmViewerRenderGlyphListImage(NANRVIEWERDATA *data, int i) {
AnmViewerCalcTransformMatrix(0.0f, 0.0f, sx, sy, rot, (double) frm.px, (double) frm.py, &mtx[0][0], trans);
CellViewerRenderCell(data->cellRender, NULL, ncer, ncgr, nclr, frm.index, cell,
FloatToInt(trans[0]), FloatToInt(trans[1]),
mtx[0][0], mtx[0][1], mtx[1][0], mtx[1][1]);
mtx[0][0], mtx[0][1], mtx[1][0], mtx[1][1],
data->forceAffine, data->forceDoubleSize);
}
//next, crop the rendered cell
@ -1252,6 +1253,20 @@ static void AnmViewerCmdOnNewSequence(HWND hWnd, HWND hWndCtl, int notif, void *
AnmViewerSetCurrentSequence(data, data->nanr.nSequences - 1, TRUE);
}
static void AnmViewerCmdOnToggleForceAffine(HWND hWnd, HWND hWndCtl, int notif, void *param) {
NANRVIEWERDATA *data = (NANRVIEWERDATA *) param;
data->forceAffine = GetCheckboxChecked(hWndCtl);
InvalidateRect(data->hWndPreview, NULL, FALSE);
InvalidateRect(data->hWndAnimList, NULL, FALSE);
}
static void AnmViewerCmdOnToggleForceDoubleSize(HWND hWnd, HWND hWndCtl, int notif, void *param) {
NANRVIEWERDATA *data = (NANRVIEWERDATA *) param;
data->forceDoubleSize = GetCheckboxChecked(hWndCtl);
InvalidateRect(data->hWndPreview, NULL, FALSE);
InvalidateRect(data->hWndAnimList, NULL, FALSE);
}
static LRESULT CALLBACK AnmViewerSeqListSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT idSubclass, DWORD_PTR data_) {
NANRVIEWERDATA *data = (NANRVIEWERDATA *) data_;
@ -1277,6 +1292,7 @@ static void AnmViewerOnCreate(NANRVIEWERDATA *data) {
data->showBorders = 1;
data->hWndAnimList = AnmViewerAnimListCreate(data);
data->hWndNewSequence = CreateButton(data->hWnd, L"New Sequence", 0, 0, 0, 0, FALSE);
data->hWndPreview = CreateWindow(L"NanrPreviewClass", L"", WS_VISIBLE | WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_CLIPSIBLINGS,
300, 0, 300, 300, data->hWnd, NULL, NULL, NULL);
FbCreate(&data->fb, data->hWndPreview, 0, 0);
@ -1284,7 +1300,8 @@ static void AnmViewerOnCreate(NANRVIEWERDATA *data) {
data->hWndPlayPause = CreateButton(data->hWnd, L"Play", 0, 0, 0, 0, FALSE);
data->hWndStop = CreateButton(data->hWnd, L"Step", 0, 0, 0, 0, FALSE);
data->hWndShowFrames = CreateButton(data->hWnd, L"Frames", 0, 0, 0, 0, FALSE);
data->hWndNewSequence = CreateButton(data->hWnd, L"New Sequence", 0, 0, 0, 0, FALSE);
data->hWndForceAffine = CreateCheckbox(data->hWnd, L"Force Affine", 0, 0, 0, 0, FALSE);
data->hWndForceDoubleSize = CreateCheckbox(data->hWnd, L"Force Double Size", 0, 0, 0, 0, FALSE);
LPCWSTR playModes[] = {
//L"[\xFF0F\xFFE3\xFFE3\xFFE3] Forward",
@ -1304,6 +1321,8 @@ static void AnmViewerOnCreate(NANRVIEWERDATA *data) {
UiCtlMgrAddCommand(&data->mgr, data->hWndShowFrames, BN_CLICKED, AnmViewerCmdOnShowFrames);
UiCtlMgrAddCommand(&data->mgr, data->hWndPlayMode, CBN_SELCHANGE, AnmViewerCmdOnSetPlayMode);
UiCtlMgrAddCommand(&data->mgr, data->hWndNewSequence, BN_CLICKED, AnmViewerCmdOnNewSequence);
UiCtlMgrAddCommand(&data->mgr, data->hWndForceAffine, BN_CLICKED, AnmViewerCmdOnToggleForceAffine);
UiCtlMgrAddCommand(&data->mgr, data->hWndForceDoubleSize, BN_CLICKED, AnmViewerCmdOnToggleForceDoubleSize);
SetWindowSubclass(data->hWndAnimList, AnmViewerSeqListSubclassProc, 2, (DWORD_PTR) data);
}
@ -1332,6 +1351,10 @@ static int AnmViewerOnSize(NANRVIEWERDATA *data, WPARAM wParam, LPARAM lParam) {
int frameButtonX = cellPropX + ctlWidthWide + UI_SCALE_COORD(10, dpiScale);
MoveWindow(data->hWndShowFrames, frameButtonX, 0, UI_SCALE_COORD(75, dpiScale), ctlHeight, TRUE);
int forceCtlX = frameButtonX + UI_SCALE_COORD(75, dpiScale) + UI_SCALE_COORD(10, dpiScale);
MoveWindow(data->hWndForceAffine, forceCtlX, 0, UI_SCALE_COORD(80, dpiScale), ctlHeight, TRUE);
MoveWindow(data->hWndForceDoubleSize, forceCtlX + UI_SCALE_COORD(80, dpiScale), 0, UI_SCALE_COORD(125, dpiScale), ctlHeight, TRUE);
if (wParam == SIZE_RESTORED) InvalidateRect(data->hWndPreview, NULL, TRUE); //full update
return DefMDIChildProc(data->hWnd, WM_SIZE, wParam, lParam);
}
@ -1577,7 +1600,8 @@ static void AnmViewerPreviewOnPaint(NANRVIEWERDATA *data) {
AnmViewerCalcTransformMatrix(0.0, 0.0, sx, sy, rot, (double) frm.px, (double) frm.py, &mtx[0][0], trans);
CellViewerRenderCell(data->cellRender, NULL, ncer, ncgr, nclr, frm.index, cell,
FloatToInt(trans[0]), FloatToInt(trans[1]),
mtx[0][0], mtx[0][1], mtx[1][0], mtx[1][1]);
mtx[0][0], mtx[0][1], mtx[1][0], mtx[1][1],
data->forceAffine, data->forceDoubleSize);
}
//ensure framebuffer size

View File

@ -33,6 +33,9 @@ typedef struct {
int direction; // current animation direction
int resetFlag; // sequence is stopped and will be restarted
int forceAffine; // force affine mode for OBJ
int forceDoubleSize; // force double size for OBJ
int mouseDown;
int hit;
int mouseDownHit;
@ -58,6 +61,8 @@ typedef struct {
HWND hWndAnimList; // animation list
HWND hWndPreview; // preview
HWND hWndNewSequence;
HWND hWndForceAffine;
HWND hWndForceDoubleSize;
HWND hWndPlayPause;
HWND hWndStop;

View File

@ -790,7 +790,7 @@ static void CellViewerCopyDIB(NCERVIEWERDATA *data) {
tmpCell->useEx2d = cell->useEx2d;
tmpCell->ex2dCharNames = exAttr;
CellViewerRenderCell(buf, NULL, &data->ncer, ncgr, nclr, data->cell, tmpCell, 0, 0, 1.0f, 0.0f, 0.0f, 1.0f);
CellViewerRenderCell(buf, NULL, &data->ncer, ncgr, nclr, data->cell, tmpCell, 0, 0, 1.0f, 0.0f, 0.0f, 1.0f, 0, 0);
free(tmpCell);
free(selAttr);
if (exAttr != NULL) free(exAttr);
@ -1029,7 +1029,9 @@ void CellViewerRenderCell(
double a,
double b,
double c,
double d
double d,
int forceAffine,
int forceDoubleSize
) {
//adjust (X,Y) offset to center of preview
xOffs += 256;
@ -1037,7 +1039,7 @@ void CellViewerRenderCell(
//get VRAM transfer entry
CHAR_VRAM_TRANSFER *vramTransfer = NULL;
if (ncer->vramTransfer != NULL) vramTransfer = &ncer->vramTransfer[cellIndex];
if (ncer != NULL && ncer->vramTransfer != NULL && cellIndex != -1) vramTransfer = &ncer->vramTransfer[cellIndex];
//if cell is NULL, we use cell at cellInex.
if (cell == NULL) {
@ -1076,7 +1078,7 @@ void CellViewerRenderCell(
CellViewerRenderObj(block, &info, ncgr, nclr, ncer->mappingMode, vramTransfer);
//HV flip? Only if not affine!
if (!info.rotateScale) {
if (!(info.rotateScale || forceAffine)) {
COLOR32 temp[64];
if (info.flipY) {
for (int i = 0; i < info.height / 2; i++) {
@ -1097,17 +1099,23 @@ void CellViewerRenderCell(
}
}
//apply transformation matrix to OBJ position
int x = info.x;
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;
int doubleSize = info.doubleSize;
if ((info.rotateScale || forceAffine) && forceDoubleSize) doubleSize = 1;
//apply transformation matrix to OBJ position
int x = SEXT9(info.x);
int y = SEXT8(info.y);
//when forcing double size on an OBJ that isn't naturally double size, we'll correct its position.
if ((forceDoubleSize && (info.rotateScale || forceAffine)) && !info.doubleSize) {
x -= info.width / 2;
y -= info.height / 2;
}
if (!isMtxIdentity) {
//adjust coordinates by correction for double-size
int realWidth = info.width << info.doubleSize;
int realHeight = info.height << info.doubleSize;
int realWidth = info.width << doubleSize;
int realHeight = info.height << doubleSize;
int movedX = x + realWidth / 2;
int movedY = y + realHeight / 2;
@ -1117,9 +1125,9 @@ void CellViewerRenderCell(
}
//copy data
if (!info.rotateScale) {
if (!(info.rotateScale || forceAffine)) {
//adjust for double size
if (info.doubleSize) {
if (doubleSize) {
x += info.width / 2;
y += info.height / 2;
}
@ -1138,8 +1146,8 @@ void CellViewerRenderCell(
}
} else {
//transform about center
int realWidth = info.width << info.doubleSize;
int realHeight = info.height << info.doubleSize;
int realWidth = info.width << doubleSize;
int realHeight = info.height << doubleSize;
double cx = (realWidth - 1) * 0.5; // rotation center X in OBJ
double cy = (realHeight - 1) * 0.5; // rotation center Y in OBJ
@ -1152,7 +1160,7 @@ void CellViewerRenderCell(
int srcY = FloatToInt(((((double) k) - cx) * invC + (((double) j) - cy) * invD) + cy);
//if double size, adjust source coordinate by the excess size
if (info.doubleSize) {
if (doubleSize) {
srcX -= realWidth / 4;
srcY -= realHeight / 4;
}
@ -1173,7 +1181,7 @@ void CellViewerRenderCell(
}
static void CellViewerRenderCellByIndex(COLOR32 *buf, int *covbuf, NCER *ncer, NCGR *ncgr, NCLR *nclr, int cellno) {
CellViewerRenderCell(buf, covbuf, ncer, ncgr, nclr, cellno, NULL, 0, 0, 1.0f, 0.0f, 0.0f, 1.0f);
CellViewerRenderCell(buf, covbuf, ncer, ncgr, nclr, cellno, NULL, 0, 0, 1.0f, 0.0f, 0.0f, 1.0f, 0, 0);
}
static void CellViewerUpdateCellRender(NCERVIEWERDATA *data) {

View File

@ -90,6 +90,22 @@ HWND CreateNcerViewerImmediate(int x, int y, int width, int height, HWND hWndPar
void CellViewerRenderGridlines(FrameBuffer *fb, int scale, int scrollX, int scrollY);
void CellViewerRenderCell(COLOR32 *px, int *covbuf, NCER *ncer, NCGR *ncgr, NCLR *nclr, int cellIndex, NCER_CELL *cell, int xOffs, int yOffs, double a, double b, double c, double d);
void CellViewerRenderCell(
COLOR32 *px, // output 512x256 pixel buffer
int *covbuf, // output coverage buffer (optional)
NCER *ncer, // cell data bank
NCGR *ncgr, // character graphics
NCLR *nclr, // color palette
int cellIndex, // cell index (required if cell is in the cell data bank)
NCER_CELL *cell, // cell data (required if not in the cell data bank)
int xOffs, // horizontal displacement of render
int yOffs, // vertical displacement of render
double a, // affine parameter A
double b, // affine parameter B
double c, // affine parameter C
double d, // affine parameter D
int forceAffine, // forces all OBJ to be in affine mode
int forceDoubleSize // forces all affine OBJ to be in double size mode
);
COLOR32 *CellViewerCropRenderedCell(COLOR32 *px, int width, int height, int *pMinX, int *pMinY, int *outWidth, int *outHeight);