# `Cauldron2D.Drafter.Client.Sprites`
[🔗](https://github.com/jaman/cauldron/blob/v0.3.0/cauldron_2d_drafter/lib/cauldron_2d/drafter/client/sprites.ex#L2)

Draw lists (`Cauldron2D.DrawList`) drawn by the graphics card, for a scene's `:gpu`
function: each item becomes a `CauldronGPU.Sprite`, each picture a texture uploaded
the first time it is drawn, and canvases are kept by name at the size last asked.

    {sprites, cache} = Sprites.sprites(cache, target, items, &MyGame.source/1)

    changes = [
      {:layers,
       [%CauldronGPU.SpriteLayer{clear: {0.0, 0.0, 0.0, 1.0}, view: {0, 0, 320, 200}, sprites: sprites}]}
    ]

`source` is a function from an item's `:picture` to `{key, raster}` or `{key,
raster, {left, top, width, height}}`, the part of `raster` drawn, or `nil` to skip the
item. Pictures with the same `key` share a texture; when `key`'s raster differs from
the one uploaded, it is uploaded again and the old texture released. Textures are
nearest-sampled, clamped, and hold the raster's bytes as display values, so the card
blends them as `Cauldron2D.Blend` does.

Items are drawn in `Cauldron2D.DrawList.in_depth_order/1`. An item's `:blend`,
`:alpha` and `:mode` become the sprite's `colour`, `alpha` and `mode`; a mode
`{:gamemaker, mode}` is drawn as `mode`.

# `key`

```elixir
@type key() :: term()
```

# `source`

```elixir
@type source() :: (term() -&gt;
               {key(), FrenchCurve.Raster.t()}
               | {key(), FrenchCurve.Raster.t(),
                  {number(), number(), number(), number()}}
               | nil)
```

# `t`

```elixir
@type t() :: %Cauldron2D.Drafter.Client.Sprites{
  canvases: %{
    required(term()) =&gt; {{pos_integer(), pos_integer()}, CauldronGPU.Handle.t()}
  },
  textures: %{
    required(key()) =&gt; {FrenchCurve.Raster.t(), CauldronGPU.Handle.t()}
  }
}
```

# `canvas`

```elixir
@spec canvas(t(), CauldronGPU.Target.t(), term(), {pos_integer(), pos_integer()}) ::
  {CauldronGPU.Handle.t(), t()}
```

The canvas `name` at `size` `{width, height}`: the one kept when its size matches, else
a new one, the old one released.

# `colour`

```elixir
@spec colour({byte(), byte(), byte(), byte()}) :: {float(), float(), float(), float()}
```

`{r, g, b, a}` bytes as the 0 to 1 colour a layer's `clear` takes.

# `new`

```elixir
@spec new() :: t()
```

An empty cache.

# `sprites`

```elixir
@spec sprites(t(), CauldronGPU.Target.t(), [Cauldron2D.DrawList.item()], source()) ::
  {[CauldronGPU.Sprite.t()], t()}
```

The sprites for `items`, uploading the pictures `target` does not have yet.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
