Shader assets: graph-built shaders, the Shader tab and sprite rows from the graph (#62)
game-maker / suite (push) Failing after 3m59s

A shader is an asset carrying a node graph (Texture color, Output, Property,
Color, Add/Subtract/Multiply/Divide, Mix, Luminance) that compiles to the GLSL
fragment of a Pixi filter. The Shader tab reuses the Behavior canvas; a sprite
wears a shader through its Shader picker, and the rows below it are the
graph's Property nodes. Property schema, resolution and deviation take the
project because a sprite's rows now live in another asset. The built-in
registry of the prototype is gone; "Adjust colors" ships as a graph in the
fixture and the three example games.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-12 22:41:14 +02:00
1 parent 6141d07d4f
commit 42cafa7543
62 files changed
+1682 -144

No files matched your search

+6 -2
View File
@@ -3,8 +3,12 @@ import { type DeclaredPortKind, KIND } from '../properties/kinds';
export type { DeclaredPortKind } from '../properties/kinds';
/** `exec` carries control flow, the others values; `any` accepts every value type. */
export type PortType = 'exec' | 'number' | 'boolean' | 'string' | 'object' | 'list' | 'struct' | 'any';
/**
* `exec` carries control flow, the others values; `any` accepts every value type. `vec3` is a
* colour inside a shader graph, where the values are GLSL and no behavior node ever sees one.
*/
export type PortType =
'exec' | 'number' | 'boolean' | 'string' | 'object' | 'list' | 'struct' | 'vec3' | 'any';
export interface PortRef {
node: string;
+8 -3
View File
@@ -16,8 +16,11 @@ export interface PortDef {
field?: PropertyDef;
}
/** `state` is the one category no behavior graph offers: its nodes are the states of a state machine. */
export type NodeCategory = 'event' | 'flow' | 'data' | 'variable' | 'action' | 'state';
/**
* `state` and `shader` are the categories no behavior graph offers: their nodes are the states of
* a state machine and the GLSL of a shader asset.
*/
export type NodeCategory = 'event' | 'flow' | 'data' | 'variable' | 'action' | 'state' | 'shader';
/**
* How a loop node asks for one of its exec outputs to be run repeatedly: `port` carries the body,
@@ -134,13 +137,15 @@ export function hasExecInput(def: NodeDef): boolean {
/**
* Data inputs that may carry an inline value while unconnected. An object is a live handle and a
* struct is assembled from its parts, so neither has a value that could be typed on one line.
* struct is assembled from its parts, so neither has a value that could be typed on one line; a
* shader colour has one only where the node gives it a colour field.
*/
export function inlineInputs(def: NodeDef): PortDef[] {
return def.inputs.filter(isInlinePort);
}
function isInlinePort(port: PortDef): boolean {
if (port.type === 'vec3') return port.field !== undefined;
return port.type !== 'exec' && port.type !== 'object' && port.type !== 'struct';
}
+4 -1
View File
@@ -88,6 +88,7 @@ import { RunBehavior } from './flow/RunBehavior';
import { Sequence } from './flow/Sequence';
import { SetState } from './flow/SetState';
import { StateBranch } from './flow/StateBranch';
import { SHADER_NODES } from '../../shader/nodes';
import { State } from '../stateMachine';
import { Variables } from './variable/Variables';
@@ -187,5 +188,7 @@ export const BUILT_IN_NODES: readonly NodeDef[] = [
];
for (const def of BUILT_IN_NODES) registerNode(def);
// Registered so a machine's graph loads and draws, but not built in: no behavior graph offers it.
// Registered so a machine's or a shader's graph loads and draws, but not built in: no behavior
// graph offers them.
registerNode(State);
for (const def of SHADER_NODES) registerNode(def);