bevy_ecs_tilemap/
lib.rs

1#![allow(dead_code)]
2
3//! Bevy ECS Tilemap plugin is a ECS driven tilemap rendering library. It's designed to be fast and highly customizable. Each tile is considered a unique entity and all tiles are stored in the game world.
4//!
5//!
6//! ## Features
7//! - A tile per entity.
8//! - Fast rendering using a chunked approach.
9//! - Layers and sparse tile maps.
10//! - GPU powered animations.
11//! - Isometric and Hexagonal tile maps.
12//! - Initial support for Tiled file exports.
13//! - Support for isometric and hexagon rendering.
14//! - Built in animation support  – see [`animation` example](https://github.com/StarArawn/bevy_ecs_tilemap/blob/main/examples/animation.rs).
15//! - Texture array support.
16//! - Can `Anchor` tilemap like a sprite.
17
18use bevy::{
19    ecs::schedule::IntoScheduleConfigs,
20    prelude::{
21        Bundle, Changed, Component, Deref, First, GlobalTransform, InheritedVisibility, Plugin,
22        Query, Reflect, ReflectComponent, SystemSet, Transform, ViewVisibility, Visibility,
23    },
24    render::sync_world::SyncToRenderWorld,
25    time::TimeSystems,
26};
27
28#[cfg(feature = "render")]
29use render::material::MaterialTilemapHandle;
30
31use anchor::TilemapAnchor;
32use map::{
33    TilemapGridSize, TilemapSize, TilemapSpacing, TilemapTexture, TilemapTextureSize,
34    TilemapTileSize, TilemapType,
35};
36use prelude::{TilemapId, TilemapRenderSettings};
37#[cfg(feature = "render")]
38use render::material::{MaterialTilemap, StandardTilemapMaterial};
39use tiles::{
40    AnimatedTile, TileColor, TileFlip, TilePos, TilePosOld, TileStorage, TileTextureIndex,
41    TileVisible,
42};
43
44#[cfg(all(not(feature = "atlas"), feature = "render"))]
45use bevy::render::{ExtractSchedule, RenderApp};
46
47pub mod anchor;
48/// A module that allows pre-loading of atlases into array textures.
49#[cfg(all(not(feature = "atlas"), feature = "render"))]
50mod array_texture_preload;
51/// A module which provides helper functions.
52pub mod helpers;
53/// A module which contains tilemap components.
54pub mod map;
55#[cfg(feature = "render")]
56pub(crate) mod render;
57/// A module which contains tile components.
58pub mod tiles;
59
60/// A bevy tilemap plugin. This must be included in order for everything to be rendered.
61/// But is not necessary if you are running without a renderer.
62pub struct TilemapPlugin;
63
64impl Plugin for TilemapPlugin {
65    fn build(&self, app: &mut bevy::prelude::App) {
66        #[cfg(feature = "render")]
67        app.add_plugins(render::TilemapRenderingPlugin);
68
69        app.add_systems(First, update_changed_tile_positions.in_set(TilemapFirstSet));
70
71        #[cfg(all(not(feature = "atlas"), feature = "render"))]
72        {
73            app.insert_resource(array_texture_preload::ArrayTextureLoader::default());
74            let render_app = app.sub_app_mut(RenderApp);
75            render_app.add_systems(ExtractSchedule, array_texture_preload::extract);
76        }
77
78        app.register_type::<FrustumCulling>()
79            .register_type::<TilemapId>()
80            .register_type::<TilemapSize>()
81            .register_type::<TilemapTexture>()
82            .register_type::<TilemapTileSize>()
83            .register_type::<TilemapGridSize>()
84            .register_type::<TilemapSpacing>()
85            .register_type::<TilemapTextureSize>()
86            .register_type::<TilemapType>()
87            .register_type::<TilemapAnchor>()
88            .register_type::<TilePos>()
89            .register_type::<TileTextureIndex>()
90            .register_type::<TileColor>()
91            .register_type::<TileVisible>()
92            .register_type::<TileFlip>()
93            .register_type::<TileStorage>()
94            .register_type::<TilePosOld>()
95            .register_type::<AnimatedTile>()
96            .configure_sets(First, TilemapFirstSet.after(TimeSystems));
97    }
98}
99
100#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
101pub struct TilemapFirstSet;
102
103#[derive(Component, Reflect, Debug, Clone, Copy, Deref)]
104#[reflect(Component)]
105pub struct FrustumCulling(pub bool);
106
107impl Default for FrustumCulling {
108    /// By default, `FrustumCulling` is `true`.
109    fn default() -> Self {
110        FrustumCulling(true)
111    }
112}
113
114#[cfg(feature = "render")]
115pub type TilemapBundle = MaterialTilemapBundle<StandardTilemapMaterial>;
116
117#[cfg(feature = "render")]
118/// The default tilemap bundle. All of the components within are required.
119#[derive(Bundle, Debug, Default, Clone)]
120pub struct MaterialTilemapBundle<M: MaterialTilemap> {
121    pub grid_size: TilemapGridSize,
122    pub map_type: TilemapType,
123    pub size: TilemapSize,
124    pub spacing: TilemapSpacing,
125    pub storage: TileStorage,
126    pub texture: TilemapTexture,
127    pub tile_size: TilemapTileSize,
128    pub transform: Transform,
129    pub global_transform: GlobalTransform,
130    pub render_settings: TilemapRenderSettings,
131    /// User indication of whether an entity is visible
132    pub visibility: Visibility,
133    /// Algorithmically-computed indication of whether an entity is visible and should be extracted
134    /// for rendering
135    pub inherited_visibility: InheritedVisibility,
136    pub view_visibility: ViewVisibility,
137    /// User indication of whether tilemap should be frustum culled.
138    pub frustum_culling: FrustumCulling,
139    pub material: MaterialTilemapHandle<M>,
140    pub sync: SyncToRenderWorld,
141    pub anchor: TilemapAnchor,
142}
143
144#[cfg(not(feature = "render"))]
145/// The default tilemap bundle. All of the components within are required.
146#[derive(Bundle, Debug, Default, Clone)]
147pub struct StandardTilemapBundle {
148    pub grid_size: TilemapGridSize,
149    pub map_type: TilemapType,
150    pub size: TilemapSize,
151    pub spacing: TilemapSpacing,
152    pub storage: TileStorage,
153    pub texture: TilemapTexture,
154    pub tile_size: TilemapTileSize,
155    pub transform: Transform,
156    pub global_transform: GlobalTransform,
157    pub render_settings: TilemapRenderSettings,
158    /// User indication of whether an entity is visible
159    pub visibility: Visibility,
160    /// Algorithmically-computed indication of whether an entity is visible and should be extracted
161    /// for rendering
162    pub inherited_visibility: InheritedVisibility,
163    pub view_visibility: ViewVisibility,
164    /// User indication of whether tilemap should be frustum culled.
165    pub frustum_culling: FrustumCulling,
166    pub sync: SyncToRenderWorld,
167}
168
169/// A module which exports commonly used dependencies.
170pub mod prelude {
171    #[cfg(feature = "render")]
172    pub use crate::MaterialTilemapBundle;
173    #[cfg(feature = "render")]
174    pub use crate::TilemapBundle;
175    pub use crate::TilemapPlugin;
176    pub use crate::anchor::TilemapAnchor;
177    #[cfg(all(not(feature = "atlas"), feature = "render"))]
178    pub use crate::array_texture_preload::*;
179    pub use crate::helpers;
180    pub use crate::helpers::filling::*;
181    pub use crate::helpers::geometry::*;
182    pub use crate::helpers::transform::*;
183    pub use crate::map::*;
184    #[cfg(feature = "render")]
185    pub use crate::render::material::MaterialTilemap;
186    #[cfg(feature = "render")]
187    pub use crate::render::material::MaterialTilemapHandle;
188    #[cfg(feature = "render")]
189    pub use crate::render::material::MaterialTilemapKey;
190    #[cfg(feature = "render")]
191    pub use crate::render::material::MaterialTilemapPlugin;
192    #[cfg(feature = "render")]
193    pub use crate::render::material::StandardTilemapMaterial;
194    pub use crate::tiles::*;
195}
196
197/// Updates old tile positions with the new values from the last frame.
198fn update_changed_tile_positions(mut query: Query<(&TilePos, &mut TilePosOld), Changed<TilePos>>) {
199    for (tile_pos, mut tile_pos_old) in query.iter_mut() {
200        tile_pos_old.0 = *tile_pos;
201    }
202}