Initial commit

moved from private version control
This commit is contained in:
2025-10-19 21:12:41 +11:00
parent 5e84773bbe
commit e64f3e881e
187 changed files with 25372 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Reads the state of a PICO-8 button using BTN.
*/
export const btnNode = createNodeModule(
{
id: "input_btn",
title: "Button State",
category: "Input",
description: "Read the current pressed state for a controller button.",
searchTags: ["btn", "input", "button", "press"],
inputs: [
{
id: "button",
name: "Button",
direction: "input",
kind: "number",
description: "Button index or glyph code",
},
{
id: "player",
name: "Player",
direction: "input",
kind: "number",
description: "Optional player index",
},
],
outputs: [
{ id: "value", name: "Pressed", direction: "output", kind: "boolean" },
],
properties: [],
},
{
evaluateValue: ({ resolveValueInput }) => {
const OMIT = "__pg_omit__";
const button = resolveValueInput("button", OMIT);
const player = resolveValueInput("player", OMIT);
if (button === OMIT && player === OMIT) {
return "btn()";
}
if (button === OMIT) {
return `btn(nil, ${player})`;
}
if (player === OMIT) {
return `btn(${button})`;
}
return `btn(${button}, ${player})`;
},
}
);

View File

@@ -0,0 +1,56 @@
import { createNodeModule } from "../../nodeTypes.js";
/**
* Reads button press transitions using BTNP.
*/
export const btnpNode = createNodeModule(
{
id: "input_btnp",
title: "Button Press",
category: "Input",
description:
"Detect when a button is initially pressed or repeats using BTNP.",
searchTags: ["btnp", "input", "button", "press", "repeat"],
inputs: [
{
id: "button",
name: "Button",
direction: "input",
kind: "number",
description: "Button index or glyph code",
},
{
id: "player",
name: "Player",
direction: "input",
kind: "number",
description: "Optional player index",
},
],
outputs: [
{ id: "value", name: "Pressed", direction: "output", kind: "boolean" },
],
properties: [],
},
{
evaluateValue: ({ resolveValueInput }) => {
const OMIT = "__pg_omit__";
const button = resolveValueInput("button", OMIT);
const player = resolveValueInput("player", OMIT);
if (button === OMIT && player === OMIT) {
return "btnp()";
}
if (button === OMIT) {
return `btnp(nil, ${player})`;
}
if (player === OMIT) {
return `btnp(${button})`;
}
return `btnp(${button}, ${player})`;
},
}
);

View File

@@ -0,0 +1,175 @@
import { createNodeModule } from "../../nodeTypes.js";
const DEFAULT_PLAYER_VALUE = "0";
/**
* Normalizes the stored player property to a valid controller index.
*
* @param {unknown} value Raw inspector value.
* @returns {number}
*/
const resolvePlayerIndex = (value) => {
const numeric = Number.parseInt(
typeof value === "string" ? value : String(value ?? DEFAULT_PLAYER_VALUE),
10
);
if (!Number.isFinite(numeric) || numeric < 0) {
return 0;
}
if (numeric > 7) {
return 7;
}
return numeric;
};
const BUTTON_OPTIONS = [
{ value: "0", label: "Left" },
{ value: "1", label: "Right" },
{ value: "2", label: "Up" },
{ value: "3", label: "Down" },
{ value: "4", label: "O" },
{ value: "5", label: "X" },
];
const BUTTON_VALUE_SET = new Set(BUTTON_OPTIONS.map((option) => option.value));
const DEFAULT_BUTTON_VALUE = BUTTON_OPTIONS[0]?.value ?? "0";
/**
* Normalizes button property values to a valid BTN index represented as a string.
*
* @param {unknown} value Raw inspector value.
* @returns {string}
*/
const resolveButtonValue = (value) => {
const numeric = Number.parseInt(
typeof value === "string" ? value : String(value ?? DEFAULT_BUTTON_VALUE),
10
);
const candidate = Number.isFinite(numeric) ? String(numeric) : DEFAULT_BUTTON_VALUE;
if (BUTTON_VALUE_SET.has(candidate)) {
return candidate;
}
return DEFAULT_BUTTON_VALUE;
};
const PLAYER_OPTIONS = [
{ value: "0", label: "Player 0 (Cursors / Z X)" },
{ value: "1", label: "Player 1 (SFED / Tab Q W A)" },
{ value: "2", label: "Player 2" },
{ value: "3", label: "Player 3" },
{ value: "4", label: "Player 4" },
{ value: "5", label: "Player 5" },
{ value: "6", label: "Player 6" },
{ value: "7", label: "Player 7" },
];
/**
* Evaluates whether the configured button is currently pressed.
*/
export const controllerButtonsNode = createNodeModule(
{
id: "input_button_constants",
title: "Named Button",
category: "Input",
description:
"Read a specific controller button with a dropdown selector and optional player override.",
searchTags: [
"button",
"controller",
"dpad",
"input",
"player",
"named",
"press",
],
inputs: [
{
id: "button",
name: "Button",
direction: "input",
kind: "number",
description: "Optional button index override",
},
{
id: "player",
name: "Player",
direction: "input",
kind: "number",
description: "Optional player index override",
},
],
outputs: [
{
id: "pressed",
name: "Pressed",
direction: "output",
kind: "boolean",
},
],
properties: [
{
key: "button",
label: "Button",
type: "enum",
defaultValue: DEFAULT_BUTTON_VALUE,
options: BUTTON_OPTIONS,
},
{
key: "player",
label: "Default Player",
type: "enum",
defaultValue: DEFAULT_PLAYER_VALUE,
options: PLAYER_OPTIONS,
},
],
initializeProperties: (properties) => {
properties.button = resolveButtonValue(properties.button);
const normalizedPlayer = resolvePlayerIndex(properties.player);
properties.player = String(normalizedPlayer);
const buttonInlineKey = "pin:button";
const playerInlineKey = "pin:player";
const numericButton = Number.parseInt(properties.button, 10);
const numericPlayer = normalizedPlayer;
properties[buttonInlineKey] = Number.isFinite(numericButton)
? numericButton
: 0;
properties[playerInlineKey] = Number.isFinite(numericPlayer)
? numericPlayer
: 0;
},
onPropertiesChanged: (properties) => {
properties.button = resolveButtonValue(properties.button);
const normalizedPlayer = resolvePlayerIndex(properties.player);
properties.player = String(normalizedPlayer);
const buttonInlineKey = "pin:button";
const playerInlineKey = "pin:player";
const numericButton = Number.parseInt(properties.button, 10);
const numericPlayer = normalizedPlayer;
properties[buttonInlineKey] = Number.isFinite(numericButton)
? numericButton
: 0;
properties[playerInlineKey] = Number.isFinite(numericPlayer)
? numericPlayer
: 0;
},
},
{
evaluateValue: ({ node, resolveValueInput, formatLiteral }) => {
const buttonValue = resolveButtonValue(node.properties.button);
const parsedButton = Number.parseInt(buttonValue, 10);
const buttonIndex = Number.isFinite(parsedButton) ? parsedButton : 0;
const fallbackButton = formatLiteral("number", buttonIndex);
const buttonInput = resolveValueInput("button", fallbackButton);
const fallbackPlayer = formatLiteral(
"number",
resolvePlayerIndex(node.properties.player)
);
const playerInput = resolveValueInput("player", fallbackPlayer);
return `btn(${buttonInput}, ${playerInput})`;
},
}
);

View File

@@ -0,0 +1,17 @@
import { btnNode } from "./btn.js";
import { btnpNode } from "./btnp.js";
import { controllerButtonsNode } from "./controllerButtons.js";
/**
* All input-related node modules backed by PICO-8 helpers.
*/
export const inputNodes = [controllerButtonsNode, btnNode, btnpNode];
/**
* Checklist tracking coverage of documented input helpers.
* @type {Array<{ function: string, nodeId: string, implemented: boolean }>}
*/
export const inputFunctionChecklist = [
{ function: "BTN", nodeId: "input_btn", implemented: true },
{ function: "BTNP", nodeId: "input_btnp", implemented: true },
];