# `Cauldron3D.Net.Scene`
[🔗](https://github.com/jaman/cauldron/blob/v0.3.3/cauldron_3d_net/lib/cauldron_3d/net/scene.ex#L1)

A scene browsers watch: it keeps everything sent to it (`CauldronGPU.Host.Record`) so a
browser that joins later gets the whole scene, and broadcasts each batch to the
browsers already watching as `CauldronGPU.Stream` bytes.

    {:ok, scene} = Cauldron3D.Net.Scene.open(id: "courtyard", events: self())
    cube = Cauldron3D.Net.Scene.mesh(scene, CauldronGPU.Mesh.cube(1.0))
    Cauldron3D.Net.Scene.submit(scene, [{:instance, 1, %CauldronGPU.Instance{mesh: cube}}])

A scene is a `CauldronGPU.Target`, so the converters (`CauldronGPU.Bsp.upload/4` and the
rest) upload to it as they do to a renderer. Changes are `CauldronGPU.Stream` changes.
Meshes, textures and materials are kept until `release/2`. Input from a browser
arrives at the `:events` pid as `{:cauldron_3d_net, scene_id, session, event}`,
`session` a reference for the browser and `event` shaped as `CauldronGPU`'s window
events, plus `:joined` and `:left`.

`open/1` starts the scene linked to the caller; `start_link/1` is the same for a
supervisor, and `lookup/1` finds a started scene by id.

# `t`

```elixir
@type t() :: %Cauldron3D.Net.Scene{id: String.t(), server: pid()}
```

# `canvas`

```elixir
@spec canvas(t(), CauldronGPU.Canvas.t()) :: CauldronGPU.Handle.t()
```

Makes a canvas and returns its handle, a texture's.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `event`

```elixir
@spec event(t(), reference(), term()) :: :ok
```

Passes a browser's event to the scene's `:events` pid.

# `lookup`

```elixir
@spec lookup(String.t()) :: t() | nil
```

The scene started as `id`, or `nil`.

# `material`

```elixir
@spec material(t(), CauldronGPU.Material.t()) :: CauldronGPU.Handle.t()
```

Defines a material and returns its handle.

# `mesh`

```elixir
@spec mesh(t(), CauldronGPU.Mesh.t()) :: CauldronGPU.Handle.t()
```

Uploads a mesh and returns its handle.

# `open`

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

Starts a scene. Options: `:id` (a string, required), `:events` (a pid, default none).

# `release`

```elixir
@spec release(t(), CauldronGPU.Handle.t()) :: :ok
```

Lets the scene drop a mesh, texture or material once no scene entry uses it.

# `snapshot`

```elixir
@spec snapshot(t()) :: binary()
```

The bytes that give a browser the whole scene as it stands.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Starts a scene as `open/1` does, answering its pid, for a supervisor.

# `submit`

```elixir
@spec submit(t(), [CauldronGPU.Stream.change()]) :: :ok
```

Sends one tick of changes to every watching browser and keeps them for later ones.

# `texture`

```elixir
@spec texture(t(), CauldronGPU.Texture.t()) :: CauldronGPU.Handle.t()
```

Uploads a texture and returns its handle.

# `topic`

```elixir
@spec topic(String.t()) :: String.t()
```

The PubSub topic a scene's batches are broadcast on.

---

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