Skip to content

Commit

Permalink
Merge pull request #1597 from pau-tomas/wip/vram-tile-info
Browse files Browse the repository at this point in the history
Add tile index info to VRAM preview in debugger
  • Loading branch information
chrismaltby authored Oct 18, 2024
2 parents a1af565 + 836e102 commit 0a4c78e
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add support for theme, localization and project template plugins
- Add ability to right click a scene to "Run From Here" allowing quick preview of a specific scene. Optionally can only include the selected scenes for faster build previews in large projects.
- Add events "Load Projectile Into Slot" and "Launch Projectile In Slot" to allow more advanced control over setup and launch of projectiles and changing the loaded projectiles at run time
- Add ability to hover over tiles in debugger VRAM preview to see tile memory address information [@pau-tomas](https://github.com/pau-tomas)

### Changed

Expand Down
4 changes: 2 additions & 2 deletions src/components/debugger/DebuggerState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ const Content = styled.div`
padding: 10px;
`;

const DataRow = styled.div`
export const DataRow = styled.div`
padding-bottom: 5px;
&:last-of-type {
padding-bottom: 0;
}
`;

const DataLabel = styled.span`
export const DataLabel = styled.span`
font-weight: bold;
padding-right: 5px;
`;
Expand Down
175 changes: 170 additions & 5 deletions src/components/debugger/DebuggerVRAMPane.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,48 @@
import React, { useCallback } from "react";
import React, {
useCallback,
useContext,
useEffect,
useRef,
useState,
} from "react";
import { getSettings } from "store/features/settings/settingsState";
import settingsActions from "store/features/settings/settingsActions";
import { useAppDispatch, useAppSelector } from "store/hooks";
import styled from "styled-components";
import styled, { ThemeContext } from "styled-components";
import { SplitPaneHeader } from "ui/splitpane/SplitPaneHeader";
import { decHexVal } from "shared/lib/helpers/8bit";
import l10n from "shared/lib/lang/l10n";
import { DataLabel, DataRow } from "components/debugger/DebuggerState";

const Content = styled.div`
background: ${(props) => props.theme.colors.scripting.form.background};
padding: 10px;
max-width: 256px;
`;

const VramPreview = styled.div`
position: relative;
max-height: 240px;
`;

const Canvas = styled.canvas`
position: absolute;
top: 0px;
left: 0px;
width: 256px;
height: 256px;
border-radius: 4px;
image-rendering: pixelated;
`;

const TileAddr = styled.span`
font-family: monospace;
`;

const VramAreaLabel = styled.span`
opacity: 0.5;
text-overflow: ellipsis;
overflow: hidden;
`;

const DebuggerVRAMPane = () => {
Expand All @@ -16,10 +51,122 @@ const DebuggerVRAMPane = () => {
const isCollapsed = useAppSelector((state) =>
getSettings(state).debuggerCollapsedPanes.includes("vram")
);
const themeContext = useContext(ThemeContext);

const onToggleCollapsed = useCallback(() => {
dispatch(settingsActions.toggleDebuggerPaneCollapsed("vram"));
}, [dispatch]);
const [position, setPosition] = useState([-1, -1]);
const [index, setIndex] = useState(0);
const [bank, setBank] = useState(0);
const [vramArea, setVramArea] = useState(l10n("NAV_SPRITES"));

const canvasRef = useRef<HTMLCanvasElement>(null);

useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) {
return;
}
if (!themeContext) {
return;
}

const drawWidth = canvas.width;
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
const scaleY = canvas.height / rect.height;

const ctx = canvas.getContext("2d");

const tileSize = drawWidth / 32;

// eslint-disable-next-line no-self-assign
canvas.width = canvas.width;
// eslint-disable-next-line no-self-assign
canvas.height = canvas.height;

const highlightColor = themeContext.colors.highlight;

const drawGrid = () => {
if (ctx) {
// Draw grid
ctx.beginPath();
ctx.strokeStyle = "rgba(0, 0, 0, .1)";
ctx.lineWidth = scaleX;

ctx.moveTo(tileSize * 16 - 1, 0);
ctx.lineTo(tileSize * 16 - 1, 24 * tileSize);

ctx.moveTo(0, tileSize * 8 - 1);
ctx.lineTo(canvas.width, tileSize * 8 - 1);

ctx.moveTo(0, tileSize * 12 - 1);
ctx.lineTo(canvas.width, tileSize * 12 - 1);

ctx.moveTo(0, tileSize * 16 - 1);
ctx.lineTo(canvas.width, tileSize * 16 - 1);
ctx.stroke();

ctx.beginPath();
ctx.strokeStyle = highlightColor;
ctx.strokeRect(
position[0] * tileSize - 1,
position[1] * tileSize - 1,
tileSize,
tileSize
);

ctx.stroke();
}
};

drawGrid();

const handleMouseMove = (e: MouseEvent) => {
if (e.target !== canvasRef.current) {
return;
}

if (ctx) {
const x = (e.clientX - rect.left) * scaleX;
const y = (e.clientY - rect.top) * scaleY;
const i = Math.floor(x / 16);
const j = Math.floor(y / 16);

if (i >= 0 && j >= 0) {
let index = j * 16 + (i % 16);

const bank = i < 16 ? 0 : 1;

let vramArea = "";
if (j < 8) {
vramArea = l10n("NAV_SPRITES");
} else if (j < 12) {
vramArea = l10n("FIELD_SHARED");
} else if (j < 16) {
vramArea = l10n("MENU_UI_ELEMENTS");
} else if (j < 24) {
vramArea = l10n("FIELD_BACKGROUND");
index = index - 256;
}

if (j < 24) {
setPosition([i, j]);
setIndex(index);
setBank(bank);
setVramArea(vramArea);
}
}
}
};

window.addEventListener("mousemove", handleMouseMove);

return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
});

return (
<>
Expand All @@ -31,9 +178,27 @@ const DebuggerVRAMPane = () => {
VRAM
</SplitPaneHeader>
{!isCollapsed && (
<Content>
<img src={vramPreview} alt=""></img>
</Content>
<>
<Content>
<VramPreview>
<img src={vramPreview} alt=""></img>
<Canvas ref={canvasRef} width={512} height={512} />
</VramPreview>
<DataRow>
<DataLabel>{l10n("FIELD_TILE_INDEX")}:</DataLabel>
<TileAddr>
{String(index).padStart(3, "0")} (${decHexVal(index)})
</TileAddr>
</DataRow>
<DataRow>
<DataLabel>{l10n("FIELD_MEMORY_BANK")}:</DataLabel>
<TileAddr>{bank}</TileAddr>
</DataRow>
<DataRow>
<VramAreaLabel>{vramArea}</VramAreaLabel>
</DataRow>
</Content>
</>
)}
</>
);
Expand Down
3 changes: 3 additions & 0 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,9 @@
"FIELD_PROJECTILE_SLOT_DESC": "The slot that contains the projectile you want to launch",
"FIELD_LOAD_PROJECTILE_SLOT_DESC": "The slot where you want to store projectile data",
"FIELD_INITIAL_OFFSET": "Initial Offset",
"FIELD_TILE_INDEX": "Tile Index",
"FIELD_MEMORY_BANK": "Bank",
"FIELD_SHARED": "Shared",

"// 7": "Asset Viewer ---------------------------------------------",
"ASSET_SEARCH": "Search...",
Expand Down

0 comments on commit 0a4c78e

Please sign in to comment.