generated from hheik/bevy-template
Added drawing debug shapes in immediate mode
parent
782a568eb6
commit
9c76992905
96
src/debug.rs
96
src/debug.rs
|
|
@ -1,4 +1,5 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_prototype_lyon::prelude::*;
|
||||
|
||||
pub struct DebugPlugin;
|
||||
|
||||
|
|
@ -11,12 +12,18 @@ impl Plugin for DebugPlugin {
|
|||
.configure_sets(PostUpdate, DebugSet.run_if(is_debug_enabled));
|
||||
|
||||
app.insert_resource(DebugMode::off())
|
||||
.add_plugins((
|
||||
bevy_inspector_egui::quick::WorldInspectorPlugin::new().run_if(is_debug_enabled),
|
||||
bevy_rapier2d::prelude::RapierDebugRenderPlugin::default(),
|
||||
))
|
||||
.insert_resource(DebugDraw::default());
|
||||
|
||||
app.add_plugins((
|
||||
bevy_inspector_egui::quick::WorldInspectorPlugin::new().run_if(is_debug_enabled),
|
||||
bevy_rapier2d::prelude::RapierDebugRenderPlugin::default(),
|
||||
));
|
||||
|
||||
app.register_type::<DebugCanvas>()
|
||||
.add_systems(First, clear_shapes)
|
||||
.add_systems(Update, debug_toggle)
|
||||
.add_systems(PostUpdate, draw_debug.in_set(DebugSet));
|
||||
// TODO: Check if this could be scheduled just before render instead
|
||||
.add_systems(PostUpdate, draw_shapes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +43,43 @@ impl DebugMode {
|
|||
}
|
||||
}
|
||||
|
||||
/// TODO: Rename to something smarter
|
||||
#[derive(Clone, Copy, Debug, Reflect)]
|
||||
pub struct Draw {
|
||||
pub shape: Shape,
|
||||
pub color: Srgba,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Reflect)]
|
||||
pub enum Shape {
|
||||
Line {
|
||||
from: Vec2,
|
||||
to: Vec2,
|
||||
},
|
||||
Polygon {
|
||||
center: Vec2,
|
||||
sides: usize,
|
||||
radius: f32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Component, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[require(Transform, Visibility)]
|
||||
pub struct DebugCanvas;
|
||||
|
||||
#[derive(Debug, Default, Resource, Reflect)]
|
||||
#[reflect(Resource)]
|
||||
pub struct DebugDraw {
|
||||
pub draw_queue: Vec<Draw>,
|
||||
}
|
||||
|
||||
impl DebugDraw {
|
||||
pub fn shape(&mut self, draw: Draw) {
|
||||
self.draw_queue.push(draw);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_debug_enabled(debug_mode: Res<DebugMode>) -> bool {
|
||||
debug_mode.enabled
|
||||
}
|
||||
|
|
@ -46,6 +90,44 @@ fn debug_toggle(input: Res<ButtonInput<KeyCode>>, mut debug_mode: ResMut<DebugMo
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_debug() {
|
||||
// TODO
|
||||
fn clear_shapes(mut commands: Commands, canvas_query: Query<Entity, With<DebugCanvas>>) {
|
||||
for parent in canvas_query.iter() {
|
||||
commands.entity(parent).despawn_descendants();
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_shapes(
|
||||
mut commands: Commands,
|
||||
canvas: Option<Single<Entity, With<DebugCanvas>>>,
|
||||
mut debug_draw: ResMut<DebugDraw>,
|
||||
) {
|
||||
let canvas = match canvas {
|
||||
Some(canvas) => *canvas,
|
||||
None => commands
|
||||
.spawn((Name::new("Debug Canvas"), DebugCanvas))
|
||||
.id(),
|
||||
};
|
||||
commands.entity(canvas).with_children(|builder| {
|
||||
for draw in debug_draw.draw_queue.drain(..) {
|
||||
// TODO
|
||||
let path = match draw.shape {
|
||||
Shape::Line { from, to } => GeometryBuilder::build_as(&shapes::Line(from, to)),
|
||||
Shape::Polygon {
|
||||
center,
|
||||
sides,
|
||||
radius,
|
||||
} => GeometryBuilder::build_as(&shapes::RegularPolygon {
|
||||
center,
|
||||
sides,
|
||||
feature: RegularPolygonFeature::Radius(radius),
|
||||
}),
|
||||
};
|
||||
|
||||
builder.spawn((
|
||||
ShapeBundle { path, ..default() },
|
||||
Fill::color(Srgba::NONE),
|
||||
Stroke::color(draw.color),
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{debug, game_setup, util};
|
||||
use bevy::prelude::*;
|
||||
use bevy_prototype_lyon::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
mod item;
|
||||
|
|
@ -10,6 +11,7 @@ mod work;
|
|||
pub fn init(app: &mut App) {
|
||||
let app = app.add_plugins((
|
||||
game_setup::GameSetupPlugin,
|
||||
ShapePlugin,
|
||||
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||
util::UtilPlugin,
|
||||
debug::DebugPlugin,
|
||||
|
|
@ -24,5 +26,6 @@ pub fn init(app: &mut App) {
|
|||
.register_type::<prefab::Tree>()
|
||||
.add_systems(Startup, systems::setup_2d)
|
||||
.add_systems(Update, (systems::demo_2d, systems::work_select))
|
||||
.add_systems(PostUpdate, item::update_item_sprite);
|
||||
.add_systems(PostUpdate, item::update_item_sprite)
|
||||
.add_systems(Update, (systems::draw_job_targets).in_set(debug::DebugSet));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
use bevy::prelude::*;
|
||||
|
||||
use crate::game::{item::Item, prefab};
|
||||
use crate::game::{
|
||||
item::{Inventory, Item, ItemStack},
|
||||
prefab,
|
||||
};
|
||||
|
||||
pub fn setup_2d(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
|
|
@ -9,13 +12,23 @@ pub fn setup_2d(mut commands: Commands) {
|
|||
Transform::from_xyz(0.0, 0.0, 10.0),
|
||||
));
|
||||
|
||||
commands.spawn((Transform::from_xyz(-200.0, 0.0, 0.0), prefab::Glorb));
|
||||
commands.spawn((
|
||||
Transform::from_xyz(-300.0, 0.0, 0.0),
|
||||
prefab::Glorb,
|
||||
Inventory {
|
||||
items: vec![ItemStack {
|
||||
item: Item::Wood,
|
||||
count: 1,
|
||||
}],
|
||||
capacity: Some(1),
|
||||
},
|
||||
));
|
||||
commands.spawn((Transform::from_xyz(-200.0, 100.0, 0.0), prefab::Glorb));
|
||||
commands.spawn((Transform::from_xyz(-200.0, -100.0, 0.0), prefab::Glorb));
|
||||
|
||||
commands.spawn((Transform::from_xyz(200.0, 0.0, 0.0), prefab::Tree));
|
||||
|
||||
commands.spawn((Name::from("Wood"), Item::Wood));
|
||||
// commands.spawn((Name::from("Wood"), Item::Wood));
|
||||
|
||||
commands.spawn((Transform::from_xyz(-200.0, -150.0, 0.0), prefab::Chest));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy::{color::palettes::css, prelude::*};
|
||||
|
||||
use crate::game::{
|
||||
item::{Inventory, ItemSource, Stockpile},
|
||||
work::{Task, WorkType, Worker},
|
||||
use crate::{
|
||||
debug::{DebugDraw, Draw, Shape},
|
||||
game::{
|
||||
item::{Inventory, ItemSource, Stockpile},
|
||||
work::{Task, WorkType, Worker},
|
||||
},
|
||||
};
|
||||
|
||||
pub fn work_select(
|
||||
|
|
@ -26,7 +29,7 @@ pub fn work_select(
|
|||
let stockpile_dist_squared = worker_transform
|
||||
.translation()
|
||||
.distance_squared(stockpile_transform.translation());
|
||||
if task_by_distance.map_or(true, |(_, closest_task_dist)| {
|
||||
if task_by_distance.is_none_or(|(_, closest_task_dist)| {
|
||||
stockpile_dist_squared < closest_task_dist
|
||||
}) {
|
||||
task_by_distance = Some((
|
||||
|
|
@ -52,9 +55,9 @@ pub fn work_select(
|
|||
let source_dist_squared = worker_transform
|
||||
.translation()
|
||||
.distance_squared(item_source_transform.translation());
|
||||
if task_by_distance.map_or(true, |(_, closest_task_dist)| {
|
||||
source_dist_squared < closest_task_dist
|
||||
}) {
|
||||
if task_by_distance
|
||||
.is_none_or(|(_, closest_task_dist)| source_dist_squared < closest_task_dist)
|
||||
{
|
||||
task_by_distance = Some((
|
||||
Task {
|
||||
target: item_source_entity,
|
||||
|
|
@ -70,3 +73,63 @@ pub fn work_select(
|
|||
worker.0 = task_by_distance.map(|(task, _)| task);
|
||||
}
|
||||
}
|
||||
|
||||
/// Example of DebugDraw usage
|
||||
pub fn draw_job_targets(
|
||||
mut debug_draw: ResMut<DebugDraw>,
|
||||
worker_query: Query<(Entity, &Worker)>,
|
||||
global_query: Query<&GlobalTransform>,
|
||||
) {
|
||||
for (worker_entity, worker) in worker_query.iter() {
|
||||
let worker_global = global_query.get(worker_entity).unwrap();
|
||||
let draws = match worker.0 {
|
||||
Some(task) => match task.work_type {
|
||||
WorkType::Gather => vec![
|
||||
Draw {
|
||||
shape: Shape::Polygon {
|
||||
center: worker_global.translation().xy(),
|
||||
sides: 3,
|
||||
radius: 16.,
|
||||
},
|
||||
color: css::GREEN,
|
||||
},
|
||||
Draw {
|
||||
shape: Shape::Line {
|
||||
from: worker_global.translation().xy(),
|
||||
to: global_query.get(task.target).unwrap().translation().xy(),
|
||||
},
|
||||
color: css::GREEN,
|
||||
},
|
||||
],
|
||||
WorkType::Store(_) => vec![
|
||||
Draw {
|
||||
shape: Shape::Polygon {
|
||||
center: worker_global.translation().xy(),
|
||||
sides: 3,
|
||||
radius: 16.,
|
||||
},
|
||||
color: css::YELLOW,
|
||||
},
|
||||
Draw {
|
||||
shape: Shape::Line {
|
||||
from: worker_global.translation().xy(),
|
||||
to: global_query.get(task.target).unwrap().translation().xy(),
|
||||
},
|
||||
color: css::YELLOW,
|
||||
},
|
||||
],
|
||||
},
|
||||
None => vec![Draw {
|
||||
shape: Shape::Polygon {
|
||||
center: worker_global.translation().xy(),
|
||||
sides: 3,
|
||||
radius: 16.,
|
||||
},
|
||||
color: css::RED,
|
||||
}],
|
||||
};
|
||||
for draw in draws {
|
||||
debug_draw.shape(draw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue