b1173ba6bb6cbc1981cddf0dd2b683bf746ee5d5
26
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4d0a696327 |
Keep composition sound in step and give compositions a bus of their own
A composition's sound ran on the audio clock while its picture ran on the frames. A frame counts at most 0.1 s, so after a hitch the sound stayed ahead of the picture until the next stop. Songs in a trailer drifted off the cut. The items of a composition also had no bus of their own, and a video sprite could not pick where its sound goes. - CompositionSound.follow compares the audio clock with the picture each frame. More than 40 ms apart, it starts the sound again where the picture is. This holds in the tab and in a run. - A time scale other than 1 now restarts the sound again and again. It stays in time but comes in pieces. - The sprite of a video item shows "Driven (by composition)" as a fixed Video clock row. Video time is hidden there, because the composition sets it every frame. - Every composition has a bus in the mix and a node in the master routing. A new one goes to the master unless other compositions are linked elsewhere, apart from where the sounds go. - Audio items pick From asset, To composition, Master or a bus. New items start with To composition. Items saved before keep From asset, so music already sent through a bus does not bypass it. - Video sprites have a new row Video bus: From asset by default, the master or a bus. In a composition the default is the composition's bus, also for video sprites inside a container item. - The chosen bus is part of the key of the video player, so a sprite with another bus gets a player of its own. Found along the way: - Six tests with full lists of sprite defaults expected the old rows and now list Video bus too. Tests: - tsc, eslint, Prettier clean - Unit: 971 green in the 28 files touched - npm run check on melektaus-atx: green, 309 files, 4804 tests - e2e 68 (melektaus-atx): 13 checks green, 68i new. The sound item and the video item go into mix:cp68-cut, which goes to the master. - e2e 69 (melektaus-atx): ALL PASSED, 23 checks, 69q and 69r new. After a hitch of 500 ms the sound restarted twice and then lay 0.5 to 5 ms off the playhead. - Counter-checks in unit tests: without the comparison the hitch test fails, without the bus in the preload the run test fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
acd12326dc |
Fade sounds and videos in and out on the items of a composition
A trailer needs its music and its clips to come in softly and leave
softly. Until now an item of a composition could only play at one
level, and a video item could not even be turned down on its own.
- Every item with sound gets a grip at its upper left and upper right
corner. Dragging one inwards fades the item in or out. Dragging it
back to the edge removes the fade. Lower down the same edge still
trims as before.
- The fade is drawn as its curve, with the part above it darkened.
The inspector shows Fade in and Fade out in seconds, each with the
curves sound clips already know.
- The model keeps fadeIn and fadeOut in frames plus curveIn and
curveOut on the item. Old projects load unchanged. An item shorter
than its fades plays them cut to its length but keeps the setting.
- Sound, pattern and song items ramp the gain of their own bus. The
scheduler plans the ramps on the audio clock next to the notes.
Starting in the middle of a fade picks it up from there.
- Video items set the new sprite property Video volume each frame.
It multiplies with the fade and is only shown for a driven video.
The player glides to each new level over 15 ms so it does not click
between frames.
Not covered: a container item that carries a video further down gets
no grips. Only a video on the item's own sprite counts.
Tests:
- tsc, eslint, Prettier clean.
- Unit tests for composition, music, song and sound (12 files): 269
passed, 7 of them new.
- e2e 69 on melektaus-atx: ALL PASSED, 21 checks. 69p drags a grip to
a fade in of 10 frames and hears the item bus rise from 0.127 over
0.229 and 0.339 to 1 within one second.
- Counter-checks as unit tests: without the audio ramps, and without
the level on the video sprite in the game, both go red.
- Gate on melektaus-atx: 309 files, 4796 tests passed, 8 more than
at
|
||
|
|
c9e8a3f6ac |
Let an animation drive a sprite's video picture by picture (#404)
A video used to run on its own clock as soon as a sprite wore it. An animation could switch the sprite on and off, but never say which picture shows at which frame. Cutting a video in an animation needs the opposite: the animation sets the time and the video follows. - Sprites wearing a video or a clip get two rows, Video clock and Video time. They show only while the texture holds a video. - With Video clock on Driven the video does not play by itself. It shows the picture at Video time, counted from the clip's start. Past the end it goes round with Loop and holds the last picture without. - Video time is a number like any other, so keys, step, easing and curves give stills, slow motion and ramps. - A driven sprite gets a player of its own, keyed by the wearer's name. The same clip can run twice at different times. - Following has two ways (`videoFollow.ts`). Running forward at 0.25x to 4x the video plays at that rate and is nudged. A still, a scrub or a step backwards seeks, and only the newest seek counts. - Sound is heard only near 1x. The animation tab now plays it too, so a cut can follow the sound. Scrubbing is silent. - Scene, game view, the inspector's PREVIEW and the shader preview show the driven picture. In a running game Play animation sets it. Found on the way: - After a scrub the video in the animation tab kept running. The preview redrew only while the playhead moved, so nobody asked for the video once it stood. `AnimationEditor.tick` now redraws it every frame while it shows a video. - Every sprite has two more defaults (`videoClock: 'free'`, `videoTime: 0`). Eight tests in five files pinned the old list and are updated. Tests: - Unit: video-clock and video-follow new, 4 files with 42 tests green. - e2e 66 (melektaus-atx): ALL PASSED, 22 checks, 3 new. 66i: two sprites on one clip stand at 0.2 s red and 0.7 s green. 66j: a scrub to frames 2, 7, 12 and 3 shows red, green, blue, red, and each colour still stands 0.7 s later. 66k: playing runs 10-30 ms behind at rate 1.00-1.03 and is not muted. - Counterchecks: a seek that keeps the rate turns the seek test red. Not seeing Driven turns 66i, 66j and 66k red. - Gate (melektaus-atx): exit 0, 297 files, 4546 tests. - Not tested in the browser: Play animation in a running game. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b2326085ed |
Show each camera only its layers and lay overlay cameras on top (#302)
A camera could only show the whole scene, so a HUD drawn in the world would run through a camera shader (#299) with everything else. Render layers say which cameras see an object, and overlay cameras draw their own picture over the main one. - The project has a list of up to 16 render layers, edited in Project settings next to the collision layers. It is a list of its own, read by the same rules (`layerNamesOf`). - Sprites, texts, tilemaps, particle sources and containers carry a row `Render layer` under their switches. Its default `Inherit` takes the parent's layer, at the top the first one. - A camera has `Sees` (all layers by default) and `Overlay`. The main camera is the first one switched on without Overlay, so two plain cameras still draw through the first one only. - Every view through a camera keeps only what that camera sees and lays one see-through view per overlay camera over itself. That view is a `WorldViewport` of its own, handed its view and frame from below. - An overlay is fitted into the main camera's whole picture without distortion. One of the same size and zoom covers it exactly. - `z` sorts within one camera only. The pictures lie on top of each other as a whole, which is what a shader per camera (#299) needs. - The Game tab's preview now collects the scene once per redraw. Before it collected it twice, with the cameras it would have been five times. - `SetCollisionLayersCommand` became `SetLayerNamesCommand`, which takes the list it sets. Follow-ups: #304 (the mouse through a chosen camera) and #305 (change the render layer at run time). Tests: - Gate: 226 files, 3487 tests (3480 + 7) - e2e 63 (new): 4 checks. A green overlay sprite at z -10 covers a red main sprite at z 1000, in the preview and in the running game. A `UI` sprite in front of the main camera and a `Default` one in front of the overlay stay away. Without Overlay the second camera draws nothing. The settings dialog adds a render layer at the end. - Counter-checks: inheriting from parents switched off fails 1 unit test. Overlays never drawn fails the two overlay checks in e2e 63. - e2e total 1720 (1716 + 4), computed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f03ca0d382 |
Draw a shader in passes with a Pass node (#301)
A Blur stops at radius 8 in one pass, and bloom needs a softened copy of the picture beside the original. A Pass node cuts the graph: what feeds it is drawn into a picture of its own first, and the nodes that read a picture read that one when it feeds them. - Pass has color and alpha like the Output, a Resolution setting (Full, Half, Quarter) and a picture output. Texture color, Texture alpha, Sample texture, Blur and Texture size get a picture input. Unconnected it is the wearer's own picture, so the original stays readable beside any pass. - picture is a port type of its own. It plugs only into a picture input, not even into an any port. - The walk shared by the compilers can stop at a node (cut). The shader compiler draws each Pass it meets as a fragment of its own, earlier passes first. A ring through a picture says Feeds itself, and more than 8 passes say so at the node. - A pass draws untinted. The tint comes on when the last part reads a picture, so a particle source draws its passes once for all of its particles (user decision). - A pass's picture is the wearer's picture and its Padding, at the pixels of the picture times Resolution, at most 2048 per side. It is read with the picture's own filter and continues past its frame as the Output's Edge says. - PassPictures keeps one render texture per pass and wearer. It draws again only when picture, size, Padding or a uniform changed. A field's picture is a render texture that changes under the same id, so a field draws its passes every time. - Sprite, sliced sprite, text, particle source, field shader and the Shader tab's preview all draw passes. syncShader takes a fixed picture for a 9-slice, which holds its corners but keeps the margin. - texelAt and blur take the sampler they read. Existing shaders compile to the same program apart from that argument. - A field shader's Blur and Texture size count a pixel as a unit of the frame (uPixelScale), not of the screen. Before, a field's blur grew when zooming out and shrank when zooming in. This came with #170 and #300 and is fixed here because passes inherit it. - tools/perf-shaders.mjs and tools/perf-field-shaders.mjs measure two passes with GM_PERF_PASSES=1 and GM_PERF_PASS_RESOLUTION. Below Full an open Pass shrinks the picture first, as the wiki's recipe does. Found on the way: - Destroying the pictures before the shader made Pixi warn that a texture was still bound. The shader goes first now, and a picture of a new size is resized rather than replaced. - Two passes in a row could draw plain white the first time. Pixi builds the code that binds a program's resources once and finds them by position. A pass of one graph is often the same program as a pass of another with fewer slots, so it bound a placeholder. Every shader now declares all 8 pass slots and its uniform group. Tests: - Gate on melektaus-atx: 225 files, 3480 tests (3467 + 13), exit 0. - e2e 28 and 31 on melektaus-atx: 97 checks (94 + 3) and 44 checks (43 + 1), all passed, no Pixi warning in the console. - 28l-vii: a Blur across, a Pass and a Blur down draw the 5x5 spot of a Blur of Both (difference 0.000). On a grey sprite a pass's picture added to the original is 231/60/60, each tinted once. Two Passes in a row after a graph with one show red and green, not white. - 31v-iii: a Blur of 8 fades a field's frame edge over 8.0 units at 50 % and at 200 % zoom. - Counter-checks: a tinted pass fails 1 unit test. Pictures never bound fail both e2e checks (spot 0.20 instead of 0.04, 243/158/158). Pass slots by the number of passes draw #ffffff, and a field without its pixel scale ramps over 16 and 4 units: exactly the two new checks fail. - e2e sum 1716 is counted, not yet measured (1712 + 4). - Measured on stein2 (HD 630, one run per row): 50 field shaders at radius 8 go from 11.4 to 41.3 fps in two passes, 44.4 at radius 16 (three passes at Half). 800 sprites at radius 8 go from 13.9 to 24.5 fps. At radius 4 one pass stays faster from 400 sprites on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bf27e42e8a |
Let a shader declare a color the sprite sets (#298)
A shader could only ask its sprites for numbers. A tint, an outline colour or a glow colour had to be built from three Property nodes. - New node Color property next to Property: Name and Default (a colour, white unless picked), output `color`. It becomes a colour row below the Shader dropdown and a vec3 uniform in the program. - Number and colour properties share one set of names. A clash is the existing "Another property is named" problem. - Like Color it cannot feed the Vertex output. - Placed from the palette it is called tint, then tint2. - The preview in the Shader tab shows a colour field for it. Like the sliders it starts at the sprite's value and never writes into the project. - `declaredRows` takes the row builder, so the particle graph keeps its number rows unchanged. Tests: - Gate: 222 files, 3452 tests (3445 + 7) - e2e 28: 89 checks (28l-v: default colour drawn, then the colour the sprite sets) - e2e total 1704, counted (1703 + 1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e933fad446 |
Give a shader room to draw around the picture it wears (#69)
A shader ran only inside the rectangle of what wears it: the quad has the size of the sprite, and outside of it no fragment runs. An outline or a glow built with Sample texture was cut off at the border. The issue still spoke of Filter.padding, but since #77 the shader is no filter any more, the limit is the geometry. - The Output node has a number Padding next to Edge: so many pixels of the picture per side the wearer draws beyond it. 0 is the default and draws as before, 256 is the most. - The quad grows and its UVs grow with it, so the picture keeps its place and size. In the margin the UVs run on below 0 and above 1. - Transparent is a fourth Edge mode: outside of the picture there is nothing. It is cut in the fragment (texelAt), so it needs no copy of the picture with an address mode of its own. - Edge holds everywhere alike, also for Texture color, Texture alpha and unconnected inputs. - Padding above 0 with Edge on Clamp puts the hint "Padding with Clamp smears the border" on the Output. The shader still compiles. A chosen Clamp and the default cannot be told apart. - All four wearers draw the margin. A sprite counts in pixels of its frame, a text in its units, a particle source grows every particle about its centre. - A nine-slice sprite gets a ring around its nine fields, as wide as so many border pixels. The fields themselves stay. - Without a picture a pixel is one unit of the wearer's own size, or of the particle size. - Particles now take the Edge mode of their shader. It had no effect on them before. - An object wearing a padded shader is never culled, or its margin would vanish at the edge of the screen. - The preview in the shader tab shows the margin and leaves room for it. - Picking, the selection frame, the size and the collider stay with the rectangle without the margin. Tests: - Gate on melektaus-atx right before this commit: 216 files, 3336 tests (3319 + 17), exit 0. - e2e 28,30,31,37,41 on melektaus-atx: 178 checks, all pass. e2e 1-37,47,48,58 ran before the last change (no culling with padding): 1281 checks, all pass. - 17 new unit tests: the compiler (padding, Transparent, the hint) and the geometry (quad, nine-slice ring). - Seven new e2e checks: four at the sprite in module 28, one each for text, particles and nine-slice. - 17 unit counter-probes all fail their tests. Three browser counter-probes fail their checks (5, 3 and 1 of them). - Three screenshots looked at: the sprite with Clamp and margin in the scene, the preview in the shader tab, the text. - The e2e sum of 1687 is counted (1680 + 7), the full suite and the smokes did not run. - Not seen: the hint at the node in a picture, particles and nine-slice in a picture, the game view while playing, sprites without a picture, vector and pixel art pictures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f02adabcf9 |
Show the type an arithmetic shader node really puts out (#219)
The result of Add, Multiply, Mix and the other arithmetic nodes of a shader graph was drawn as any, whatever went in. The compiler already lifts a colour on any side to a colour result, so the pin said less than the code knew. A colour result could also be wired into a number input, and the shader then failed to compile. - liftedType in core/shader/nodes.ts is the one rule. The compiler reads it when it lifts two operands, and the editor reads it through liftedPortType for the ports it draws. - A SharedPortGroup may bring its own rule as agree. Without one it is agreedType, as before. The thirteen arithmetic nodes share their type by liftedPortType. - Only the any inputs decide. An input nothing feeds counts as the number typed into it. t, edge, exponent, min and max have no say. - The type travels through a chain of such nodes without code of its own, because #210 hands a shared type on. - In a ring the result stays any, unless a colour has settled it. - A number may feed a colour input. Without that a number result no longer fitted Output.color, although the compiler spreads it over three channels. The rule sits in portsCompatible, but only the shader graph has colour ports. - A colour result no longer fits a number input. An edge laid before the colour came in stays and is drawn in the danger colour, and the node at its end names the problem. - The nine shaders in the stored projects (108 edges) all stay valid under the new rule. Tests: - Gate on melektaus-atx: 212 files, 3260 tests (3240 + 20), exit 0. The gate right before this commit ran on the tree of this and the next commit together, with the same numbers. - e2e 28 on melektaus-atx: 81 checks, all pass. - e2e 1-31: 1059 pass, 1 fail in module 18 (the editor clock read 1.97 s after a stop). A rerun of 1-18 passed with 602 checks and 0.18 s. 1-31 was not run in full again. - No full run and no smokes. The sum of 1676 (1673 + 3) is reckoned. - Twenty unit tests in shader-port-types.test.ts, one of them runs all thirteen nodes through every mix of number and colour and compares what is drawn with the code made. - Two tests in shaders.test.ts now lay the edge first and bring the colour in after, the only order that still wires such a graph. - Three e2e checks in module 28 with the real mouse: a colour into Multiply, the red edge with its message, and the colour result refused at alpha and taken at color. - Fifteen unit counter-probes and two browser counter-probes all fail their tests. - Not checked in the browser: the one-input nodes, Mix and the ring, and a number wired straight into a colour input. Nothing was looked at after the build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1aa824ecb4 |
Keep objects through a Load scene with a switch (#165)
A Load scene destroyed every object of the old scene. A player, a HUD or a music object had to be built again in each scene, with its state pushed through shared variables. A top-level object with the new switch Keep on scene load now travels into the next scene as the same entity, with everything below it. - The switch is a common property right under Enabled, off by default, on the asset and on a placed object. The inspector shows the row on top-level objects of a scene only, as answered in the issue. - runtime/keptObjects.ts holds the rules as pure functions. keptEntities picks what travels, objectsToBring copies the stored objects as the run parents them, and bringObjects puts them into the next scene. - World.instantiate takes a handed entity as it is instead of making one. The next syncToModel then writes the run's values into the scene. - BehaviorSystem.release takes the running instances out before the old world is destroyed, and the next system adopts them. They hear no On destroy and no second On start, and their sounds play on. - PhysicsSystem.resume gives a dynamic body the velocity and spin it had. - Duplicates: the object brought along wins. The next scene does not build its own object with the same id, which is the way back into the scene the object came from. - Decided here: the next scene does not build a top-level object of the same asset that is kept itself either. The issue only names the id. With the id alone a level that places its own player would hold two after a swap. - Decided here: kept objects land behind the scene's own, the switch is no animation row, and collisions are found anew. A finding, fixed along with it: Load scene did not build a scene as it is stored, but as the run had left it. A moved object stayed moved and a destroyed one stayed gone. The way back into a scene needs a clean build. - GameRun copies a scene's objects and groups before it first builds it and puts them back before it builds it again. - GameRun.end puts every such scene back. The player calls it on stop, so spawned objects no longer stay for "Click to play again". - The consequence: an edit made in a scene during Play is gone the next time that scene is loaded. Tests: - Gate: 199 files, 2944 tests (2929 + 15), exit 0 - e2e, full run: 1625 checks passed (1619 + 6), exit 0 - Smokes: 24 / 19 / 21, exit 0 - 15 unit tests in tests/core/keep-on-scene-load.test.ts - Six e2e checks in module 35: the switch is set with a real mouse, the child has no row, the object is in the new scene, its counter still reads 1, its sound plays on, and the stored scenes are unchanged after Stop - Eleven tests with fixed row lists only count the new schema row - 16 unit counter-probes all fail tests, run on stein2. One did not fail at first (same id not left out), it has its own test now. - The browser counter-probe fails 4 of the 6 new checks - Not looked at in the browser: the switch as a port of the Properties node, and a released game with a kept object Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
14972d057f |
Refactoring round 8: hide data files, safe saves, Esc as Cancel (#85)
Recurring cleanup round over the code since round 7 (
|
||
|
|
8b44f97c35 |
Let a child sort with its parent so its Z stays local (#232)
An animated or set Z of -1 on a weapon put it behind everything on Z 0, not just behind the player holding it. A child can now opt in to being drawn at its parent's place, so its own Z only orders it against the parent and its siblings. - New property "Sort with parent" on sprites, texts and particle emitters, shown in the inspector right under Z. It is a normal property, set on the asset and overridable per object. - With it on, the rest of the scene sees only the parent's Z and, where the layer sorts by Y, the parent's feet. Below 0 the child is drawn behind the parent, from 0 on in front. - It works across levels: a grandchild with the switch hangs on the top object of the chain. - It has no effect under a parent that is not drawn itself (container, behavior, camera, collider) or under a tilemap. - New assets start with it on, saved ones read as off, so old projects draw unchanged. For that a schema row now has "initial" next to "default". The gold "changed" mark and reset follow "initial", so a fresh sprite is not marked as changed. No load migration is needed. - parentGroups() in drawOrder.ts gives a slot only to the top of a chain and inserts the children there. Editor, play mode and picking all use it, so they agree. Tests: - 10 new unit tests in tests/viewport/sort-with-parent.test.ts. - 8 existing tests list the sprite rows or defaults and got the row. - New e2e check 5b-ii clicks the switch and checks order and undo. - Counter-checks, all originals restored by cmp: switch ignored fails 7, children not sorted by Z fails 6, no chain fails 1, "initial" ignored fails 9, row missing in the inspector fails e2e 5. - ./check.sh: 166 files, 2426 tests, CHECK EXIT 0. - e2e 5: ALL PASSED, 13 checks. Check total 1398, computed only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cc6db5f350 |
Three stores, three importers and three pickers that differ only in their type are one of each (#85)
Refactoring round one: HttpFontStore/HttpSoundStore/HttpTextureStore collapse into a generic HttpFileStore over a FileStore contract; fontImport/soundImport/textureImport share assetImport with an ImportKind per sort; ImagePicker/FontPicker/SoundPicker sit on FilePicker and describe only their row. The group/comment drag logic leaves GraphCanvas for annotationDrag.ts (with its own unit test), declaredRows.ts replaces the duplicated row build in particles.ts and shaders.ts, and dead code in font/sound/compile/emission/transform/actions is gone. README: asset list, check count 958, the two-job CI, the Scenes wiki page. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
c990dbcb26 |
A name that a sprite already owns cannot name a property, and a division by zero cannot answer (#63, #64)
game-maker / suite (push) Failing after 11m29s
#63: a shader Property node named "width" quietly took over the sprite row of the same name. isSpriteProp lives in PropertySchema now and is derived from FULL_SCHEMAS.sprite instead of being a second list that drifts. isValidPropertyName rejects those ten names, and the compiler reports it at the node as its own problem: "width" is a sprite property, told apart from "not a word" and from a duplicate. #64: Divide emitted (a / b) and handed NaN to the driver. It emits divide(a, b) now, with the guard in the prologue next to straight(), scalar and per channel: zero divided by zero is zero. That was already the house rule in the behavior and particle graphs - only the shader had never been told. Clamp comes along as a shader node for the same reason: the behavior catalog has had it all along. |
||
|
|
2637feb715 |
A square root is one node everywhere else, so the shader graph gets its own (#92)
game-maker / suite (push) Successful in 10m29s
`Sqrt` already exists in the behavior graph (`data/Sqrt.ts`) and in particles (`ParticleSqrt`); the shader was the only graph without it. `Pow` with exponent 0.5 does the same job, so this is convenience, not a missing capability -- a radial falloff no longer needs a node whose purpose has to be read off its parameter. Like `Pow` it cannot go through `unary()`: GLSL leaves `sqrt` undefined below 0, so the value is held there with `max(value, 0.0)`. That form takes a float second argument for a `vec3` too, so unlike `pow` the exponent broadcast has no counterpart here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e0c459ce92 |
Shader graph: Clamp is the Output's default edge, and the sheet's own mode is a constant of its own (#81)
game-maker / suite (push) Successful in 9m16s
The default of the Edge param and the address mode the shared sheet physically
carries were the same constant; changing the value would have turned every
sentinel with it and given each shader sprite a full copy of its texture.
SHEET_EDGE ('mirror', what TextureLibrary uploads) is now separate from
DEFAULT_EDGE ('clamp'). A graph whose Sample reads nothing but its own pixel
draws with the plain sheet whatever the Edge says, so the common shader costs
no second copy.
Without a shader the quad's coordinates never leave 0..1, and mirror-repeat
reads like clamp within a texel - so clamp is what a sprite shows anyway.
|
||
|
|
28c0789b19 |
Shader graph: Abs node, the distance from 0 per channel
game-maker / suite (push) Failing after 8m10s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a399795772 |
Shader graph: Pow node, base held at 0, exponent broadcast for colours (#80)
game-maker / suite (push) Failing after 8m13s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
102a649a35 |
Shader library: fingerprint without node positions, a drag no longer recompiles (#65)
game-maker / suite (push) Successful in 9m5s
shaderFingerprint(graph) covers node id/type/params/ports and edge endpoints only; x/y, collapsed, folded and edge ids stay out. ShaderLibrary keys on it and counts compiles (__gm.shaderCompiles()). Measured before: one compile per preview step of a node drag (12 for a harness drag); after: 0, a param change exactly +1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
016e83c9b5 |
Transform: scale, rotation and mirror as properties, world transform as a matrix chain, oriented colliders (#76)
game-maker / suite (push) Successful in 9m5s
Four new rows on sprite, text, collider and container (block TRANSFORM): scale, rotation in degrees clockwise, mirrorX, mirrorY. As properties they get override/reset/apply, loading of old projects, write-back after play and the Properties node for free; camera and behavior have none. The hierarchy composes T*R*S per level (composeAlongChain replaces sumAlongChain), so children rotate and scale with their parent. Reparenting and grouping keep the look (carriedTransform). Drawing goes through placeNode, the gizmo is a polygon, cull and objectRect use the AABB, drags are computed in the parent's system. Colliders are oriented boxes: SAT for box/box, box-circle in the box frame; exitDistance replaces axisSeparation/axisCorrection, moveAndSlide moves along the object's own axes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
f85606427b |
Shader graph: UV, Sample texture, Texture size, Time, Sin/Floor/Fract/Step; edge mode on Output (#78)
game-maker / suite (push) Successful in 8m38s
Fragment-side coordinate nodes instead of vertex nodes: the quad stays the quad, a UV read plus a sample at a computed coordinate covers flip, scroll, wave, pixelate and scanlines. Time is a uniform only when a Time node reaches the Output; a viewport that drew a Time shader redraws from the ticker so the Scene tab animates without a running world. Edge (Mirror/Repeat/Clamp) is a second texture variant in TextureLibrary because WebGL binds no TextureStyle resource of the shader. The compiler now emits #version 300 es first: Pixi only compiles as ES 3.00 when the fragment says so, and textureSize needs it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
0e5e5ef925 |
Shaders draw in the sprite's own pass: a Mesh with the graph's fragment, no filter (#77)
game-maker / suite (push) Successful in 8m24s
A sprite's picture is now a Mesh (unit quad, sibling of its Graphics node, which keeps only the hit area); a worn shader replaces Pixi's fragment in that draw, so there is no intermediate texture and no extra render pass. Measured on the HD 630: 400 shaded sprites hold 60 fps (was 34), 800 hold 56 (was 20). Two Pixi facts the code leans on: a mesh's texture is bound only for Pixi's own shader, so GraphShader.wear hands it over; and MeshPipe caches whether a mesh batches and re-checks it only in a frame without structure changes, so switching a shader on or off calls mesh.unload(). The console panel mirrors console.group/groupCollapsed/groupEnd and fills the %s %d %o %c directives, so Pixi's deprecation warning shows its head, not only its stack. E2E 12 guards against the addChild-on-Graphics warning, 28 counts shaders instead of filters. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
5c1c3c6fd6 |
Properties node: name each shader param by its shader (#66)
game-maker / suite (push) Successful in 8m23s
The + Property menu of the Properties node offered every shader's params for every sprite. Each shader row now carries its shader name, and a name shared by two shaders lists both: "brightness (Adjust colors, Neon glow)". Sprite-owned rows stay unlabelled. The note hangs off a map keyed by the def object, not by the name -- a sprite property and a shader param may share a name (#63), and keying by name would label the wrong row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ccc6dc5b6e |
Shader graph: Number node, a typed constant like Color (#72)
game-maker / suite (push) Canceled after 6m55s
No input, one Value param (step 0.05, drawn on the node), output `value` as a float literal via floatLiteral (2 -> 2.0, NaN -> 0.0). No uniform, no sprite row - that is the difference to Property. The e2e negative check for "no behavior node in the palette" now uses Boolean as its marker, and step 28 types the palette search first because the palette scrolls from twelve entries on. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
3da0ef1be2 |
Shader graph: alpha input on Output, Texture alpha node (#70)
game-maker / suite (push) Successful in 7m55s
Output gains a number input `alpha`; unconnected it reads the texel's alpha, like `color` reads the texel. The epilogue premultiplies with the resolved alpha. New `Texture alpha` node exposes texel.a for maths. PortDef.inline=false keeps the alpha port without an inline field: every number port is inline by default, and a typed default of 0 would have made every shaded sprite invisible. The compiler's texel fallback is typed: colour ports get rgb, number ports get texel.a. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a32b7c6daa |
Adjust colors: brightness adds instead of multiplying (#62)
game-maker / suite (push) Failing after 4m1s
The shipped shader graph gains a `brightness - 1` offset node, so 1 stays neutral and brightness lifts every channel by the same amount; contrast keeps multiplying, saturation keeps mixing with the luma. Fixture, seeds, unit and e2e expectations follow (twelve nodes, 1.25 -> #80c0ff). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
42cafa7543 |
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> |