Skip to content

Commit

Permalink
J2D: Introduce J2DAnchorPos to correct for wider aspect ratios
Browse files Browse the repository at this point in the history
J2DScreens are typically 640x480. When rendering in a different aspect ratio, the height will scale to match but the new and old widths will differ. The new J2DAnchorPos determines at what X position the elements will be rendered. Either anchored in the center, or on the left/right side of the screen.

E.g. With J2DAnchorPos.Left an element that was 10% from the left edge of the original 640x480, it will be 10% from the left screen edge.
  • Loading branch information
themikelester committed Dec 30, 2024
1 parent 0bfa915 commit 5b9e2d2
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
22 changes: 21 additions & 1 deletion src/Common/JSYSTEM/J2Dv1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ function parseResourceReference(buffer: ArrayBufferSlice, offset: number, resTyp
return { refType, resType, resName, arcName, _nextOffset: nextOffset };
}

/**
* When rendering a J2D element that was originally designed for 4:3 in a wider aspect ratio, the screenspace Y
* positions are maintained but the X positions must be adjusted. Often we simply want to keep the elements centered,
* but occasionally we want to anchor them to the left or right.
* See also: J2DGrafContext.setPort() and dPlaceName.load()
*/
export enum J2DAnchorPos {
Left,
Center,
Right
}

/**
* If set, the UVs for a quad will be pinned (bound) to the quad edge. If not set, the UVs will be clipped by the quad.
* For instance, if the texture is 200 pixels wide, but the quad is 100 pixels wide and Right is not set, the texture
Expand Down Expand Up @@ -566,14 +578,22 @@ export class J2DPicture extends J2DPane {
//#region J2DScreen
export class J2DScreen extends J2DPane {
public color: Color;
public anchorPos: J2DAnchorPos;

constructor(data: SCRN, cache: GfxRenderCache, resolver: ResourceResolver<JUTResType>) {
constructor(data: SCRN, cache: GfxRenderCache, resolver: ResourceResolver<JUTResType>, anchorPos: J2DAnchorPos) {
super(data, cache, null);
this.color = data.color;
this.anchorPos = anchorPos;
this.resolveReferences(resolver);
}

public override draw(renderInstManager: GfxRenderInstManager, ctx2D: J2DGrafContext, offsetX?: number, offsetY?: number): void {
switch(this.anchorPos) {
case J2DAnchorPos.Left: this.data.x = 0; break;
case J2DAnchorPos.Center: this.data.x = (ctx2D.aspectRatioCorrection - 1.0) * ctx2D.viewport[2] * 0.5; break;
case J2DAnchorPos.Right: this.data.x = (ctx2D.aspectRatioCorrection - 1.0) * ctx2D.viewport[2]; break;
}

super.draw(renderInstManager, ctx2D, offsetX, offsetY);
}

Expand Down
4 changes: 2 additions & 2 deletions src/ZeldaWindWaker/d_a.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { fopAcIt_JudgeByID, fopAcM_create, fopAcM_prm_class, fopAc_ac_c } from "
import { cPhs__Status, fGlobals, fpcPf__Register, fpcSCtRq_Request, fpc_bs__Constructor } from "./framework.js";
import { mDoExt_McaMorf, mDoExt_bckAnm, mDoExt_brkAnm, mDoExt_btkAnm, mDoExt_btpAnm, mDoExt_modelEntryDL, mDoExt_modelUpdateDL } from "./m_do_ext.js";
import { MtxPosition, MtxTrans, calc_mtx, mDoMtx_XYZrotM, mDoMtx_XrotM, mDoMtx_YrotM, mDoMtx_YrotS, mDoMtx_ZXYrotM, mDoMtx_ZrotM, mDoMtx_ZrotS, quatM } from "./m_do_mtx.js";
import { J2DGrafContext, J2DPane, J2DScreen } from "../Common/JSYSTEM/J2Dv1.js";
import { J2DAnchorPos, J2DGrafContext, J2DPane, J2DScreen } from "../Common/JSYSTEM/J2Dv1.js";

// Framework'd actors

Expand Down Expand Up @@ -5857,7 +5857,7 @@ class d_a_title extends fopAc_ac_c {
private proc_init2D(globals: dGlobals) {
const screenData = globals.resCtrl.getObjectResByName(ResType.Blo, d_a_title.arcName, "title_logo_e.blo");
assert(screenData !== null);
this.screen = new J2DScreen(screenData, globals.renderer.renderCache, globals.resCtrl.getResResolver(d_a_title.arcName));
this.screen = new J2DScreen(screenData, globals.renderer.renderCache, globals.resCtrl.getResResolver(d_a_title.arcName), J2DAnchorPos.Center);
this.screen.color = White;
this.screen.setAlpha(1.0); // TODO: This isn't here originally

Expand Down
4 changes: 2 additions & 2 deletions src/ZeldaWindWaker/d_place_name.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { J2DPicture, J2DScreen } from "../Common/JSYSTEM/J2Dv1.js";
import { J2DAnchorPos, J2DPicture, J2DScreen } from "../Common/JSYSTEM/J2Dv1.js";
import { BTI, BTIData } from "../Common/JSYSTEM/JUTTexture.js";
import { GfxRenderInstManager } from "../gfx/render/GfxRenderInstManager.js";
import { assertExists } from "../util.js";
Expand Down Expand Up @@ -89,7 +89,7 @@ export class d_place_name extends msg_class {
return status;

const screenData = globals.resCtrl.getObjectRes(ResType.Blo, `PName`, 0x04);
this.screen = new J2DScreen(screenData, globals.renderer.renderCache, globals.resCtrl.getResResolver('PName'));
this.screen = new J2DScreen(screenData, globals.renderer.renderCache, globals.resCtrl.getResResolver('PName'), J2DAnchorPos.Left);
this.screen.search('blc1')!.hide();
this.screen.search('blc2')!.hide();

Expand Down

0 comments on commit 5b9e2d2

Please sign in to comment.