Skip to content

Commit

Permalink
ui: initial flexbox support
Browse files Browse the repository at this point in the history
  • Loading branch information
cart committed Jul 25, 2020
1 parent bcf95a2 commit 93bb1d5
Show file tree
Hide file tree
Showing 22 changed files with 617 additions and 377 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Default for App {
schedule: Default::default(),
executor: Default::default(),
startup_schedule: Default::default(),
startup_executor: Default::default(),
startup_executor: ParallelExecutor::without_tracker_clears(),
runner: Box::new(run_once),
}
}
Expand Down
12 changes: 11 additions & 1 deletion crates/bevy_ecs/src/schedule/parallel_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,26 @@ use std::sync::{Arc, Mutex};
pub struct ParallelExecutor {
stages: Vec<ExecutorStage>,
last_schedule_generation: usize,
clear_trackers: bool,
}

impl Default for ParallelExecutor {
fn default() -> Self {
Self {
stages: Default::default(),
last_schedule_generation: usize::MAX, // MAX forces prepare to run the first time
clear_trackers: true,
}
}
}

impl ParallelExecutor {
pub fn without_tracker_clears() -> Self {
Self {
clear_trackers: false,
..Default::default()
}
}
pub fn prepare(&mut self, schedule: &mut Schedule, world: &World) {
let schedule_generation = schedule.generation();
let schedule_changed = schedule_generation != self.last_schedule_generation;
Expand Down Expand Up @@ -53,7 +61,9 @@ impl ParallelExecutor {
}
}

world.clear_trackers();
if self.clear_trackers {
world.clear_trackers();
}
}
}

Expand Down
36 changes: 6 additions & 30 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use super::CameraProjection;
use bevy_app::prelude::{EventReader, Events};
use bevy_ecs::{Component, Local, Query, Res};
use bevy_math::Mat4;
use bevy_property::Properties;
use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows};
use bevy_app::prelude::{Events, EventReader};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};

#[derive(Default, Debug, Properties)]
pub struct Camera {
pub projection_matrix: Mat4,
pub name: Option<String>,
#[property(ignore)]
pub window: WindowReference,
pub window: WindowId,
}

#[derive(Default)]
Expand All @@ -27,7 +27,6 @@ pub fn camera_system<T: CameraProjection + Component>(
mut query: Query<(&mut Camera, &mut T)>,
) {
let mut changed_window_ids = Vec::new();
let mut changed_primary_window_id = None;
// handle resize events. latest events are handled first because we only want to resize each window once
for event in state
.window_resized_event_reader
Expand All @@ -38,11 +37,7 @@ pub fn camera_system<T: CameraProjection + Component>(
continue;
}

if event.is_primary {
changed_primary_window_id = Some(event.id);
} else {
changed_window_ids.push(event.id);
}
changed_window_ids.push(event.id);
}

// handle resize events. latest events are handled first because we only want to resize each window once
Expand All @@ -55,30 +50,11 @@ pub fn camera_system<T: CameraProjection + Component>(
continue;
}

if event.is_primary {
changed_primary_window_id = Some(event.id);
} else {
changed_window_ids.push(event.id);
}
changed_window_ids.push(event.id);
}

for (mut camera, mut camera_projection) in &mut query.iter() {
if let Some(window) = match camera.window {
WindowReference::Id(id) => {
if changed_window_ids.contains(&id) {
windows.get(id)
} else {
None
}
}
WindowReference::Primary => {
if let Some(id) = changed_primary_window_id {
windows.get(id)
} else {
None
}
}
} {
if let Some(window) = windows.get(camera.window) {
camera_projection.update(window.width as usize, window.height as usize);
camera.projection_matrix = camera_projection.get_projection_matrix();
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_render/src/render_graph/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
Color,
};
use bevy_window::WindowReference;
use bevy_window::WindowId;

pub struct BaseRenderGraphConfig {
pub add_2d_camera: bool,
Expand Down Expand Up @@ -71,7 +71,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
self.add_node(
node::MAIN_DEPTH_TEXTURE,
WindowTextureNode::new(
WindowReference::Primary,
WindowId::primary(),
TextureDescriptor {
size: Extent3d {
depth: 1,
Expand Down Expand Up @@ -137,7 +137,7 @@ impl BaseRenderGraphBuilder for RenderGraph {

self.add_node(
node::PRIMARY_SWAP_CHAIN,
WindowSwapChainNode::new(WindowReference::Primary),
WindowSwapChainNode::new(WindowId::primary()),
);

if config.connect_main_pass_to_swapchain {
Expand Down
17 changes: 7 additions & 10 deletions crates/bevy_render/src/render_graph/nodes/window_swapchain_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ use crate::{
};
use bevy_app::prelude::{EventReader, Events};
use bevy_ecs::{Resources, World};
use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use std::borrow::Cow;

pub struct WindowSwapChainNode {
window_reference: WindowReference,
window_id: WindowId,
window_created_event_reader: EventReader<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>,
}

impl WindowSwapChainNode {
pub const OUT_TEXTURE: &'static str = "texture";
pub fn new(window_reference: WindowReference) -> Self {
pub fn new(window_id: WindowId) -> Self {
WindowSwapChainNode {
window_reference,
window_id,
window_created_event_reader: Default::default(),
window_resized_event_reader: Default::default(),
}
Expand Down Expand Up @@ -46,12 +46,9 @@ impl Node for WindowSwapChainNode {
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
let windows = resources.get::<Windows>().unwrap();

let window = match self.window_reference {
WindowReference::Primary => windows.get_primary().expect("No primary window exists"),
WindowReference::Id(id) => windows
.get(id)
.expect("Received window resized event for non-existent window"),
};
let window = windows
.get(self.window_id)
.expect("Received window resized event for non-existent window");

let render_resource_context = render_context.resources_mut();

Expand Down
17 changes: 7 additions & 10 deletions crates/bevy_render/src/render_graph/nodes/window_texture_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ use crate::{
};
use bevy_app::prelude::{EventReader, Events};
use bevy_ecs::{Resources, World};
use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows};
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
use std::borrow::Cow;

pub struct WindowTextureNode {
window_reference: WindowReference,
window_id: WindowId,
descriptor: TextureDescriptor,
window_created_event_reader: EventReader<WindowCreated>,
window_resized_event_reader: EventReader<WindowResized>,
}

impl WindowTextureNode {
pub const OUT_TEXTURE: &'static str = "texture";
pub fn new(window_reference: WindowReference, descriptor: TextureDescriptor) -> Self {
pub fn new(window_id: WindowId, descriptor: TextureDescriptor) -> Self {
WindowTextureNode {
window_reference,
window_id,
descriptor,
window_created_event_reader: Default::default(),
window_resized_event_reader: Default::default(),
Expand Down Expand Up @@ -49,12 +49,9 @@ impl Node for WindowTextureNode {
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
let windows = resources.get::<Windows>().unwrap();

let window = match self.window_reference {
WindowReference::Primary => windows.get_primary().expect("No primary window exists"),
WindowReference::Id(id) => windows
.get(id)
.expect("Received window resized event for non-existent window"),
};
let window = windows
.get(self.window_id)
.expect("Received window resized event for non-existent window");

if self
.window_created_event_reader
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_transform/src/hierarchy/hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ pub fn run_on_hierarchy<T, S>(
children_query: &Query<&Children>,
state: &mut S,
entity: Entity,
parent_result: Option<&mut T>,
parent_result: Option<T>,
mut previous_result: Option<T>,
run: &mut dyn FnMut(&mut S, Entity, Option<&mut T>, Option<T>) -> Option<T>,
run: &mut dyn FnMut(&mut S, Entity, Option<T>, Option<T>) -> Option<T>,
) -> Option<T>
where
T: Clone,
Expand All @@ -25,15 +25,15 @@ where
Err(_) => None,
};

let mut parent_result = run(state, entity, parent_result, previous_result);
let parent_result = run(state, entity, parent_result, previous_result);
previous_result = None;
if let Some(children) = children {
for child in children {
previous_result = run_on_hierarchy(
children_query,
state,
child,
parent_result.as_mut(),
parent_result.clone(),
previous_result,
run,
);
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ bevy_transform = { path = "../bevy_transform" }
bevy_render = { path = "../bevy_render" }
bevy_window = { path = "../bevy_window" }

bevy_math = { path = "../bevy_math" }
bevy_math = { path = "../bevy_math" }

stretch = "0.3"
56 changes: 54 additions & 2 deletions crates/bevy_ui/src/entity.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
use super::Node;
use crate::{
prelude::Flex,
render::UI_PIPELINE_HANDLE,
widget::{Button, Text},
Click, FocusPolicy, Hover,
Click, FlexSurfaceId, FocusPolicy, Hover,
};
use bevy_asset::Handle;
use bevy_ecs::Bundle;
use bevy_render::{
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
draw::Draw,
mesh::Mesh,
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
};
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
use bevy_transform::{components::LocalTransform, prelude::Transform};
use bevy_transform::{
components::LocalTransform,
prelude::{Rotation, Scale, Transform, Translation},
};

#[derive(Bundle)]
pub struct NodeComponents {
pub node: Node,
pub flex: Flex,
pub flex_surface_id: FlexSurfaceId,
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
pub material: Handle<ColorMaterial>,
pub draw: Draw,
Expand Down Expand Up @@ -48,6 +55,8 @@ impl Default for NodeComponents {
},
)]),
node: Default::default(),
flex_surface_id: Default::default(),
flex: Flex::default(),
material: Default::default(),
draw: Default::default(),
transform: Default::default(),
Expand All @@ -59,6 +68,8 @@ impl Default for NodeComponents {
#[derive(Bundle)]
pub struct TextComponents {
pub node: Node,
pub flex: Flex,
pub flex_surface_id: FlexSurfaceId,
pub draw: Draw,
pub text: Text,
pub focus_policy: FocusPolicy,
Expand All @@ -71,6 +82,8 @@ impl Default for TextComponents {
TextComponents {
text: Text::default(),
node: Default::default(),
flex: Flex::default(),
flex_surface_id: Default::default(),
focus_policy: FocusPolicy::Pass,
draw: Draw {
is_transparent: true,
Expand All @@ -86,6 +99,8 @@ impl Default for TextComponents {
pub struct ButtonComponents {
pub node: Node,
pub button: Button,
pub flex: Flex,
pub flex_surface_id: FlexSurfaceId,
pub click: Click,
pub hover: Hover,
pub focus_policy: FocusPolicy,
Expand Down Expand Up @@ -124,10 +139,47 @@ impl Default for ButtonComponents {
},
)]),
node: Default::default(),
flex_surface_id: Default::default(),
flex: Flex::default(),
material: Default::default(),
draw: Default::default(),
transform: Default::default(),
local_transform: Default::default(),
}
}
}

#[derive(Bundle)]
pub struct UiCameraComponents {
pub camera: Camera,
pub orthographic_projection: OrthographicProjection,
pub visible_entities: VisibleEntities,
pub transform: Transform,
pub translation: Translation,
pub rotation: Rotation,
pub scale: Scale,
}

impl Default for UiCameraComponents {
fn default() -> Self {
// we want 0 to be "closest" and +far to be "farthest" in 2d, so we offset
// the camera's translation by far and use a right handed coordinate system
let far = 1000.0;
UiCameraComponents {
camera: Camera {
name: Some(crate::camera::UI_CAMERA.to_string()),
..Default::default()
},
orthographic_projection: OrthographicProjection {
far,
window_origin: WindowOrigin::BottomLeft,
..Default::default()
},
visible_entities: Default::default(),
transform: Default::default(),
translation: Translation::new(0.0, 0.0, far - 0.1),
rotation: Default::default(),
scale: Default::default(),
}
}
}
Loading

0 comments on commit 93bb1d5

Please sign in to comment.