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>
154 lines
4.6 KiB
TypeScript
154 lines
4.6 KiB
TypeScript
/** Design tokens for the canvas UI. Sizes only one widget uses may stay local to it. */
|
|
import { TextStyle } from 'pixi.js';
|
|
|
|
export const Theme = {
|
|
font: 'Inter, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
monoFont: '"JetBrains Mono", Consolas, "Courier New", monospace',
|
|
fontSize: 13,
|
|
smallFontSize: 11,
|
|
viewportLabelSize: 10,
|
|
rowHeight: 26,
|
|
controlHeight: 24,
|
|
padding: 8,
|
|
gap: 6,
|
|
radius: 4,
|
|
fieldPadding: 6,
|
|
checkboxSize: 16,
|
|
swatchSize: 12,
|
|
scrollbarWidth: 6,
|
|
/** Horizontal indent per nesting level in tree lists. */
|
|
treeIndent: 14,
|
|
hoverCursor: 'default',
|
|
colors: {
|
|
background: 0x1b1d22,
|
|
panel: 0x24272e,
|
|
panelHeader: 0x2c3038,
|
|
border: 0x383c46,
|
|
control: 0x16181d,
|
|
controlHover: 0x1e2127,
|
|
controlActive: 0x16181d,
|
|
accent: 0x4c8dff,
|
|
accentText: 0xffffff,
|
|
text: 0xe6e8ee,
|
|
textMuted: 0x8a90a0,
|
|
selection: 0x2b4a80,
|
|
danger: 0xe0553f,
|
|
viewport: 0x121316,
|
|
gizmo: 0x4c8dff,
|
|
/** Behavior symbols and owner links. */
|
|
behavior: 0xb066ff,
|
|
/** Collider outlines: solid (blocking) and trigger (events only). */
|
|
collider: 0x4fd18b,
|
|
trigger: 0xf2c84b,
|
|
container: 0x3fb8c9,
|
|
marquee: 0x4c8dff,
|
|
/** A value deviating from what it follows: an override on a placed object, a non-default on an asset. */
|
|
override: 0xf2c84b,
|
|
/** Node graph: canvas, node chrome, per-category title colors, port colors, live highlight. */
|
|
graphBackground: 0x15171b,
|
|
node: 0x262a32,
|
|
nodeBorder: 0x3b404b,
|
|
nodeSelected: 0x4c8dff,
|
|
categoryEvent: 0xc0392b,
|
|
categoryFlow: 0x7f8c8d,
|
|
categoryData: 0x2e8b57,
|
|
categoryVariable: 0xb8860b,
|
|
categoryAction: 0x2f6fd6,
|
|
categoryState: 0x8e5ad6,
|
|
categoryShader: 0x1f8f8f,
|
|
portExec: 0xffffff,
|
|
portNumber: 0x6fcf97,
|
|
portBoolean: 0xe57373,
|
|
portString: 0xe6a8ff,
|
|
portObject: 0x56ccf2,
|
|
portList: 0xf2a75c,
|
|
portStruct: 0xd4c25a,
|
|
portVec3: 0xff9ad5,
|
|
portAny: 0xbdbdbd,
|
|
/** Ring around the port a running edge drag would connect to. */
|
|
portTarget: 0xffffff,
|
|
hot: 0xffc857,
|
|
},
|
|
} as const;
|
|
|
|
const styleCache = new Map<string, TextStyle>();
|
|
|
|
export type TextStyleToken =
|
|
| 'body'
|
|
| 'bodyBold'
|
|
| 'muted'
|
|
| 'override'
|
|
| 'small'
|
|
| 'warning'
|
|
| 'live'
|
|
| 'title'
|
|
| 'mono'
|
|
| 'monoMuted'
|
|
| 'monoWarn'
|
|
| 'monoError'
|
|
| 'accent'
|
|
| 'viewportLabel'
|
|
| 'viewportLabelMuted';
|
|
|
|
/** Shared TextStyle instances so Pixi can cache glyph measurements per token. */
|
|
export function textStyle(token: TextStyleToken = 'body'): TextStyle {
|
|
let style = styleCache.get(token);
|
|
if (style) return style;
|
|
const base = { fontFamily: Theme.font, fontSize: Theme.fontSize, fill: Theme.colors.text };
|
|
switch (token) {
|
|
case 'body':
|
|
style = new TextStyle(base);
|
|
break;
|
|
case 'bodyBold':
|
|
style = new TextStyle({ ...base, fontWeight: '600' });
|
|
break;
|
|
case 'muted':
|
|
style = new TextStyle({ ...base, fill: Theme.colors.textMuted });
|
|
break;
|
|
case 'override':
|
|
style = new TextStyle({ ...base, fill: Theme.colors.override });
|
|
break;
|
|
case 'small':
|
|
style = new TextStyle({ ...base, fontSize: Theme.smallFontSize, fill: Theme.colors.textMuted });
|
|
break;
|
|
case 'warning':
|
|
style = new TextStyle({ ...base, fontSize: Theme.smallFontSize, fill: Theme.colors.danger });
|
|
break;
|
|
case 'live':
|
|
style = new TextStyle({ ...base, fontSize: Theme.smallFontSize, fill: Theme.colors.hot });
|
|
break;
|
|
case 'title':
|
|
style = new TextStyle({
|
|
...base,
|
|
fontSize: Theme.smallFontSize,
|
|
fontWeight: '700',
|
|
letterSpacing: 0.5,
|
|
fill: Theme.colors.textMuted,
|
|
});
|
|
break;
|
|
case 'mono':
|
|
style = new TextStyle({ ...base, fontFamily: Theme.monoFont });
|
|
break;
|
|
case 'monoMuted':
|
|
style = new TextStyle({ ...base, fontFamily: Theme.monoFont, fill: Theme.colors.textMuted });
|
|
break;
|
|
case 'monoWarn':
|
|
style = new TextStyle({ ...base, fontFamily: Theme.monoFont, fill: Theme.colors.override });
|
|
break;
|
|
case 'monoError':
|
|
style = new TextStyle({ ...base, fontFamily: Theme.monoFont, fill: Theme.colors.danger });
|
|
break;
|
|
case 'accent':
|
|
style = new TextStyle({ ...base, fill: Theme.colors.accentText, fontWeight: '600' });
|
|
break;
|
|
case 'viewportLabel':
|
|
style = new TextStyle({ ...base, fontSize: Theme.viewportLabelSize });
|
|
break;
|
|
case 'viewportLabelMuted':
|
|
style = new TextStyle({ ...base, fontSize: Theme.viewportLabelSize, fill: Theme.colors.textMuted });
|
|
break;
|
|
}
|
|
styleCache.set(token, style);
|
|
return style;
|
|
}
|