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

+13 -3
View File
@@ -18,6 +18,7 @@ import { HierarchyPanel } from './panels/HierarchyPanel';
import { Toolbar } from './panels/Toolbar';
import { type PlayHost, PlaySession, type WorldSnapshot } from './PlaySession';
import { ProjectSession } from './ProjectSession';
import { ShaderEditor } from './shader/ShaderEditor';
import { StateMachineEditor } from './statemachine/StateMachineEditor';
import { installShortcuts } from './shortcuts';
import type { EditorState } from './state';
@@ -25,13 +26,14 @@ import { TextureEditor } from './texture/TextureEditor';
import { installTextureImport } from './textureImport';
export type CentreTab =
'scene' | 'graph' | 'statemachine' | 'game' | 'texture' | 'animation' | 'container' | 'list';
'scene' | 'graph' | 'statemachine' | 'shader' | 'game' | 'texture' | 'animation' | 'container' | 'list';
const TAB_ORDER = [
'scene',
'game',
'graph',
'statemachine',
'shader',
'texture',
'animation',
'container',
@@ -43,6 +45,7 @@ const TAB_LABELS: Record<CentreTab, string> = {
game: 'Game',
graph: 'Behavior',
statemachine: 'State machine',
shader: 'Shader',
texture: 'Texture',
animation: 'Animation',
container: 'Container',
@@ -69,6 +72,7 @@ export class Editor implements PlayHost {
readonly gameView: GameViewport;
readonly graphEditor: GraphEditor;
readonly stateMachineEditor: StateMachineEditor;
readonly shaderEditor: ShaderEditor;
readonly textureEditor: TextureEditor;
readonly animationEditor: AnimationEditor;
readonly containerEditor: ContainerEditor;
@@ -109,6 +113,7 @@ export class Editor implements PlayHost {
this.gameView = new GameViewport(state);
this.graphEditor = new GraphEditor(state);
this.stateMachineEditor = new StateMachineEditor(state);
this.shaderEditor = new ShaderEditor(state);
this.textureEditor = new TextureEditor(state);
this.animationEditor = new AnimationEditor(state);
this.containerEditor = new ContainerEditor(state);
@@ -154,6 +159,7 @@ export class Editor implements PlayHost {
game: this.gameView,
graph: this.graphEditor,
statemachine: this.stateMachineEditor,
shader: this.shaderEditor,
texture: this.textureEditor,
animation: this.animationEditor,
container: this.containerEditor,
@@ -164,6 +170,7 @@ export class Editor implements PlayHost {
game: this.tabButton('game'),
graph: this.tabButton('graph'),
statemachine: this.tabButton('statemachine'),
shader: this.tabButton('shader'),
texture: this.tabButton('texture'),
animation: this.tabButton('animation'),
container: this.tabButton('container'),
@@ -216,13 +223,16 @@ export class Editor implements PlayHost {
app.ticker.add((ticker) => this.tick(ticker.deltaMS / 1000));
// A node, a frame and a template object exist only in their own tab, so selecting one
// switches to it; selecting the behavior, texture or container asset itself does not. A state
// machine asset does switch (user's choice): its tab is the only place it shows anything.
// machine or shader asset does switch (user's choice): its tab is the only place it shows anything.
state.on('selection', () => {
const s = state.selection;
const machine = state.selectedStateMachineId !== null;
if (s?.kind === 'node' && !machine && this.tab !== 'graph') this.showTab('graph');
const shader = state.selectedShaderId !== null;
if (s?.kind === 'node' && !machine && !shader && this.tab !== 'graph') this.showTab('graph');
if ((s?.kind === 'node' || s?.kind === 'asset') && machine && this.tab !== 'statemachine')
this.showTab('statemachine');
if ((s?.kind === 'node' || s?.kind === 'asset') && shader && this.tab !== 'shader')
this.showTab('shader');
if (s?.kind === 'frame' && this.tab !== 'texture') this.showTab('texture');
if (
s?.kind === 'object' &&