Sprites.Media.Image.Layers

The image editor's layers panel: the stack of layers and the controls to add, clone, reorder, delete and hide them. Window is a resizable floating window, shown while its own visible flag is true, holding a scrolling list of layer cards over a row of buttons. A card is a selectable option carrying the layer's thumbnail and a visible checkbox. The image has layers and no frames, so a layer edit writes straight into the layers list, with none of the sprite editor's frames indirection. A composite over the button, input, scroll and window primitives and the image model helpers. The Layers button that opens it lives in Sprites.Media.Image.Tool.

Sprites.Media.Image.Layers

Sprites.Media.Image.Layers.Preview Void

Sprites.Media.Image.Layers.Preview(thumb)

One layer's thumbnail preview: a small fixed square on a white ground, the layer drawn to fit, so a transparent layer reads as empty. thumb is the reactive PNG data URL, usually from Sprites.Media.Image.Thumbnail over the layer's grid.

InputTypeDescription
thumbSprites.Reactive.ValueA PNG data URL of the layer's pixels.

Returns nothing.

const doc = Sprites.Media.Image.NewDocument(16, 16, undefined);
const data = Sprites.Reactive.Value(doc);
const layers = Sprites.Object.Field(data, 'layers');
const layer = Sprites.Array.At(layers, 0);
const grid = Sprites.Media.Image.LayerGrid(layer, 16, 16, 16);
const thumb = Sprites.Media.Image.Thumbnail(grid);
Sprites.Media.Image.Layers.Preview(thumb);
A blank layer's thumbnail: transparent, so it reads as an empty white square.

Sprites.Media.Image.Layers.Card Void

Sprites.Media.Image.Layers.Card(layer, index, layers, width, height, tile)

One layer card: a row of a selectable thumbnail and a visible checkbox. The thumbnail is an Option, so a click selects the layer and the selected card darkens; the checkbox is a two way flag written back into the layer through the layers list, so hiding a layer drops it from the flattened view. layer is the layer value, index its position in layers. It builds an Option, so wrap it in a Sprites.Ui.Button.Select over the selected layer.

InputTypeDescription
layerObjectThe layer, { tiles, visible }.
indexNumberThe layer's position in the layers list.
layersSprites.Reactive.ValueThe two way layers list, written when the checkbox toggles.
widthNumberThe document width, for the thumbnail grid.
heightNumberThe document height, for the thumbnail grid.
tileNumberThe tile side of the pixel block.

Returns nothing.

const doc = Sprites.Media.Image.NewDocument(16, 16, undefined);
const data = Sprites.Reactive.Value(doc);
const layers = Sprites.Object.Field(data, 'layers');
const layer = Sprites.Array.At(layers, 0);
const selectedLayer = Sprites.Reactive.Value(0);
Sprites.Ui.Button.Select(selectedLayer, () => {
  Sprites.Media.Image.Layers.Card(layer, 0, layers, 16, 16, 16);
});
A single card: click the thumbnail to select, toggle the box to hide.

Sprites.Media.Image.Layers.List Void

Sprites.Media.Image.Layers.List(layers, selectedLayer, width, height, tile)

The scrolling list of layer cards: a Select over the selected layer so exactly one card darkens, an Each over the layers, and column-reverse so the top layer, drawn last, sits at the top of the list. It scrolls inside the resizable window.

InputTypeDescription
layersSprites.Reactive.ValueThe two way layers list.
selectedLayerSprites.Reactive.ValueThe selected layer index, the one card that darkens.
widthNumberThe document width, for each card's thumbnail.
heightNumberThe document height, for each card's thumbnail.
tileNumberThe tile side of the pixel block.

Returns nothing.

const doc = Sprites.Media.Image.NewDocument(16, 16, undefined);
const data = Sprites.Reactive.Value(doc);
const one = Sprites.Object.Field(data, 'layers');
const front = Sprites.Media.Image.NewLayer(16, 16, 16);
const both = Sprites.Array.InsertAt(one, 1, front);
const layers = Sprites.Reactive.Value(both);
const selectedLayer = Sprites.Reactive.Value(1);
Sprites.Media.Image.Layers.List(layers, selectedLayer, 16, 16, 16);
Sprites.Ui.Dom.Text(' selected = ', selectedLayer);
Two stacked layers, top card first; click to select.

Sprites.Media.Image.Layers.Buttons Void

Sprites.Media.Image.Layers.Buttons(layers, selectedLayer, layerIndex, width, height, tile)

The layer buttons: Add and Clone a layer just above the selected one and select it, Up and Down swap the selected layer with its neighbour and follow it, and Delete removes it unless it is the last layer. Each composes a new layers list and Sets it. Up disables at the top, Down at the bottom, and Delete while one layer is left. layerIndex is the selection clamped to the layer count.

InputTypeDescription
layersSprites.Reactive.ValueThe two way layers list.
selectedLayerSprites.Reactive.ValueThe selection, set to follow the acted-on layer.
layerIndexSprites.Reactive.ValueThe selection clamped to the layer count.
widthNumberThe document width, for a new layer's block.
heightNumberThe document height, for a new layer's block.
tileNumberThe tile side of the pixel block.

Returns nothing.

const doc = Sprites.Media.Image.NewDocument(16, 16, undefined);
const data = Sprites.Reactive.Value(doc);
const layers = Sprites.Object.Field(data, 'layers');
const selectedLayer = Sprites.Reactive.Value(0);
const count = Sprites.Array.Length(layers);
const last = Sprites.Maths.Subtract(count, 1);
const layerIndex = Sprites.Maths.Clamp(selectedLayer, 0, last);
Sprites.Media.Image.Layers.Buttons(layers, selectedLayer, layerIndex, 16, 16, 16);
Sprites.Ui.Dom.Text(' layers = ', count);
Add, Clone, Up, Down and Delete; Delete stays off while one layer is left.

Sprites.Media.Image.Layers.Window Void

Sprites.Media.Image.Layers.Window(visible, layers, selectedLayer, layerIndex, width, height, tile)

The Layers panel window: a resizable floating panel, shown while visible is true, with a close button. It fills as a column, a scrolling list of layer cards over a fixed row of buttons. It owns its live rect, so it keeps its dragged corner and size across a close and reopen. It opens a floating window, so the example below is gated behind a button.

InputTypeDescription
visibleSprites.Reactive.ValueShows the window while true.
layersSprites.Reactive.ValueThe two way layers list.
selectedLayerSprites.Reactive.ValueThe two way selection.
layerIndexSprites.Reactive.ValueThe selection clamped to the layer count.
widthNumberThe document width, for new layers and thumbnails.
heightNumberThe document height, for new layers and thumbnails.
tileNumberThe tile side of the pixel block.

Returns nothing.

const doc = Sprites.Media.Image.NewDocument(16, 16, undefined);
const data = Sprites.Reactive.Value(doc);
const layers = Sprites.Object.Field(data, 'layers');
const selectedLayer = Sprites.Reactive.Value(0);
const count = Sprites.Array.Length(layers);
const last = Sprites.Maths.Subtract(count, 1);
const layerIndex = Sprites.Maths.Clamp(selectedLayer, 0, last);
const visible = Sprites.Reactive.Value(false);
Sprites.Ui.Button.SetValue(visible, true, 'Open Layers window');
Sprites.Media.Image.Layers.Window(visible, layers, selectedLayer, layerIndex, 16, 16, 16);
Open the Layers panel; it carries its own close button.