hoplite/ecs.rs
1//! ECS components for entity-based rendering.
2//!
3//! This module provides components for rendering entities using the `hecs` ECS library.
4//! Entities with [`Transform`](crate::Transform) and [`RenderMesh`] components are
5//! automatically rendered when [`Frame::render_world`](crate::Frame::render_world) is called.
6//!
7//! # Example
8//!
9//! ```ignore
10//! use hoplite::*;
11//!
12//! run(|ctx| {
13//! ctx.enable_mesh_rendering();
14//! let cube = ctx.mesh_cube();
15//!
16//! // Spawn an entity with mesh components
17//! ctx.world.spawn((
18//! Transform::new().position(Vec3::new(0.0, 0.0, -5.0)),
19//! RenderMesh::new(cube, Color::RED),
20//! ));
21//!
22//! move |frame| {
23//! frame.render_world();
24//! }
25//! });
26//! ```
27
28use crate::draw2d::Color;
29
30/// Type-safe handle to a mesh stored in the MeshQueue.
31///
32/// Obtained from mesh creation methods like [`SetupContext::mesh_cube`](crate::SetupContext::mesh_cube).
33/// This newtype wrapper prevents accidentally passing texture indices where mesh indices are expected.
34///
35/// # Example
36///
37/// ```ignore
38/// let cube: MeshId = ctx.mesh_cube();
39/// frame.mesh(cube).draw(); // Type-safe: can't pass a TextureId here
40/// ```
41#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
42pub struct MeshId(pub(crate) usize);
43
44/// Type-safe handle to a texture stored in the MeshQueue.
45///
46/// Obtained from texture creation methods like [`SetupContext::texture_from_file`](crate::SetupContext::texture_from_file).
47/// This newtype wrapper prevents accidentally passing mesh indices where texture indices are expected.
48///
49/// # Example
50///
51/// ```ignore
52/// let tex: TextureId = ctx.texture_from_file("brick.png")?;
53/// frame.mesh(cube).texture(tex).draw(); // Type-safe: can't pass a MeshId here
54/// ```
55#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
56pub struct TextureId(pub(crate) usize);
57
58// Keep MeshHandle and TextureHandle as aliases for backwards compatibility in ECS contexts
59/// Alias for [`MeshId`] - used in ECS components.
60pub type MeshHandle = MeshId;
61
62/// Alias for [`TextureId`] - used in ECS components.
63pub type TextureHandle = TextureId;
64
65/// Component for rendering a mesh on an entity.
66///
67/// Attach this component along with a [`Transform`](crate::Transform) to make an entity
68/// renderable. Call [`Frame::render_world`](crate::Frame::render_world) to render all
69/// entities with these components.
70///
71/// # Example
72///
73/// ```ignore
74/// // Untextured colored mesh
75/// world.spawn((
76/// Transform::new().position(Vec3::Y * 2.0),
77/// RenderMesh::new(MeshHandle(cube), Color::RED),
78/// ));
79///
80/// // Textured mesh
81/// world.spawn((
82/// Transform::new(),
83/// RenderMesh::with_texture(MeshHandle(cube), Color::WHITE, TextureHandle(tex)),
84/// ));
85/// ```
86#[derive(Clone, Copy, Debug)]
87pub struct RenderMesh {
88 /// Handle to the mesh geometry.
89 pub mesh: MeshHandle,
90 /// Color tint applied to the mesh.
91 pub color: Color,
92 /// Optional texture. If `None`, uses vertex colors only.
93 pub texture: Option<TextureHandle>,
94}
95
96impl RenderMesh {
97 /// Create a new render mesh component with a color tint.
98 pub fn new(mesh: MeshHandle, color: Color) -> Self {
99 Self {
100 mesh,
101 color,
102 texture: None,
103 }
104 }
105
106 /// Create a new render mesh component with a texture.
107 pub fn with_texture(mesh: MeshHandle, color: Color, texture: TextureHandle) -> Self {
108 Self {
109 mesh,
110 color,
111 texture: Some(texture),
112 }
113 }
114}