Compare commits

..

No commits in common. "da5f9b0820a15de142b8cd7106c69825a7c9807b" and "09138229ca9554b2e86586368ace1182ad610a84" have entirely different histories.

2 changed files with 46 additions and 200 deletions

View file

@ -51,12 +51,6 @@ Skip to level `N: u32` with the command `bevyjam <N>`.
Edit the level `N: u32` with the command `bevyjam <N> e`. Edit the level `N: u32` with the command `bevyjam <N> e`.
### Editor controls
* **Select handles**: left click to select, click in void to deselect, CTRL+click to select many, CTRL+A to select all
* **Move handles**: arrows to move one step, Shift+arrows to move continuously
* **Move camera**: CTRL+arrows
## License ## License
GNU AGPL v3, CopyLeft 2022 Pascal Engélibert, Nixon Cheng GNU AGPL v3, CopyLeft 2022 Pascal Engélibert, Nixon Cheng

View file

@ -1,4 +1,3 @@
#![allow(clippy::type_complexity)]
use crate::{levels::stored::*, AppState}; use crate::{levels::stored::*, AppState};
use bevy::{ use bevy::{
@ -7,7 +6,6 @@ use bevy::{
shape::{Circle, Quad}, shape::{Circle, Quad},
*, *,
}, },
sprite::Mesh2dHandle,
}; };
use bevy_mod_picking::*; use bevy_mod_picking::*;
@ -15,40 +13,28 @@ pub struct EditorPlugin;
impl Plugin for EditorPlugin { impl Plugin for EditorPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<DragEndEvent>() app.add_plugins(DefaultPickingPlugins)
.add_plugins(DefaultPickingPlugins)
.add_system_set(SystemSet::on_enter(AppState::Editor).with_system(setup)) .add_system_set(SystemSet::on_enter(AppState::Editor).with_system(setup))
.add_system_set( .add_system_set(
SystemSet::on_update(AppState::Editor) SystemSet::on_update(AppState::Editor).with_system(keyboard_input_system),
.with_system(move_system)
.with_system(follow_ends_system),
); );
} }
} }
// Events
struct DragEndEvent(Entity);
// Resources
// Components
#[derive(Component)] #[derive(Component)]
struct Platform(Entity, Entity); struct Platform;
#[derive(Component)] #[derive(Component)]
struct Draggable; struct Draggable;
#[derive(Component)] #[derive(Component)]
struct End(Entity); struct End;
// Bundles
#[derive(Bundle)] #[derive(Bundle)]
struct PlatformBundle { struct PlatformBundle {
#[bundle] #[bundle]
mesh: ColorMesh2dBundle, mesh: ColorMesh2dBundle,
platform: Platform,
} }
#[derive(Bundle)] #[derive(Bundle)]
@ -61,17 +47,6 @@ struct PlatformEndBundle {
end: End, end: End,
} }
#[derive(Bundle)]
struct CharacterBundle {
#[bundle]
mesh: ColorMesh2dBundle,
#[bundle]
pickable: PickableBundle,
draggable: Draggable,
}
// Functions
fn spawn_platform( fn spawn_platform(
commands: &mut Commands, commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>, meshes: &mut ResMut<Assets<Mesh>>,
@ -80,7 +55,7 @@ fn spawn_platform(
transform: Transform, transform: Transform,
size: Vec2, size: Vec2,
) { ) {
let platform = commands commands
.spawn_bundle(PlatformBundle { .spawn_bundle(PlatformBundle {
mesh: ColorMesh2dBundle { mesh: ColorMesh2dBundle {
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(), mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
@ -88,97 +63,40 @@ fn spawn_platform(
transform, transform,
..default() ..default()
}, },
}) platform: Platform,
.id();
let ends = Platform(
commands
.spawn_bundle(PlatformEndBundle {
mesh: ColorMesh2dBundle {
mesh: meshes
.add(Mesh::from(Circle {
radius: 8.,
vertices: 12,
}))
.into(),
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
transform: Transform::from_xyz(
transform.translation.x - size.x / 2.,
transform.translation.y - size.y / 2.,
0.5,
),
..default()
},
pickable: PickableBundle::default(),
draggable: Draggable,
end: End(platform),
})
.id(),
commands
.spawn_bundle(PlatformEndBundle {
mesh: ColorMesh2dBundle {
mesh: meshes
.add(Mesh::from(Circle {
radius: 8.,
vertices: 12,
}))
.into(),
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
transform: Transform::from_xyz(
transform.translation.x + size.x / 2.,
transform.translation.y + size.y / 2.,
0.5,
),
..default()
},
pickable: PickableBundle::default(),
draggable: Draggable,
end: End(platform),
})
.id(),
);
commands.entity(platform).insert(ends);
}
fn spawn_character(
commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<ColorMaterial>>,
asset_server: &Res<AssetServer>,
transform: Transform,
color: Color,
index: usize,
) {
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
commands
.spawn_bundle(CharacterBundle {
mesh: ColorMesh2dBundle {
mesh: meshes
.add(Mesh::from(Quad {
size: Vec2 { x: 64., y: 64. },
flip: false,
}))
.into(),
material: materials.add(ColorMaterial::from(color)),
transform,
..default()
},
pickable: PickableBundle::default(),
draggable: Draggable,
}) })
.with_children(|c| { .with_children(|c| {
c.spawn_bundle(Text2dBundle { c.spawn_bundle(PlatformEndBundle {
text: Text::from_section( mesh: ColorMesh2dBundle {
&index.to_string(), mesh: meshes
TextStyle { .add(Mesh::from(Circle {
font: font.clone(), radius: 8.,
font_size: 32., vertices: 12,
color: Color::WHITE, }))
.into(),
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
transform: Transform::from_xyz(-size.x / 2., -size.y / 2., 0.5),
..default()
}, },
) pickable: PickableBundle::default(),
.with_alignment(TextAlignment::CENTER), draggable: Draggable,
transform: Transform::from_xyz(0., 0., 1.), end: End,
..Default::default() });
c.spawn_bundle(PlatformEndBundle {
mesh: ColorMesh2dBundle {
mesh: meshes
.add(Mesh::from(Circle {
radius: 8.,
vertices: 12,
}))
.into(),
material: materials.add(ColorMaterial::from(Color::rgba(1., 1., 0., 0.7))),
transform: Transform::from_xyz(size.x / 2., size.y / 2., 0.5),
..default()
},
pickable: PickableBundle::default(),
draggable: Draggable,
end: End,
}); });
}); });
} }
@ -191,6 +109,8 @@ pub fn spawn_stored_level(
stored_level: &StoredLevel, stored_level: &StoredLevel,
) { ) {
let _font = asset_server.get_handle::<Font, _>("UacariLegacy-Thin.ttf");
for platform in stored_level.platforms.iter() { for platform in stored_level.platforms.iter() {
spawn_platform( spawn_platform(
commands, commands,
@ -200,21 +120,7 @@ pub fn spawn_stored_level(
platform.size, platform.size,
); );
} }
for (i, character) in stored_level.characters.iter().enumerate() {
spawn_character(
commands,
meshes,
materials,
asset_server,
Transform::from_xyz(character.pos.x, character.pos.y, 0.),
character.color.into(),
i,
);
} }
}
// Systems
fn setup( fn setup(
mut commands: Commands, mut commands: Commands,
@ -246,76 +152,22 @@ fn setup(
} }
} }
fn move_system( fn keyboard_input_system(
keyboard_input: Res<Input<KeyCode>>, keyboard_input: Res<Input<KeyCode>>,
mut camera_query: Query<&mut Transform, (With<Camera>, Without<Draggable>)>, mut drag_query: Query<(&mut Transform, &Selection), With<Draggable>>,
mut drag_query: Query<(&mut Transform, &Selection, Option<&End>), With<Draggable>>,
mut drag_end_event: EventWriter<DragEndEvent>,
) { ) {
if keyboard_input.pressed(KeyCode::LControl) || keyboard_input.pressed(KeyCode::RControl) { let drag = 8.
let mut transform = camera_query.single_mut(); * Vec3 {
let drag = Vec3 {
x: (keyboard_input.pressed(KeyCode::Right) as i8 x: (keyboard_input.pressed(KeyCode::Right) as i8
- keyboard_input.pressed(KeyCode::Left) as i8) as _, - keyboard_input.pressed(KeyCode::Left) as i8) as _,
y: (keyboard_input.pressed(KeyCode::Up) as i8 y: (keyboard_input.pressed(KeyCode::Up) as i8
- keyboard_input.pressed(KeyCode::Down) as i8) as _, - keyboard_input.pressed(KeyCode::Down) as i8) as _,
z: 0., z: 0.,
} * 8.; };
transform.translation += drag;
return;
}
let drag = if keyboard_input.pressed(KeyCode::LShift) || keyboard_input.pressed(KeyCode::RShift)
{
Vec3 {
x: (keyboard_input.pressed(KeyCode::Right) as i8
- keyboard_input.pressed(KeyCode::Left) as i8) as _,
y: (keyboard_input.pressed(KeyCode::Up) as i8
- keyboard_input.pressed(KeyCode::Down) as i8) as _,
z: 0.,
}
} else {
Vec3 {
x: (keyboard_input.just_pressed(KeyCode::Right) as i8
- keyboard_input.just_pressed(KeyCode::Left) as i8) as _,
y: (keyboard_input.just_pressed(KeyCode::Up) as i8
- keyboard_input.just_pressed(KeyCode::Down) as i8) as _,
z: 0.,
}
} * 8.;
if drag != Vec3::ZERO { if drag != Vec3::ZERO {
for (mut transform, selection, end) in drag_query.iter_mut() { for (mut transform, selection) in drag_query.iter_mut() {
if selection.selected() { if selection.selected() {
transform.translation += drag; transform.translation += drag;
if let Some(End(entity)) = end {
drag_end_event.send(DragEndEvent(*entity));
}
}
}
}
}
fn follow_ends_system(
mut meshes: ResMut<Assets<Mesh>>,
mut platform_query: Query<(&mut Transform, &mut Mesh2dHandle, &Platform)>,
end_query: Query<&Transform, Without<Platform>>,
mut drag_end_event: EventReader<DragEndEvent>,
) {
for DragEndEvent(entity) in drag_end_event.iter() {
if let Ok((mut transform, mut mesh, Platform(end1, end2))) = platform_query.get_mut(*entity)
{
if let (Ok(end1), Ok(end2)) = (end_query.get(*end1), end_query.get(*end2)) {
transform.translation.x = (end1.translation.x + end2.translation.x) / 2.;
transform.translation.y = (end1.translation.y + end2.translation.y) / 2.;
*mesh = meshes
.add(Mesh::from(Quad {
size: Vec2 {
x: (end2.translation.x - end1.translation.x).abs(),
y: (end2.translation.y - end1.translation.y).abs(),
},
flip: false,
}))
.into();
} }
} }
} }