# `Cauldron2D.Easel.Project`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.0/cauldron_2d_easel/lib/cauldron_2d/easel/project.ex#L1)

An art directory as an editor sees it: the pictures in it, the manifest beside them
(`Cauldron2D.Atlas.Manifest`), and the atlas they make.

    project = Cauldron2D.Easel.Project.open("priv/art", tile: 16)
    Cauldron2D.Easel.Project.arts(project)
    {:ok, easel} = Cauldron2D.Easel.Project.load(project, :ship)
    {:ok, project} = Cauldron2D.Easel.Project.save(project, :ship, easel)
    {:ok, :my_game} = Cauldron2D.Easel.Project.install(project, :my_game)

Every art is a `.pic` or `.png` file named for it, or a line in the manifest deriving
it from another (`derive/3`, as `Linocut.Derive` reads the line); `save/3` writes
`.pic`, keeping a `.png` that was there. `install/2` builds the atlas with
`Cauldron2D.Atlas.load/3` and installs it, so a running game that subscribed to the
atlas sees the change.

# `t`

```elixir
@type t() :: %Cauldron2D.Easel.Project{
  dir: Path.t(),
  manifest: Cauldron2D.Atlas.Manifest.t(),
  tile: pos_integer(),
  void: Cauldron2D.Atlas.rgb()
}
```

# `arts`

```elixir
@spec arts(t()) :: [
  %{
    :name =&gt; atom(),
    :frames =&gt; non_neg_integer(),
    optional(:file) =&gt; String.t(),
    optional(:derived) =&gt; String.t()
  }
]
```

Every art, by name, with how many frames it has: those drawn, each with its `:file`,
then those derived, each with its `:derived` line, in name order.

# `clone`

```elixir
@spec clone(t(), atom(), atom()) :: {:ok, t()} | {:error, term()}
```

Write `from` — drawn or derived — as the picture `to.pic`, a picture of its own.

# `derive`

```elixir
@spec derive(t(), atom(), String.t()) :: {:ok, t()} | {:error, String.t() | term()}
```

Make `name` a derived art: `line` as `Linocut.Derive` reads it, built once to prove it
can be, then kept in the manifest. A name a drawn picture already has is refused.

# `entry`

```elixir
@spec entry(t(), atom()) :: Cauldron2D.Atlas.Manifest.entry()
```

The manifest's entry for `name`, `%{}` when it has none.

# `install`

```elixir
@spec install(t(), Cauldron2D.Atlas.name()) ::
  {:ok, Cauldron2D.Atlas.name()} | {:error, term()}
```

Build the atlas from the directory and install it under `name`.

# `load`

```elixir
@spec load(t(), atom()) :: {:ok, Cauldron2D.Easel.t()} | {:error, term()}
```

The art `name` as an easel, a derived one built from its line.

# `new_art`

```elixir
@spec new_art(t(), keyword()) :: Cauldron2D.Easel.t()
```

A transparent easel at the project's tile size; `:palette` as `Cauldron2D.Easel.new/3` takes it.

# `open`

```elixir
@spec open(Path.t(), keyword()) :: t()
```

The project in `dir`; `:tile` (required) and `:void` as `Cauldron2D.Atlas.new/2` takes them.

# `put_entry`

```elixir
@spec put_entry(t(), atom(), keyword()) :: {:ok, t()} | {:error, term()}
```

Set `name`'s `:glyph`, `:color` and `:fps` in the manifest and write it.

# `save`

```elixir
@spec save(t(), atom(), Cauldron2D.Easel.t()) :: {:ok, t()} | {:error, term()}
```

Write `easel` as `<name>.pic`, keeping its rate in the manifest.

---

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