1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#![allow(clippy::type_complexity)]

//! `bevy_vector_shapes` is a library for easily and ergonomically creating instanced vector shapes in [Bevy](https://bevyengine.org/).
//!
//! ## Usage
//! See the the [examples](https://github.com/james-j-obrien/bevy_vector_shapes/tree/main/examples) for more details on all supported features.
//! ```rust
//! use bevy::prelude::*;
//! // Import commonly used items
//! use bevy_vector_shapes::prelude::*;

//! fn main() {
//!     App::new()
//!         .add_plugins(DefaultPlugins)
//!         // Add the shape plugin:
//!         // - Shape2dPlugin for 2D cameras
//!         // - ShapePlugin for both 3D and 2D cameras
//!         .add_plugins(Shape2dPlugin::default())
//!         .add_startup_system(setup)
//!         .add_system(draw)
//!         .run();
//! }

//! fn setup(mut commands: Commands) {
//!     // Spawn the camera
//!     commands.spawn(Camera2dBundle::default());
//! }

//! fn draw(mut painter: ShapePainter) {
//!     // Draw a circle
//!     painter.circle(100.0);
//! }
//! ```
//!

use bevy::prelude::*;

/// Components and Enums used to define shape types.
pub mod shapes;
use shapes::*;

/// Rendering specific traits and structs.
pub mod render;
use render::{ShapeRenderPlugin, ShapeType3dPlugin, ShapeTypePlugin};

/// Structs and components used by the [`ShapePainter`], [`ShapeCommands`] and [`Canvas`] APIs.
pub mod painter;
use painter::*;

/// `use bevy_vector_shapes::prelude::*` to import commonly used items.
pub mod prelude {
    pub use crate::painter::{
        BuildShapeChildren, Canvas, CanvasCommands, CanvasConfig, CanvasMode, ShapeChildBuilder,
        ShapeCommands, ShapeConfig, ShapeEntityCommands, ShapePainter, ShapeSpawner,
    };
    pub use crate::{shapes::*, BaseShapeConfig, Shape2dPlugin, ShapePlugin};
}

/// Resource that represents the default shape config to be used by [`ShapePainter`] and [`ShapeCommands`] APIs.
///
/// When a [`ShapePainter`] is cleared it will have it's config reset to the current value of this resource.
#[derive(Resource, Clone)]
pub struct BaseShapeConfig(pub ShapeConfig);

/// Plugin that contains all necessary functionality to draw shapes with a 2D camera.
pub struct Shape2dPlugin {
    /// Default config that will be used for all [`ShapePainter`]s.
    ///
    /// Available as a resource [`BaseShapeConfig`].
    pub base_config: ShapeConfig,
}

impl Default for Shape2dPlugin {
    fn default() -> Self {
        Self {
            base_config: ShapeConfig::default_2d(),
        }
    }
}

impl Shape2dPlugin {
    pub fn new(base_config: ShapeConfig) -> Self {
        Self { base_config }
    }
}

impl Plugin for Shape2dPlugin {
    fn build(&self, app: &mut App) {
        app.insert_resource(BaseShapeConfig(self.base_config.clone()))
            .add_plugins(PainterPlugin)
            .add_plugins(ShapeRenderPlugin)
            .add_plugins(ShapeTypePlugin::<LineComponent>::default())
            .add_plugins(ShapeTypePlugin::<DiscComponent>::default())
            .add_plugins(ShapeTypePlugin::<RectangleComponent>::default())
            .add_plugins(ShapeTypePlugin::<RegularPolygonComponent>::default())
            .add_plugins(ShapeTypePlugin::<TriangleComponent>::default());
    }
}

/// Plugin that contains all necessary functionality to draw shapes with a 3D or 2D camera.
pub struct ShapePlugin {
    /// Default config that will be used for all [`ShapePainter`]s.
    ///
    /// Available as a resource [`BaseShapeConfig`].
    pub base_config: ShapeConfig,
    /// Whether to also add the 2d plugin.
    ///
    /// Useful if you want to add the 3d functionality when another plugin has already added the 2d plugin.
    pub exclude_2d: bool,
}

impl ShapePlugin {
    pub fn new(base_config: ShapeConfig) -> Self {
        Self {
            base_config,
            ..default()
        }
    }
}

impl Default for ShapePlugin {
    fn default() -> Self {
        Self {
            base_config: ShapeConfig::default_3d(),
            exclude_2d: false,
        }
    }
}

impl Plugin for ShapePlugin {
    fn build(&self, app: &mut App) {
        if !self.exclude_2d {
            app.add_plugins(Shape2dPlugin::new(self.base_config.clone()));
        }
        app.add_plugins(ShapeType3dPlugin::<LineComponent>::default())
            .add_plugins(ShapeType3dPlugin::<DiscComponent>::default())
            .add_plugins(ShapeType3dPlugin::<RectangleComponent>::default())
            .add_plugins(ShapeType3dPlugin::<RegularPolygonComponent>::default())
            .add_plugins(ShapeType3dPlugin::<TriangleComponent>::default());
    }
}