Shader assets: graph-built shaders, the Shader tab and sprite rows from the graph (#62)
game-maker / suite (push) Failing after 3m59s
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:
1 parent
6141d07d4f
commit
42cafa7543
62 files changed
+1682
-144
No files matched your search
@@ -42,8 +42,8 @@ export class ApplyOverrideToAssetCommand extends ObjectEditCommand {
|
||||
|
||||
protected override apply(ref: ObjectRef, project: Project): void {
|
||||
const asset = requireAsset(project, ref.object.assetId);
|
||||
requirePropDef(asset, this.key);
|
||||
const value = resolveSceneObjectProps(asset, ref.object)[this.key];
|
||||
requirePropDef(project, asset, this.key, ref.object);
|
||||
const value = resolveSceneObjectProps(project, asset, ref.object)[this.key];
|
||||
this.asset = asset;
|
||||
this.previousAssetValue = asset.props[this.key];
|
||||
asset.props[this.key] = value!;
|
||||
|
||||
@@ -36,6 +36,8 @@ export function buildAsset(type: AssetType, name: string, id = newId()): Asset {
|
||||
return { ...base, type: 'animation', frames: [] };
|
||||
case 'statemachine':
|
||||
return { ...base, type: 'statemachine', graph: createEmptyGraph() };
|
||||
case 'shader':
|
||||
return { ...base, type: 'shader', graph: createEmptyGraph() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +59,7 @@ export class CreateAssetCommand implements Command {
|
||||
|
||||
execute(project: Project): void {
|
||||
for (const [key, value] of Object.entries(this.props))
|
||||
this.asset.props[key] = coerceValue(requirePropDef(this.asset, key), value);
|
||||
this.asset.props[key] = coerceValue(requirePropDef(project, this.asset, key), value);
|
||||
project.assets.push(this.asset);
|
||||
this.previousActiveScene = project.activeSceneId;
|
||||
if (this.asset.type === 'scene' && !project.activeSceneId) project.activeSceneId = this.asset.id;
|
||||
@@ -195,8 +197,8 @@ export class SetAssetPropertyCommand extends AssetPropertyCommand {
|
||||
super(assetId, key, `Set ${key}`);
|
||||
}
|
||||
|
||||
protected override computeNext(asset: Asset): PropertyValue {
|
||||
return coerceValue(requirePropDef(asset, this.key), this.value);
|
||||
protected override computeNext(asset: Asset, project: Project): PropertyValue {
|
||||
return coerceValue(requirePropDef(project, asset, this.key), this.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,8 +207,8 @@ export class ResetAssetPropertyCommand extends AssetPropertyCommand {
|
||||
super(assetId, key, `Reset ${key}`);
|
||||
}
|
||||
|
||||
protected override computeNext(asset: Asset): PropertyValue {
|
||||
return requirePropDef(asset, this.key).default;
|
||||
protected override computeNext(asset: Asset, project: Project): PropertyValue {
|
||||
return requirePropDef(project, asset, this.key).default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export class AddColliderCommand implements Command {
|
||||
this.assetId,
|
||||
);
|
||||
if (targetAsset.type === 'sprite') {
|
||||
const props = resolveSceneObjectProps(targetAsset, target);
|
||||
const props = resolveSceneObjectProps(project, targetAsset, target);
|
||||
asset.props.width = Number(props.width);
|
||||
asset.props.height = Number(props.height);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
type Project,
|
||||
} from '../model/Project';
|
||||
import type { SceneObject } from '../model/SceneObject';
|
||||
import { propDef, type PropertyDef } from '../properties/PropertySchema';
|
||||
import { type PropertyDef, schemaForAsset, schemaForObject } from '../properties/PropertySchema';
|
||||
import { CommandError } from './Command';
|
||||
|
||||
export function requireAsset(project: Project, assetId: string): Asset {
|
||||
@@ -91,8 +91,15 @@ export function requireNodeDef(type: string): NodeDef {
|
||||
return def;
|
||||
}
|
||||
|
||||
export function requirePropDef(asset: Asset, key: string): PropertyDef {
|
||||
const def = propDef(asset, key);
|
||||
/** The row `key` names on the asset – or, given the placed object, on that object (its shader's rows). */
|
||||
export function requirePropDef(
|
||||
project: Project,
|
||||
asset: Asset,
|
||||
key: string,
|
||||
object?: SceneObject,
|
||||
): PropertyDef {
|
||||
const schema = object ? schemaForObject(project, asset, object) : schemaForAsset(project, asset);
|
||||
const def = schema.find((d) => d.key === key);
|
||||
if (!def) throw new CommandError(`Property "${key}" is not defined for ${asset.type}`);
|
||||
return def;
|
||||
}
|
||||
@@ -189,7 +189,10 @@ export class SetOverrideCommand extends OverrideCommand {
|
||||
}
|
||||
|
||||
protected override nextValue(object: SceneObject, project: Project): PropertyValue {
|
||||
return coerceValue(requirePropDef(requireAsset(project, object.assetId), this.key), this.value);
|
||||
return coerceValue(
|
||||
requirePropDef(project, requireAsset(project, object.assetId), this.key, object),
|
||||
this.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user