-
-
Notifications
You must be signed in to change notification settings - Fork 29
Display arrows from factory spawn to target #489
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e697b77
Display arrows from factory spawn to target
0HyperCube 8b03b89
Another code review change
0HyperCube c749b54
Fix a doc comment
Indy2222 e5372f4
Add sysem ordering condition
Indy2222 bdafa8e
Cometics
Indy2222 39580e1
Remove unused import
Indy2222 1d8634c
Fix & improve owner de-spawning
Indy2222 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#import bevy_pbr::mesh_view_bindings | ||
#import bevy_pbr::mesh_bindings | ||
|
||
struct CustomMaterial { | ||
color: vec4<f32>, | ||
pointiness: f32, | ||
speed: f32, | ||
length: f32, | ||
spacing: f32, | ||
fade: f32, | ||
}; | ||
|
||
@group(1) @binding(0) | ||
var<uniform> material: CustomMaterial; | ||
|
||
const COLOR: vec4<f32> = vec4<f32>(0.0, 0.5, 0.0, 0.8); | ||
const POINTINESS: f32 = 2.; | ||
const SPEED: f32 = 3.; | ||
const LENGTH: f32 = 1.; | ||
const SPACING: f32 = 0.5; | ||
const FADE: f32 = 3.; | ||
|
||
@fragment | ||
fn fragment( | ||
#import bevy_pbr::mesh_vertex_output | ||
) -> @location(0) vec4<f32> { | ||
let world_space_length: f32 = length(mesh.model[0].xyz); | ||
let scaled_x: f32 = uv.x * world_space_length; | ||
let offset_y: f32 = abs(uv.y - 0.5) * POINTINESS; | ||
let scaled_time: f32 = globals.time * SPEED; | ||
let total_length = LENGTH + SPACING; | ||
|
||
let value = scaled_x + offset_y - scaled_time; | ||
// Ensure that the result of the modulo operation is always positive | ||
let positive_modulo = (value % total_length + total_length) % total_length; | ||
let alpha = step(SPACING, positive_modulo); | ||
|
||
let start_fade: f32 = (floor(value / total_length) * total_length + scaled_time) / FADE; | ||
let end_fade: f32 = (world_space_length - ((ceil(value / total_length) * total_length + scaled_time))) / FADE; | ||
let fade = min(1., min(start_fade, end_fade)); | ||
|
||
return COLOR * vec4(1., 1., 1., alpha * fade); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
use ahash::AHashMap; | ||
use bevy::prelude::*; | ||
use bevy::reflect::TypeUuid; | ||
use bevy::render::render_resource::{AsBindGroup, ShaderRef}; | ||
use de_core::baseset::GameSet; | ||
use de_core::cleanup::DespawnOnGameExit; | ||
use de_core::objects::Active; | ||
use de_core::state::AppState; | ||
|
||
/// Width of the line that goes to the pole. | ||
const LINE_WIDTH: f32 = 1.; | ||
/// Offset above mean sea level of the line, stopping z-fighting with the floor. | ||
const LINE_OFFSET: Vec3 = Vec3::new(0., 1e-3, 0.); | ||
|
||
pub(crate) struct LinePlugin; | ||
|
||
impl Plugin for LinePlugin { | ||
fn build(&self, app: &mut App) { | ||
app.add_plugin(MaterialPlugin::<LineMaterial>::default()) | ||
.add_event::<UpdateLineLocationEvent>() | ||
.add_event::<UpdateLineEndEvent>() | ||
.add_event::<UpdateLineVisibilityEvent>() | ||
.add_system(setup.in_schedule(OnEnter(AppState::InGame))) | ||
.add_system(cleanup.in_schedule(OnExit(AppState::InGame))) | ||
.add_system( | ||
update_line_end | ||
.in_base_set(GameSet::PostUpdate) | ||
.run_if(in_state(AppState::InGame)) | ||
.run_if(on_event::<UpdateLineEndEvent>()) | ||
.in_set(LinesSet::LineEnd), | ||
) | ||
.add_system( | ||
update_line_location | ||
.in_base_set(GameSet::PostUpdate) | ||
.run_if(in_state(AppState::InGame)) | ||
.run_if(on_event::<UpdateLineLocationEvent>()) | ||
.in_set(LinesSet::LocationEvents) | ||
.after(LinesSet::LineEnd), | ||
) | ||
.add_system( | ||
update_line_visibility | ||
.in_base_set(GameSet::PostUpdate) | ||
.run_if(in_state(AppState::InGame)) | ||
.run_if(on_event::<UpdateLineVisibilityEvent>()) | ||
.in_set(LinesSet::VisibilityEvents) | ||
.after(LinesSet::LocationEvents), | ||
) | ||
.add_system( | ||
owner_despawn | ||
.in_base_set(GameSet::PostUpdate) | ||
.run_if(in_state(AppState::InGame)) | ||
.in_set(LinesSet::Despawn) | ||
.after(LinesSet::VisibilityEvents), | ||
); | ||
} | ||
} | ||
|
||
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, SystemSet)] | ||
enum LinesSet { | ||
LineEnd, | ||
LocationEvents, | ||
VisibilityEvents, | ||
Despawn, | ||
} | ||
|
||
// Passed to the `rally_point.wgsl` shader | ||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)] | ||
#[uuid = "d0fae52d-f398-4416-9b72-9039093a6c34"] | ||
pub struct LineMaterial {} | ||
|
||
impl Material for LineMaterial { | ||
fn fragment_shader() -> ShaderRef { | ||
"shaders/rally_point.wgsl".into() | ||
} | ||
|
||
fn alpha_mode(&self) -> AlphaMode { | ||
AlphaMode::Blend | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct LineLocation { | ||
start: Vec3, | ||
end: Vec3, | ||
} | ||
|
||
impl LineLocation { | ||
pub fn new(start: Vec3, end: Vec3) -> Self { | ||
Self { start, end } | ||
} | ||
|
||
/// A transform matrix from a plane with points at `(-0.5, 0. -0.5), (0.5, 0. -0.5), | ||
/// (0.5, 0., 0.5), (-0.5, 0., -0.5)` to the line start and end with the `LINE_WIDTH`. | ||
fn transform(&self) -> Transform { | ||
let line_direction = self.end - self.start; | ||
let perpendicular_direction = | ||
Vec3::new(-line_direction.z, line_direction.y, line_direction.x).normalize() | ||
* LINE_WIDTH; | ||
let x_axis = line_direction.extend(0.); | ||
let z_axis = perpendicular_direction.extend(0.); | ||
let w_axis = (self.start + line_direction / 2. + LINE_OFFSET).extend(1.); | ||
Transform::from_matrix(Mat4::from_cols(x_axis, Vec4::Y, z_axis, w_axis)) | ||
} | ||
} | ||
|
||
pub struct UpdateLineVisibilityEvent { | ||
owner: Entity, | ||
visible: bool, | ||
} | ||
|
||
impl UpdateLineVisibilityEvent { | ||
pub fn new(owner: Entity, visible: bool) -> Self { | ||
Self { owner, visible } | ||
} | ||
} | ||
|
||
pub struct UpdateLineLocationEvent { | ||
owner: Entity, | ||
location: LineLocation, | ||
} | ||
|
||
impl UpdateLineLocationEvent { | ||
pub fn new(owner: Entity, location: LineLocation) -> Self { | ||
Self { owner, location } | ||
} | ||
} | ||
|
||
pub struct UpdateLineEndEvent { | ||
owner: Entity, | ||
end: Vec3, | ||
} | ||
|
||
impl UpdateLineEndEvent { | ||
pub fn new(owner: Entity, end: Vec3) -> Self { | ||
Self { owner, end } | ||
} | ||
} | ||
|
||
#[derive(Resource)] | ||
struct LineMesh(Handle<Mesh>, Handle<LineMaterial>); | ||
|
||
#[derive(Resource, Default)] | ||
struct LineEntities(AHashMap<Entity, Entity>); | ||
|
||
#[derive(Resource, Default)] | ||
struct LineLocations(AHashMap<Entity, LineLocation>); | ||
|
||
fn setup( | ||
mut commands: Commands, | ||
mut meshes: ResMut<Assets<Mesh>>, | ||
mut materials: ResMut<Assets<LineMaterial>>, | ||
) { | ||
commands.init_resource::<LineEntities>(); | ||
commands.init_resource::<LineLocations>(); | ||
let line_mesh = meshes.add(shape::Plane::from_size(1.0).into()); | ||
let line_material = materials.add(LineMaterial {}); | ||
commands.insert_resource(LineMesh(line_mesh, line_material)); | ||
} | ||
|
||
fn cleanup(mut commands: Commands) { | ||
commands.remove_resource::<LineEntities>(); | ||
commands.remove_resource::<LineLocations>(); | ||
commands.remove_resource::<LineMesh>(); | ||
} | ||
|
||
fn update_line_end( | ||
mut events: EventReader<UpdateLineEndEvent>, | ||
lines: Res<LineLocations>, | ||
mut line_location: EventWriter<UpdateLineLocationEvent>, | ||
) { | ||
for event in &mut events { | ||
if let Some(old_location) = lines.0.get(&event.owner) { | ||
let location = LineLocation::new(old_location.start, event.end); | ||
line_location.send(UpdateLineLocationEvent::new(event.owner, location)); | ||
} | ||
} | ||
} | ||
|
||
fn update_line_location( | ||
lines: Res<LineEntities>, | ||
mut events: EventReader<UpdateLineLocationEvent>, | ||
mut transforms: Query<&mut Transform>, | ||
mut line_locations: ResMut<LineLocations>, | ||
) { | ||
for event in &mut events { | ||
line_locations.0.insert(event.owner, event.location); | ||
if let Some(line_entity) = lines.0.get(&event.owner) { | ||
let mut current_transform = transforms.get_mut(*line_entity).unwrap(); | ||
*current_transform = event.location.transform() | ||
} | ||
} | ||
} | ||
|
||
fn update_line_visibility( | ||
mut events: EventReader<UpdateLineVisibilityEvent>, | ||
mut lines: ResMut<LineEntities>, | ||
line_locations: Res<LineLocations>, | ||
mut commands: Commands, | ||
line_mesh: Res<LineMesh>, | ||
) { | ||
for event in &mut events { | ||
if event.visible && !lines.0.contains_key(&event.owner) { | ||
let transform = line_locations | ||
.0 | ||
.get(&event.owner) | ||
.map(|location| location.transform()); | ||
let line_id = commands | ||
.spawn(( | ||
MaterialMeshBundle { | ||
mesh: line_mesh.0.clone(), | ||
material: line_mesh.1.clone(), | ||
transform: transform.unwrap_or_default(), | ||
..default() | ||
}, | ||
DespawnOnGameExit, | ||
)) | ||
.id(); | ||
lines.0.insert(event.owner, line_id); | ||
} else if !event.visible { | ||
if let Some(line_entity) = lines.0.remove(&event.owner) { | ||
commands.entity(line_entity).despawn_recursive(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
fn owner_despawn( | ||
mut commands: Commands, | ||
mut lines: ResMut<LineEntities>, | ||
mut removed: RemovedComponents<Active>, | ||
) { | ||
for owner in removed.iter() { | ||
if let Some(line) = lines.0.remove(&owner) { | ||
commands.entity(line).despawn_recursive(); | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.