Skip to content

Commit

Permalink
wip: refactor ui
Browse files Browse the repository at this point in the history
  • Loading branch information
ten3roberts committed Apr 5, 2024
1 parent 05d7550 commit fc8ee57
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 214 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion ivy-base/src/color.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use ezy::Lerp;
use glam::{Vec3, Vec4};
use palette::{FromColor, Hsla, Hsva, Srgba};

Expand Down
17 changes: 12 additions & 5 deletions ivy-base/src/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use std::{borrow::Cow, time::Duration};

use flax::{Component, Debuggable, Fetch};
use glam::{Mat3, Mat4, Quat, Vec2, Vec3, Vec4Swizzles};
use ivy_random::Random;
use glam::{Mat4, Quat, Vec2, Vec3, Vec4Swizzles};
mod connections;
mod physics;
pub use connections::*;
Expand All @@ -22,7 +19,7 @@ flax::component! {
/// TODO: remove
pub position2v: Vec2 => [ Debuggable ],

pub size:Vec3 => [ Debuggable ],
pub size:Vec2 => [ Debuggable ],

pub is_static: () => [ Debuggable ],
pub visible: Visible => [ Debuggable ],
Expand Down Expand Up @@ -83,3 +80,13 @@ pub enum Visible {
/// Entity is hidden by a parent node
HiddenInherit,
}

impl Visible {
/// Returns `true` if the visible is [`Visible`].
///
/// [`Visible`]: Visible::Visible
#[must_use]
pub fn is_visible(&self) -> bool {
matches!(self, Self::Visible)
}
}
2 changes: 1 addition & 1 deletion ivy-graphics/src/mesh_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
use ash::vk::{DescriptorSet, IndexType};
use flax::{entity_ids, Component, Fetch, FetchExt, OptOr, Query, World};
use glam::{Mat4, Quat, Vec3, Vec4};
use ivy_base::{color, main_camera, position, rotation, scale, Color, ColorExt};
use ivy_base::{color, main_camera, position, rotation, scale, Color, ColorExt, Visible};
use ivy_resources::{Handle, Resources};
use ivy_vulkan::{context::SharedVulkanContext, descriptors::IntoSet, PassInfo, Shader};

Expand Down
6 changes: 4 additions & 2 deletions ivy-ui/src/components.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Font, Image, InputField, Text};
use crate::{Font, Image, InputField, Text, WidgetLayout};
use flax::{Entity, EntityBuilder, EntityRef, World};
pub use fontdue::layout::{HorizontalAlign, VerticalAlign};
use glam::Vec2;
Expand Down Expand Up @@ -32,6 +32,8 @@ flax::component! {
pub origin: Vec2,
pub margin: Vec2,

pub widget_layout: WidgetLayout,

pub children: Vec<Entity>,

pub canvas: (),
Expand Down Expand Up @@ -169,7 +171,7 @@ impl TextBundle {
.set(wrap(), self.wrap)
.set(alignment(), self.align)
.set(margin(), self.margin)
.set(text(), self.text)
.set(text(), self.text);
}
}

Expand Down
2 changes: 1 addition & 1 deletion ivy-ui/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ pub enum Error {
MissingGlyph(u16),

#[error("UI ecs error: {0}")]
EcsError(#[from] hecs_schedule::Error),
EcsError(#[from] flax::Error),
}
32 changes: 15 additions & 17 deletions ivy-ui/src/image_renderer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::*;
use flax::{entity_ids, Component, Fetch, Query, World};
use glam::{vec2, vec3, Mat4, Vec2, Vec3, Vec4};
use ivy_base::{color, position, size, Color};
use ivy_base::{color, position, size, visible, Color, ColorExt};
use ivy_graphics::{batch_id, BaseRenderer, Mesh, Renderer};
use ivy_resources::{Handle, Resources};
use ivy_vulkan::{context::SharedVulkanContext, descriptors::*, vk::IndexType, PassInfo, Shader};
Expand Down Expand Up @@ -55,7 +55,7 @@ impl Renderer for ImageRenderer {
offsets: &[u32],
current_frame: usize,
shaderpass: Component<Shader>,
) -> Result<()> {
) -> anyhow::Result<()> {
cmd.bind_vertexbuffer(0, self.square.vertex_buffer());
cmd.bind_indexbuffer(self.square.index_buffer(), IndexType::UINT32, 0);

Expand All @@ -72,17 +72,16 @@ impl Renderer for ImageRenderer {
entity_ids(),
batch_id(shaderpass.id()),
ObjectDataQuery::new(),
visible(),
))
.borrow(world)
.iter()
.filter_map(|(e, &batch_id, obj /* , bound */)| {
// if visible.is_visible()
// && camera.visible(**obj.position, **bound * obj.scale.max_element())
// {
Some((e, batch_id, ObjectData::from(obj)))
// } else {
// None
// }
.filter_map(|(e, &batch_id, obj, visible)| {
if visible.is_visible() {
Some((e, batch_id, ObjectData::from(obj)))
} else {
None
}
}),
)?;

Expand Down Expand Up @@ -123,13 +122,13 @@ struct ObjectData {
}

#[derive(Fetch)]
struct ObjectDataQuery<'a> {
struct ObjectDataQuery {
position: Component<Vec3>,
size: Component<Vec2>,
color: Component<Color>,
}

impl<'a> ObjectDataQuery<'a> {
impl ObjectDataQuery {
fn new() -> Self {
Self {
position: position(),
Expand All @@ -139,12 +138,11 @@ impl<'a> ObjectDataQuery<'a> {
}
}

impl<'a> Into<ObjectData> for ObjectDataQuery<'a> {
fn into(self) -> ObjectData {
impl<'a> From<ObjectDataQueryItem<'a>> for ObjectData {
fn from(value: ObjectDataQueryItem<'_>) -> ObjectData {
ObjectData {
mvp: Mat4::from_translation(self.position.extend(0.0))
* Mat4::from_scale(self.size.extend(1.0)),
color: self.color.into(),
mvp: Mat4::from_translation(*value.position) * Mat4::from_scale(value.size.extend(1.0)),
color: value.color.to_vec4(),
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions ivy-ui/src/input_field.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use flax::{Entity, EntityBuilder, Mutable, Query, QueryBorrow, System};
use flax::{BoxedSystem, Entity, EntityBuilder, Mutable, Query, QueryBorrow, System};
use glfw::{Action, Key, Modifiers};

use ivy_base::Events;

use crate::{
events::WidgetEvent, input_field, interactive, sticky, text, InteractiveState, Result, Text,
events::WidgetEvent, input_field, interactive, sticky, text, InteractiveState, Text,
WidgetEventKind,
};

Expand All @@ -28,7 +28,7 @@ impl InputFieldBundle {
entity
.set_default(interactive())
.set_default(sticky())
.set(input_field(), self.field)
.set(input_field(), self.field);
}
}

Expand Down Expand Up @@ -56,18 +56,18 @@ pub fn input_field_system(
// state: Read<InteractiveState>,
reader: flume::Receiver<WidgetEvent>,
// mut events: Write<Events>,
) -> Result<()> {
) -> BoxedSystem {
System::builder()
.with_query(Query::new((input_field().as_mut(), text().as_mut())))
.with_input::<InteractiveState>()
.with_input_mut::<InteractiveState>()
.with_input_mut::<Events>()
.build(
|mut query: QueryBorrow<(Mutable<InputField>, Mutable<Text>)>,
|mut query: QueryBorrow<(Mutable<InputField>, Mutable<Text>), _>,
state: &mut InteractiveState,
events: &mut Events| {
let focused = match state.focused() {
Some(val) => val,
None => return Ok(()),
None => return anyhow::Ok(()),
};

let Ok((field, text)) = query.get(focused) else {
Expand All @@ -78,14 +78,14 @@ pub fn input_field_system(
// None => return Ok(()),
// };

reader.for_each(|event| match event.kind {
reader.try_iter().for_each(|event| match event.kind {
WidgetEventKind::Focus(false)
| WidgetEventKind::Key {
key: Key::Enter,
action: Action::Press,
..
} => {
(field.on_submit)(focused, &mut events, text.val());
(field.on_submit)(focused, events, text.val());
}
WidgetEventKind::CharTyped(c) => {
text.append(c);
Expand Down
2 changes: 1 addition & 1 deletion ivy-ui/src/layer/event_handling.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use hecs::Entity;
use flax::Entity;
use ivy_base::Events;

use crate::{events::WidgetEvent, WidgetEventKind};
Expand Down
20 changes: 10 additions & 10 deletions ivy-ui/src/layer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use ivy_input::InputEvent;
use ivy_resources::Resources;
use ivy_window::Window;

use crate::{canvas, handle_events, input_field_system, systems, Canvas, UIControl};
use crate::{canvas, handle_events, input_field_system, update_system, UIControl};
mod event_handling;
pub use event_handling::*;

Expand All @@ -16,12 +16,13 @@ pub use event_handling::*;
/// through the world in the form of [`ivy-input::InputEvent`]s.
pub struct UILayer {
state: InteractiveState,
update_canvas: BoxedSystem,
schedule: Schedule,
}

impl UILayer {
pub fn new(
_world: &mut World,
world: &mut World,
_resources: &mut Resources,
events: &mut Events,
) -> anyhow::Result<Self> {
Expand All @@ -34,16 +35,13 @@ impl UILayer {

let schedule = Schedule::builder()
.with_system(handle_events_system(window_rx, control_rx))
.with_system(move |w: SubWorld<_>, state: Read<_>, events: Write<_>| {
input_field_system(w, state, input_field_rx.try_iter(), events)
})
.with_system(input_field_system(input_field_rx))
.build();

eprintln!("UI Layer: {}", schedule.batch_info());

Ok(Self {
state: InteractiveState::default(),
schedule,
update_canvas: update_system(),
})
}
}
Expand All @@ -56,7 +54,9 @@ impl Layer for UILayer {
events: &mut Events,
_frame_time: std::time::Duration,
) -> anyhow::Result<()> {
systems::update(world)?;
self.update_canvas
.run(world)
.context("Failed to update canvas")?;

let window = resources.get_default::<Window>()?;
// Transform the cursor position to canvas size
Expand All @@ -76,7 +76,7 @@ impl Layer for UILayer {
let mut cursor_pos = cursor_pos * *size;

self.schedule
.execute_seq((world, events, &mut self.state, &mut cursor_pos))
.execute_seq_with(world, (events, &mut self.state, &mut cursor_pos))
.context("Failed to execute UI schedule")?;

Ok(())
Expand All @@ -96,7 +96,7 @@ fn handle_events_system(
|world: &mut World,
events: &mut Events,
state: &mut InteractiveState,
cursor_pos: &Vec2| {
&cursor_pos: &Vec2| {
handle_events(
world,
events,
Expand Down
27 changes: 15 additions & 12 deletions ivy-ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{apply_constraints, children, components, update_from, Alignment, Result};
use flax::{Entity, EntityRef, World};
use crate::{apply_constraints, children, update_from, Alignment, Result};
use flax::{EntityRef, World};
use fontdue::layout::{HorizontalAlign, VerticalAlign};
use glam::Vec2;

Expand Down Expand Up @@ -45,9 +45,11 @@ impl WidgetLayout {
.map(|&v| world.entity(v).unwrap());

let total_size: Vec2 = iter.try_fold(Vec2::default(), |acc, child| -> Result<Vec2> {
apply_constraints(world, child, position, size, is_visible)?;
apply_constraints(world, &child, position, size, is_visible)?;

let child_size = world.get(child, ivy_base::components::size())?;
let child_size = child
.get(ivy_base::components::size())
.expect("Missing size");
// let child_size = world.try_get::<Vec2>(child)?;

Ok(acc + *child_size)
Expand Down Expand Up @@ -81,17 +83,17 @@ impl WidgetLayout {
LayoutKind::Horizontal => {
let mut cursor = Vec2::new(x, y);
iter.try_for_each(|child| -> Result<()> {
apply_constraints(world, child, position, size, is_visible)?;
apply_constraints(world, &child, position, size, is_visible)?;
{
let child_position =
let mut child_position =
child.get_mut(ivy_base::components::position()).unwrap();
let child_size = child.get_copy(ivy_base::components::size()).unwrap();

*child_position = cursor; //+ Position2D(**child_size);
*child_position = cursor.extend(0.0); //+ Position2D(**child_size);
cursor.x += child_size.x * 2.0 + self.spacing.x;
}

update_from(world, child, depth + 1)?;
update_from(world, &child, depth + 1)?;
Ok(())
})?
}
Expand All @@ -105,23 +107,24 @@ impl WidgetLayout {

let mut cursor = Vec2::new(x, y);
iter.try_for_each(|child| -> Result<()> {
apply_constraints(world, child.id(), position, size, is_visible)?;
apply_constraints(world, &child, position, size, is_visible)?;
{
let child_position =
let mut child_position =
child.get_mut(ivy_base::components::position()).unwrap();
let child_size = child.get_copy(ivy_base::components::size()).unwrap();

// let mut query = world.try_query_one::<(&mut Position2D, &Size2D)>(child)?;

// let (child_pos, child_size) = query.get()?;

*child_position = cursor + Vec2::new(child_size.x * offset_x, 0.0);
*child_position =
(cursor + Vec2::new(child_size.x * offset_x, 0.0)).extend(0.0);
cursor.y -= child_size.y * 2.0 + self.spacing.y;
}

// drop(query);

update_from(world, child, depth + 1)?;
update_from(world, &child, depth + 1)?;
Ok(())
})?
}
Expand Down
Loading

0 comments on commit fc8ee57

Please sign in to comment.