mirror of
https://github.com/litruv/picoGraph.git
synced 2026-07-24 02:36:04 +10:00
Initial commit
moved from private version control
This commit is contained in:
37
scripts/nodes/library/graphics/camera.js
Normal file
37
scripts/nodes/library/graphics/camera.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Applies a camera offset to subsequent draw calls.
|
||||
*/
|
||||
export const cameraNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_camera",
|
||||
title: "Add Camera Offset",
|
||||
category: "Graphics",
|
||||
description: "Shift the draw origin by the specified camera offset.",
|
||||
searchTags: ["camera", "offset", "scroll", "view"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "x", name: "X", direction: "input", kind: "number" },
|
||||
{ id: "y", name: "Y", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const x = resolveValueInput("x", OMIT);
|
||||
const y = resolveValueInput("y", OMIT);
|
||||
let call = "camera()";
|
||||
if (x !== OMIT) {
|
||||
call = `camera(${x}, ${y === OMIT ? "0" : y})`;
|
||||
}
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
57
scripts/nodes/library/graphics/circ.js
Normal file
57
scripts/nodes/library/graphics/circ.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws an outlined circle.
|
||||
*/
|
||||
export const circNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_circ",
|
||||
title: "Draw Circle",
|
||||
category: "Graphics",
|
||||
description: "Render an outlined circle at the specified position.",
|
||||
searchTags: ["circle", "outline", "shape", "draw"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "radius",
|
||||
name: "Radius",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 4,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const radius = resolveValueInput("radius", "4");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x, y, radius];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}circ(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
57
scripts/nodes/library/graphics/circfill.js
Normal file
57
scripts/nodes/library/graphics/circfill.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a filled circle.
|
||||
*/
|
||||
export const circfillNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_circfill",
|
||||
title: "Draw Filled Circle",
|
||||
category: "Graphics",
|
||||
description: "Render a filled circle at the specified position.",
|
||||
searchTags: ["circle", "filled", "shape", "draw"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "radius",
|
||||
name: "Radius",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 4,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const radius = resolveValueInput("radius", "4");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x, y, radius];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}circfill(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
63
scripts/nodes/library/graphics/clip.js
Normal file
63
scripts/nodes/library/graphics/clip.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Adjusts the active clipping rectangle for subsequent draw calls.
|
||||
*/
|
||||
export const clipNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_clip",
|
||||
title: "Set Clipping Rectangle",
|
||||
category: "Graphics",
|
||||
description:
|
||||
"Set or reset the clipping rectangle that constrains all draw operations.",
|
||||
searchTags: ["clip", "clipping", "graphics", "viewport"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "x", name: "X", direction: "input", kind: "number" },
|
||||
{ id: "y", name: "Y", direction: "input", kind: "number" },
|
||||
{ id: "w", name: "Width", direction: "input", kind: "number" },
|
||||
{ id: "h", name: "Height", direction: "input", kind: "number" },
|
||||
{
|
||||
id: "clip_previous",
|
||||
name: "Clip Previous",
|
||||
direction: "input",
|
||||
kind: "boolean",
|
||||
defaultValue: false,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const x = resolveValueInput("x", OMIT);
|
||||
const y = resolveValueInput("y", OMIT);
|
||||
const w = resolveValueInput("w", OMIT);
|
||||
const h = resolveValueInput("h", OMIT);
|
||||
const clipPrevious = resolveValueInput("clip_previous", OMIT);
|
||||
|
||||
let call;
|
||||
if (x === OMIT && y === OMIT && w === OMIT && h === OMIT) {
|
||||
call = "clip()";
|
||||
} else {
|
||||
const args = [
|
||||
x === OMIT ? "0" : x,
|
||||
y === OMIT ? "0" : y,
|
||||
w === OMIT ? "128" : w,
|
||||
h === OMIT ? "128" : h,
|
||||
];
|
||||
if (clipPrevious !== OMIT) {
|
||||
args.push(clipPrevious);
|
||||
}
|
||||
call = `clip(${args.join(", ")})`;
|
||||
}
|
||||
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
32
scripts/nodes/library/graphics/cls.js
Normal file
32
scripts/nodes/library/graphics/cls.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Clears the screen and resets clipping.
|
||||
*/
|
||||
export const clsNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_cls",
|
||||
title: "Clear Screen",
|
||||
category: "Graphics",
|
||||
description: "Clear the display, optionally filling with a specific color.",
|
||||
searchTags: ["cls", "clear", "screen", "background"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
const call = color === OMIT ? "cls()" : `cls(${color})`;
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
32
scripts/nodes/library/graphics/color.js
Normal file
32
scripts/nodes/library/graphics/color.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Updates the current draw color.
|
||||
*/
|
||||
export const colorNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_color",
|
||||
title: "Set Active Color",
|
||||
category: "Graphics",
|
||||
description: "Set the active draw color used by subsequent graphics calls.",
|
||||
searchTags: ["color", "color", "ink", "draw"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
const call = color === OMIT ? "color()" : `color(${color})`;
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
46
scripts/nodes/library/graphics/cursor.js
Normal file
46
scripts/nodes/library/graphics/cursor.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Positions the print cursor and optionally sets the draw color.
|
||||
*/
|
||||
export const cursorNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_cursor",
|
||||
title: "Set Cursor",
|
||||
category: "Graphics",
|
||||
description:
|
||||
"Move the print cursor and optionally change the active color.",
|
||||
searchTags: ["cursor", "print", "text", "position"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "x", name: "X", direction: "input", kind: "number" },
|
||||
{ id: "y", name: "Y", direction: "input", kind: "number" },
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const x = resolveValueInput("x", OMIT);
|
||||
const y = resolveValueInput("y", OMIT);
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
|
||||
let call = "cursor()";
|
||||
if (x !== OMIT) {
|
||||
const args = [x, y === OMIT ? "0" : y];
|
||||
if (color !== OMIT) {
|
||||
args.push(color);
|
||||
}
|
||||
call = `cursor(${args.join(", ")})`;
|
||||
}
|
||||
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
39
scripts/nodes/library/graphics/fget.js
Normal file
39
scripts/nodes/library/graphics/fget.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Reads sprite flag data.
|
||||
*/
|
||||
export const fgetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_fget",
|
||||
title: "Get Sprite Flag",
|
||||
category: "Graphics",
|
||||
description: "Retrieve the bitfield or specific flag value for a sprite.",
|
||||
searchTags: ["fget", "flag", "sprite", "meta"],
|
||||
inputs: [
|
||||
{
|
||||
id: "sprite",
|
||||
name: "Sprite",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "flag", name: "Flag", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "value", name: "Value", direction: "output", kind: "number" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
evaluateValue: ({ resolveValueInput }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const sprite = resolveValueInput("sprite", "0");
|
||||
const flag = resolveValueInput("flag", OMIT);
|
||||
if (flag === OMIT) {
|
||||
return `fget(${sprite})`;
|
||||
}
|
||||
return `fget(${sprite}, ${flag})`;
|
||||
},
|
||||
}
|
||||
);
|
||||
31
scripts/nodes/library/graphics/fillp.js
Normal file
31
scripts/nodes/library/graphics/fillp.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Configures the active fill pattern.
|
||||
*/
|
||||
export const fillpNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_fillp",
|
||||
title: "Set Fill Pattern",
|
||||
category: "Graphics",
|
||||
description: "Set the 4x4 fill pattern bitfield used by many draw calls.",
|
||||
searchTags: ["fillp", "pattern", "fill", "hatch"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "pattern", name: "Pattern", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const pattern = resolveValueInput("pattern", "__pg_omit__");
|
||||
const call = pattern === "__pg_omit__" ? "fillp()" : `fillp(${pattern})`;
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
52
scripts/nodes/library/graphics/fset.js
Normal file
52
scripts/nodes/library/graphics/fset.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Updates sprite flag values.
|
||||
*/
|
||||
export const fsetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_fset",
|
||||
title: "Set Sprite Flag",
|
||||
category: "Graphics",
|
||||
description: "Set a sprite's flag bitfield or a specific flag value.",
|
||||
searchTags: ["fset", "flag", "sprite", "meta"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "sprite",
|
||||
name: "Sprite",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "flag", name: "Flag", direction: "input", kind: "number" },
|
||||
{
|
||||
id: "value",
|
||||
name: "Value",
|
||||
direction: "input",
|
||||
kind: "any",
|
||||
defaultValue: true,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const sprite = resolveValueInput("sprite", "0");
|
||||
const flag = resolveValueInput("flag", OMIT);
|
||||
const value = resolveValueInput("value", "false");
|
||||
const args = [sprite];
|
||||
if (flag === OMIT) {
|
||||
args.push(value);
|
||||
} else {
|
||||
args.push(flag, value);
|
||||
}
|
||||
const line = `${indent(indentLevel)}fset(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
88
scripts/nodes/library/graphics/index.js
Normal file
88
scripts/nodes/library/graphics/index.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import { clipNode } from "./clip.js";
|
||||
import { psetNode } from "./pset.js";
|
||||
import { pgetNode } from "./pget.js";
|
||||
import { sgetNode } from "./sget.js";
|
||||
import { ssetNode } from "./sset.js";
|
||||
import { fgetNode } from "./fget.js";
|
||||
import { fsetNode } from "./fset.js";
|
||||
import { cursorNode } from "./cursor.js";
|
||||
import { colorNode } from "./color.js";
|
||||
import { clsNode } from "./cls.js";
|
||||
import { cameraNode } from "./camera.js";
|
||||
import { circNode } from "./circ.js";
|
||||
import { circfillNode } from "./circfill.js";
|
||||
import { ovalNode } from "./oval.js";
|
||||
import { ovalfillNode } from "./ovalfill.js";
|
||||
import { lineNode } from "./line.js";
|
||||
import { rectNode } from "./rect.js";
|
||||
import { rectfillNode } from "./rectfill.js";
|
||||
import { rrectNode } from "./rrect.js";
|
||||
import { rrectfillNode } from "./rrectfill.js";
|
||||
import { palNode } from "./pal.js";
|
||||
import { paltNode } from "./palt.js";
|
||||
import { sprNode } from "./spr.js";
|
||||
import { ssprNode } from "./sspr.js";
|
||||
import { fillpNode } from "./fillp.js";
|
||||
|
||||
/**
|
||||
* All graphics related node modules backed by PICO-8 draw helpers.
|
||||
*/
|
||||
export const graphicsNodes = [
|
||||
clipNode,
|
||||
psetNode,
|
||||
pgetNode,
|
||||
sgetNode,
|
||||
ssetNode,
|
||||
fgetNode,
|
||||
fsetNode,
|
||||
cursorNode,
|
||||
colorNode,
|
||||
clsNode,
|
||||
cameraNode,
|
||||
circNode,
|
||||
circfillNode,
|
||||
ovalNode,
|
||||
ovalfillNode,
|
||||
lineNode,
|
||||
rectNode,
|
||||
rectfillNode,
|
||||
rrectNode,
|
||||
rrectfillNode,
|
||||
palNode,
|
||||
paltNode,
|
||||
sprNode,
|
||||
ssprNode,
|
||||
fillpNode,
|
||||
];
|
||||
|
||||
/**
|
||||
* Checklist tracking coverage of documented graphics helpers.
|
||||
* @type {Array<{ function: string, nodeId: string, implemented: boolean }>}
|
||||
*/
|
||||
export const graphicsFunctionChecklist = [
|
||||
{ function: "CLIP", nodeId: "graphics_clip", implemented: true },
|
||||
{ function: "PSET", nodeId: "graphics_pset", implemented: true },
|
||||
{ function: "PGET", nodeId: "graphics_pget", implemented: true },
|
||||
{ function: "SGET", nodeId: "graphics_sget", implemented: true },
|
||||
{ function: "SSET", nodeId: "graphics_sset", implemented: true },
|
||||
{ function: "FGET", nodeId: "graphics_fget", implemented: true },
|
||||
{ function: "FSET", nodeId: "graphics_fset", implemented: true },
|
||||
{ function: "CURSOR", nodeId: "graphics_cursor", implemented: true },
|
||||
{ function: "COLOR", nodeId: "graphics_color", implemented: true },
|
||||
{ function: "CLS", nodeId: "graphics_cls", implemented: true },
|
||||
{ function: "CAMERA", nodeId: "graphics_camera", implemented: true },
|
||||
{ function: "CIRC", nodeId: "graphics_circ", implemented: true },
|
||||
{ function: "CIRCFILL", nodeId: "graphics_circfill", implemented: true },
|
||||
{ function: "OVAL", nodeId: "graphics_oval", implemented: true },
|
||||
{ function: "OVALFILL", nodeId: "graphics_ovalfill", implemented: true },
|
||||
{ function: "LINE", nodeId: "graphics_line", implemented: true },
|
||||
{ function: "RECT", nodeId: "graphics_rect", implemented: true },
|
||||
{ function: "RECTFILL", nodeId: "graphics_rectfill", implemented: true },
|
||||
{ function: "RRECT", nodeId: "graphics_rrect", implemented: true },
|
||||
{ function: "RRECTFILL", nodeId: "graphics_rrectfill", implemented: true },
|
||||
{ function: "PAL", nodeId: "graphics_pal", implemented: true },
|
||||
{ function: "PALT", nodeId: "graphics_palt", implemented: true },
|
||||
{ function: "SPR", nodeId: "graphics_spr", implemented: true },
|
||||
{ function: "SSPR", nodeId: "graphics_sspr", implemented: true },
|
||||
{ function: "FILLP", nodeId: "graphics_fillp", implemented: true },
|
||||
];
|
||||
60
scripts/nodes/library/graphics/line.js
Normal file
60
scripts/nodes/library/graphics/line.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a line segment.
|
||||
*/
|
||||
export const lineNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_line",
|
||||
title: "Draw Line",
|
||||
category: "Graphics",
|
||||
description:
|
||||
"Draw a line between two points or update the current pen position.",
|
||||
searchTags: ["line", "draw", "segment", "stroke"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x0",
|
||||
name: "X0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y0",
|
||||
name: "Y0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "x1", name: "X1", direction: "input", kind: "number" },
|
||||
{ id: "y1", name: "Y1", direction: "input", kind: "number" },
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const x0 = resolveValueInput("x0", "0");
|
||||
const y0 = resolveValueInput("y0", "0");
|
||||
const x1 = resolveValueInput("x1", OMIT);
|
||||
const y1 = resolveValueInput("y1", OMIT);
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
|
||||
const args = [x0, y0];
|
||||
if (x1 !== OMIT && y1 !== OMIT) {
|
||||
args.push(x1, y1);
|
||||
if (color !== OMIT) {
|
||||
args.push(color);
|
||||
}
|
||||
}
|
||||
|
||||
const line = `${indent(indentLevel)}line(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
65
scripts/nodes/library/graphics/oval.js
Normal file
65
scripts/nodes/library/graphics/oval.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws an outlined oval.
|
||||
*/
|
||||
export const ovalNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_oval",
|
||||
title: "Draw Oval",
|
||||
category: "Graphics",
|
||||
description: "Render an ellipse using the provided bounding box.",
|
||||
searchTags: ["oval", "ellipse", "shape", "outline"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x0",
|
||||
name: "X0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y0",
|
||||
name: "Y0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "x1",
|
||||
name: "X1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "y1",
|
||||
name: "Y1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x0 = resolveValueInput("x0", "0");
|
||||
const y0 = resolveValueInput("y0", "0");
|
||||
const x1 = resolveValueInput("x1", "8");
|
||||
const y1 = resolveValueInput("y1", "8");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x0, y0, x1, y1];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}oval(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
65
scripts/nodes/library/graphics/ovalfill.js
Normal file
65
scripts/nodes/library/graphics/ovalfill.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a filled oval.
|
||||
*/
|
||||
export const ovalfillNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_ovalfill",
|
||||
title: "Draw Filled Oval",
|
||||
category: "Graphics",
|
||||
description: "Render a filled ellipse using the provided bounding box.",
|
||||
searchTags: ["oval", "ellipse", "filled", "shape"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x0",
|
||||
name: "X0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y0",
|
||||
name: "Y0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "x1",
|
||||
name: "X1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "y1",
|
||||
name: "Y1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x0 = resolveValueInput("x0", "0");
|
||||
const y0 = resolveValueInput("y0", "0");
|
||||
const x1 = resolveValueInput("x1", "8");
|
||||
const y1 = resolveValueInput("y1", "8");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x0, y0, x1, y1];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}ovalfill(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
51
scripts/nodes/library/graphics/pal.js
Normal file
51
scripts/nodes/library/graphics/pal.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Remaps palette colors.
|
||||
*/
|
||||
export const palNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_pal",
|
||||
title: "Remap Palette Color",
|
||||
category: "Graphics",
|
||||
description: "Swap one palette color for another or reset the palette.",
|
||||
searchTags: ["pal", "palette", "color", "remap"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "c0", name: "Color 0", direction: "input", kind: "number" },
|
||||
{
|
||||
id: "c1",
|
||||
name: "Color 1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "p", name: "Palette", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const c0 = resolveValueInput("c0", OMIT);
|
||||
const c1 = resolveValueInput("c1", "0");
|
||||
const p = resolveValueInput("p", OMIT);
|
||||
|
||||
let call = "pal()";
|
||||
if (c0 !== OMIT) {
|
||||
const args = [c0, c1];
|
||||
if (p !== OMIT) {
|
||||
args.push(p);
|
||||
}
|
||||
call = `pal(${args.join(", ")})`;
|
||||
}
|
||||
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
47
scripts/nodes/library/graphics/palt.js
Normal file
47
scripts/nodes/library/graphics/palt.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Adjusts sprite transparency settings.
|
||||
*/
|
||||
export const paltNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_palt",
|
||||
title: "Set Sprite Transparency",
|
||||
category: "Graphics",
|
||||
description: "Set or reset sprite transparency flags.",
|
||||
searchTags: ["palt", "transparency", "palette", "sprite"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
{
|
||||
id: "transparent",
|
||||
name: "Transparent",
|
||||
direction: "input",
|
||||
kind: "boolean",
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
const transparent = resolveValueInput("transparent", OMIT);
|
||||
|
||||
let call = "palt()";
|
||||
if (color !== OMIT) {
|
||||
if (transparent === OMIT) {
|
||||
call = `palt(${color})`;
|
||||
} else {
|
||||
call = `palt(${color}, ${transparent})`;
|
||||
}
|
||||
}
|
||||
const lines = [`${indent(indentLevel)}${call}`];
|
||||
lines.push(...emitNextExec("exec_out"));
|
||||
return lines;
|
||||
},
|
||||
}
|
||||
);
|
||||
41
scripts/nodes/library/graphics/pget.js
Normal file
41
scripts/nodes/library/graphics/pget.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Reads the color of a screen pixel.
|
||||
*/
|
||||
export const pgetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_pget",
|
||||
title: "Get Pixel Color",
|
||||
category: "Graphics",
|
||||
description: "Fetch the color index at the given screen coordinate.",
|
||||
searchTags: ["pget", "pixel", "read", "sample"],
|
||||
inputs: [
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "value", name: "Color", direction: "output", kind: "number" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
evaluateValue: ({ resolveValueInput }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
return `pget(${x}, ${y})`;
|
||||
},
|
||||
}
|
||||
);
|
||||
50
scripts/nodes/library/graphics/pset.js
Normal file
50
scripts/nodes/library/graphics/pset.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a single pixel using the current or specified color.
|
||||
*/
|
||||
export const psetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_pset",
|
||||
title: "Set Pixel Color",
|
||||
category: "Graphics",
|
||||
description: "Set a pixel on screen to a color index.",
|
||||
searchTags: ["pset", "pixel", "draw", "plot"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const color = resolveValueInput("color", OMIT);
|
||||
const args = [x, y];
|
||||
if (color !== OMIT) {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}pset(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
65
scripts/nodes/library/graphics/rect.js
Normal file
65
scripts/nodes/library/graphics/rect.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws an outlined rectangle.
|
||||
*/
|
||||
export const rectNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_rect",
|
||||
title: "Draw Rectangle",
|
||||
category: "Graphics",
|
||||
description: "Render a rectangle outline defined by two corners.",
|
||||
searchTags: ["rect", "rectangle", "outline", "shape"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x0",
|
||||
name: "X0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y0",
|
||||
name: "Y0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "x1",
|
||||
name: "X1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "y1",
|
||||
name: "Y1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x0 = resolveValueInput("x0", "0");
|
||||
const y0 = resolveValueInput("y0", "0");
|
||||
const x1 = resolveValueInput("x1", "8");
|
||||
const y1 = resolveValueInput("y1", "8");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x0, y0, x1, y1];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}rect(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
65
scripts/nodes/library/graphics/rectfill.js
Normal file
65
scripts/nodes/library/graphics/rectfill.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a filled rectangle.
|
||||
*/
|
||||
export const rectfillNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_rectfill",
|
||||
title: "Draw Filled Rectangle",
|
||||
category: "Graphics",
|
||||
description: "Render a filled rectangle defined by two corners.",
|
||||
searchTags: ["rect", "rectangle", "filled", "shape"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x0",
|
||||
name: "X0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y0",
|
||||
name: "Y0",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "x1",
|
||||
name: "X1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "y1",
|
||||
name: "Y1",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x0 = resolveValueInput("x0", "0");
|
||||
const y0 = resolveValueInput("y0", "0");
|
||||
const x1 = resolveValueInput("x1", "8");
|
||||
const y1 = resolveValueInput("y1", "8");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x0, y0, x1, y1];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}rectfill(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
73
scripts/nodes/library/graphics/rrect.js
Normal file
73
scripts/nodes/library/graphics/rrect.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws an outlined rounded rectangle.
|
||||
*/
|
||||
export const rrectNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_rrect",
|
||||
title: "Draw Rounded Rectangle",
|
||||
category: "Graphics",
|
||||
description: "Render a rounded rectangle outline with the supplied radius.",
|
||||
searchTags: ["rounded", "rectangle", "outline", "shape"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "w",
|
||||
name: "Width",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "h",
|
||||
name: "Height",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "r",
|
||||
name: "Radius",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 2,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const w = resolveValueInput("w", "8");
|
||||
const h = resolveValueInput("h", "8");
|
||||
const r = resolveValueInput("r", "2");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x, y, w, h, r];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}rrect(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
73
scripts/nodes/library/graphics/rrectfill.js
Normal file
73
scripts/nodes/library/graphics/rrectfill.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a filled rounded rectangle.
|
||||
*/
|
||||
export const rrectfillNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_rrectfill",
|
||||
title: "Draw Filled Rounded Rectangle",
|
||||
category: "Graphics",
|
||||
description: "Render a filled rounded rectangle with the supplied radius.",
|
||||
searchTags: ["rounded", "rectangle", "filled", "shape"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "w",
|
||||
name: "Width",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "h",
|
||||
name: "Height",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "r",
|
||||
name: "Radius",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 2,
|
||||
},
|
||||
{ id: "color", name: "Color", direction: "input", kind: "number" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const w = resolveValueInput("w", "8");
|
||||
const h = resolveValueInput("h", "8");
|
||||
const r = resolveValueInput("r", "2");
|
||||
const color = resolveValueInput("color", "__pg_omit__");
|
||||
const args = [x, y, w, h, r];
|
||||
if (color !== "__pg_omit__") {
|
||||
args.push(color);
|
||||
}
|
||||
const line = `${indent(indentLevel)}rrectfill(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
42
scripts/nodes/library/graphics/sget.js
Normal file
42
scripts/nodes/library/graphics/sget.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Reads a pixel from the sprite sheet.
|
||||
*/
|
||||
export const sgetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_sget",
|
||||
title: "Get Sprite Pixel",
|
||||
category: "Graphics",
|
||||
description:
|
||||
"Retrieve the color index from the sprite sheet at the given coordinate.",
|
||||
searchTags: ["sget", "sprite", "sheet", "read"],
|
||||
inputs: [
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "value", name: "Color", direction: "output", kind: "number" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
evaluateValue: ({ resolveValueInput }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
return `sget(${x}, ${y})`;
|
||||
},
|
||||
}
|
||||
);
|
||||
76
scripts/nodes/library/graphics/spr.js
Normal file
76
scripts/nodes/library/graphics/spr.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws sprites from the sprite sheet.
|
||||
*/
|
||||
export const sprNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_spr",
|
||||
title: "Draw Sprite",
|
||||
category: "Graphics",
|
||||
description: "Blit one or more sprites at the given screen position.",
|
||||
searchTags: ["spr", "sprite", "draw", "blit"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "sprite",
|
||||
name: "Sprite",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "w", name: "Width", direction: "input", kind: "number" },
|
||||
{ id: "h", name: "Height", direction: "input", kind: "number" },
|
||||
{ id: "flip_x", name: "Flip X", direction: "input", kind: "boolean" },
|
||||
{ id: "flip_y", name: "Flip Y", direction: "input", kind: "boolean" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const sprite = resolveValueInput("sprite", "0");
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const w = resolveValueInput("w", OMIT);
|
||||
const h = resolveValueInput("h", OMIT);
|
||||
const flipX = resolveValueInput("flip_x", OMIT);
|
||||
const flipY = resolveValueInput("flip_y", OMIT);
|
||||
|
||||
const args = [sprite, x, y];
|
||||
const includeSize =
|
||||
w !== OMIT || h !== OMIT || flipX !== OMIT || flipY !== OMIT;
|
||||
|
||||
if (includeSize) {
|
||||
args.push(w === OMIT ? "1" : w, h === OMIT ? "1" : h);
|
||||
}
|
||||
|
||||
if (flipX !== OMIT || flipY !== OMIT) {
|
||||
args.push(
|
||||
flipX === OMIT ? "false" : flipX,
|
||||
flipY === OMIT ? "false" : flipY
|
||||
);
|
||||
}
|
||||
|
||||
const line = `${indent(indentLevel)}spr(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
51
scripts/nodes/library/graphics/sset.js
Normal file
51
scripts/nodes/library/graphics/sset.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Writes a pixel to the sprite sheet.
|
||||
*/
|
||||
export const ssetNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_sset",
|
||||
title: "Set Sprite Pixel",
|
||||
category: "Graphics",
|
||||
description: "Assign a color to the sprite sheet at the given coordinate.",
|
||||
searchTags: ["sset", "sprite", "sheet", "write"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "x",
|
||||
name: "X",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "y",
|
||||
name: "Y",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "color",
|
||||
name: "Color",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const x = resolveValueInput("x", "0");
|
||||
const y = resolveValueInput("y", "0");
|
||||
const color = resolveValueInput("color", "0");
|
||||
const line = `${indent(indentLevel)}sset(${x}, ${y}, ${color})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
100
scripts/nodes/library/graphics/sspr.js
Normal file
100
scripts/nodes/library/graphics/sspr.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import { createNodeModule } from "../../nodeTypes.js";
|
||||
|
||||
/**
|
||||
* Draws a rectangular region of the sprite sheet with scaling support.
|
||||
*/
|
||||
export const ssprNode = createNodeModule(
|
||||
{
|
||||
id: "graphics_sspr",
|
||||
title: "Draw Scaled Sprite",
|
||||
category: "Graphics",
|
||||
description: "Stretch or flip a sprite sheet region to the screen.",
|
||||
searchTags: ["sspr", "sprite", "scale", "blit"],
|
||||
inputs: [
|
||||
{ id: "exec_in", name: "Exec", direction: "input", kind: "exec" },
|
||||
{
|
||||
id: "sx",
|
||||
name: "SX",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "sy",
|
||||
name: "SY",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "sw",
|
||||
name: "SW",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "sh",
|
||||
name: "SH",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 8,
|
||||
},
|
||||
{
|
||||
id: "dx",
|
||||
name: "DX",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
id: "dy",
|
||||
name: "DY",
|
||||
direction: "input",
|
||||
kind: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{ id: "dw", name: "DW", direction: "input", kind: "number" },
|
||||
{ id: "dh", name: "DH", direction: "input", kind: "number" },
|
||||
{ id: "flip_x", name: "Flip X", direction: "input", kind: "boolean" },
|
||||
{ id: "flip_y", name: "Flip Y", direction: "input", kind: "boolean" },
|
||||
],
|
||||
outputs: [
|
||||
{ id: "exec_out", name: "Exec", direction: "output", kind: "exec" },
|
||||
],
|
||||
properties: [],
|
||||
},
|
||||
{
|
||||
emitExec: ({ indent, indentLevel, resolveValueInput, emitNextExec }) => {
|
||||
const OMIT = "__pg_omit__";
|
||||
const sx = resolveValueInput("sx", "0");
|
||||
const sy = resolveValueInput("sy", "0");
|
||||
const sw = resolveValueInput("sw", "8");
|
||||
const sh = resolveValueInput("sh", "8");
|
||||
const dx = resolveValueInput("dx", "0");
|
||||
const dy = resolveValueInput("dy", "0");
|
||||
const dw = resolveValueInput("dw", OMIT);
|
||||
const dh = resolveValueInput("dh", OMIT);
|
||||
const flipX = resolveValueInput("flip_x", OMIT);
|
||||
const flipY = resolveValueInput("flip_y", OMIT);
|
||||
|
||||
const args = [sx, sy, sw, sh, dx, dy];
|
||||
const includeDestSize =
|
||||
dw !== OMIT || dh !== OMIT || flipX !== OMIT || flipY !== OMIT;
|
||||
|
||||
if (includeDestSize) {
|
||||
args.push(dw === OMIT ? sw : dw, dh === OMIT ? sh : dh);
|
||||
}
|
||||
|
||||
if (flipX !== OMIT || flipY !== OMIT) {
|
||||
args.push(
|
||||
flipX === OMIT ? "false" : flipX,
|
||||
flipY === OMIT ? "false" : flipY
|
||||
);
|
||||
}
|
||||
|
||||
const line = `${indent(indentLevel)}sspr(${args.join(", ")})`;
|
||||
return [line, ...emitNextExec("exec_out")];
|
||||
},
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user