~saiko/game

6c2e3c49a66dbc73cd76cb49805a73185023fe3a — 2xsaiko 2 months ago c11aa26
ebin
5 files changed, 180 insertions(+), 174 deletions(-)

M src/testui.rs
M src/ui/element/button.rs
M src/ui/layout/border.rs
M src/ui/layout/stack.rs
M src/ui/mod.rs
M src/testui.rs => src/testui.rs +93 -87
@@ 3,116 3,122 @@ use std::rc::Rc;

use crate::{Model, Vertex};
use crate::cam::Camera;
use crate::cmd::{CommandScheduler, ExecSource, ExecState, Executor};
use crate::ui::controller::UiController;
use crate::cmd::{CommandScheduler, ExecSource};
use crate::ui::controller::{draw_elements, UiController};
use crate::ui::element::{Button, InputField, InputFieldEvent, Viewport};
use crate::ui::graphics::{DrawPreview, Graphics, StringDrawProps};
use crate::ui::layout::{BorderLayout, LayoutManager};
use crate::ui::layout::{BorderLayout, LayoutManager, StackLayout};
use crate::ui::panel::Container;
use crate::ui::rescap::ResizeCapabilities;
use crate::util::{apply, LogPipe};
use crate::util::apply;

ui_def! {
  pub impl TestUi, TestUiAccess for TestUiElements, TestUiController {
    Button => button,
    Button1 => button1,
    Button2 => button2,
    Button3 => button3,
    Button4 => button4,
  }
    pub impl TestUi, TestUiAccess for TestUiElements, TestUiController {
        Button => button,
        Button1 => button1,
        Button2 => button2,
        Button3 => button3,
        Viewport => viewport,
    }
}

pub struct TestUiElements {
  button: Container<Button>,
  button1: Container<InputField>,
  button2: Container<Button>,
  button3: Container<Button>,
  button4: Container<Viewport>,
    button: Container<Button>,
    button1: Container<InputField>,
    button2: Container<Button>,
    button3: Container<Button>,
    viewport: Container<Viewport>,
}

pub struct TestUiController {
  click_counter: u32,
  camera: Rc<RefCell<Camera>>,
  model: Rc<Model<Vertex>>,
  scheduler: CommandScheduler,
    click_counter: u32,
    fullscreen: bool,
    camera: Rc<RefCell<Camera>>,
    model: Rc<Model<Vertex>>,
    scheduler: CommandScheduler,
}

impl TestUiController {
  pub fn new(camera: Rc<RefCell<Camera>>, model: Rc<Model<Vertex>>, scheduler: CommandScheduler) -> TestUi {
    TestUi::new(TestUiController {
      click_counter: 0,
      camera,
      model,
      scheduler,
    })
  }
    pub fn new(camera: Rc<RefCell<Camera>>, model: Rc<Model<Vertex>>, scheduler: CommandScheduler) -> TestUi {
        TestUi::new(TestUiController {
            click_counter: 0,
            fullscreen: false,
            camera,
            model,
            scheduler,
        })
    }

  fn get_layout(&self) -> impl LayoutManager<TestUiElements> {
    use TestUiAccess::*;
    BorderLayout::of(
      Button,
      Button1,
      Button2,
      Button3,
      Button4,
    )
  }
    fn get_layout(&self) -> Box<dyn LayoutManager<TestUiElements>> {
        use TestUiAccess::*;
        if self.fullscreen {
            box StackLayout::new(vec![Viewport])
        } else {
            box BorderLayout::of(
                Button,
                Button1,
                Button2,
                Button3,
                Viewport,
            )
        }
    }
}

impl UiController for TestUiController {
  type Elements = TestUiElements;
    type Elements = TestUiElements;

  fn create_elements(&self) -> Self::Elements {
    TestUiElements {
      button: Button::new("top"),
      button1: apply(InputField::new(), |field| field.set_overlay_text("Enter commands...")),
      button2: Button::new("left"),
      button3: Button::new("right"),
      button4: Viewport::new(self.camera.clone(), self.model.clone()),
    fn create_elements(&self) -> Self::Elements {
        TestUiElements {
            button: Button::new("top"),
            button1: apply(InputField::new(), |field| field.set_overlay_text("Enter commands...")),
            button2: Button::new("left"),
            button3: Button::new("right"),
            viewport: Viewport::new(self.camera.clone(), self.model.clone()),
        }
    }
  }

  fn update(&mut self, elements: &mut TestUiElements) {
    let TestUiElements { button, button1, button2, button3, .. } = elements;
    button.poll_events(|b, e| {
      self.click_counter += 1;
      b.set_enabled(false);
      button2.set_enabled(true);
      button3.set_enabled(true);
    });
    button2.poll_events(|b, e| {
      self.click_counter += 1;
      b.set_enabled(false);
      button.set_enabled(true);
      button3.set_enabled(true);
    });
    button3.poll_events(|b, e| {
      self.click_counter += 1;
      b.set_enabled(false);
      button2.set_enabled(true);
      button.set_enabled(true);
    });
    button1.poll_events(|b, e| {
      match e {
        InputFieldEvent::EnterPressed => {
          self.scheduler.exec(b.text(), ExecSource::Console);
          b.set_text("");
        }
        _ => {}
      }
    });
  }
    fn update(&mut self, elements: &mut TestUiElements) {
        let TestUiElements { button, button1, button2, button3, .. } = elements;
        button.poll_events(|b, e| {
            self.click_counter += 1;
            b.set_enabled(false);
            button2.set_enabled(true);
            button3.set_enabled(true);
        });
        button2.poll_events(|b, e| {
            self.click_counter += 1;
            b.set_enabled(false);
            button.set_enabled(true);
            button3.set_enabled(true);
        });
        button3.poll_events(|b, e| {
            self.click_counter += 1;
            b.set_enabled(false);
            button2.set_enabled(true);
            button.set_enabled(true);
        });
        button1.poll_events(|b, e| {
            match e {
                InputFieldEvent::EnterPressed => {
                    self.scheduler.exec(b.text(), ExecSource::Console);
                    b.set_text("");
                }
                _ => {}
            }
        });
    }

  fn resize(&mut self, elements: &mut Self::Elements, g: &Graphics, width: u32, height: u32) {
    self.get_layout().relayout(elements, g, width, height);
  }
    fn resize(&mut self, elements: &mut Self::Elements, g: &Graphics, width: u32, height: u32) {
        self.get_layout().relayout(elements, g, width, height);
    }

  fn get_resize_capabilities(&self, elements: &Self::Elements, g: &DrawPreview) -> ResizeCapabilities {
    self.get_layout().get_resize_capabilities(elements, g)
  }
    fn get_resize_capabilities(&self, elements: &Self::Elements, g: &DrawPreview) -> ResizeCapabilities {
        self.get_layout().get_resize_capabilities(elements, g)
    }

  fn draw(&mut self, elements: &mut Self::Elements, g: &mut Graphics) {
    self.default_draw(elements, g);
    g.draw_string(&format!("click counter: {}", self.click_counter), 2, 2, StringDrawProps::default());
  }
    fn draw(&mut self, elements: &mut Self::Elements, g: &mut Graphics) {
        draw_elements(elements, g);
        g.draw_string(&format!("click counter: {}", self.click_counter), 2, 2, StringDrawProps::default());
    }
}

M src/ui/element/button.rs => src/ui/element/button.rs +0 -1
@@ 6,7 6,6 @@ use crate::ui::graphics::{Alignment, DrawPreview, Graphics, StringDrawProps};
use crate::ui::panel::Container;
use crate::ui::rescap::ResizeCapabilities;
use crate::ui::util::is_in_bounds;
use crate::util::Color;

pub enum ButtonEvent {
    Pressed,

M src/ui/layout/border.rs => src/ui/layout/border.rs +4 -8
@@ 30,9 30,7 @@ pub enum Position {
/// |                 Bottom                 |
/// +----------------------------------------+
/// ```
pub struct BorderLayout<X: UiAccess, T, B, L, R, C>
    where T: LayoutManager<X>, B: LayoutManager<X>, L: LayoutManager<X>, R: LayoutManager<X>, C: LayoutManager<X>
{
pub struct BorderLayout<X, T, B, L, R, C> {
    top: T,
    bottom: B,
    left: L,


@@ 41,9 39,7 @@ pub struct BorderLayout<X: UiAccess, T, B, L, R, C>
    _phantom_data: PhantomData<X>,
}

impl<X: UiAccess, T, B, L, R, C> BorderLayout<X, T, B, L, R, C>
    where T: LayoutManager<X>, B: LayoutManager<X>, L: LayoutManager<X>, R: LayoutManager<X>, C: LayoutManager<X>
{
impl<X, T, B, L, R, C> BorderLayout<X, T, B, L, R, C> {
    pub fn of(top: T, bottom: B, left: L, right: R, center: C) -> Self {
        BorderLayout {
            top,


@@ 56,8 52,8 @@ impl<X: UiAccess, T, B, L, R, C> BorderLayout<X, T, B, L, R, C>
    }
}

impl<X: UiAccess, T, B, L, R, C> LayoutManager<X> for BorderLayout<X, T, B, L, R, C>
    where T: LayoutManager<X>, B: LayoutManager<X>, L: LayoutManager<X>, R: LayoutManager<X>, C: LayoutManager<X>
impl<X, T, B, L, R, C> LayoutManager<X> for BorderLayout<X, T, B, L, R, C>
    where X: UiAccess, T: LayoutManager<X>, B: LayoutManager<X>, L: LayoutManager<X>, R: LayoutManager<X>, C: LayoutManager<X>
{
    fn relayout_at(&self, ui: &mut X, g: &Graphics, x: i32, y: i32, width: u32, height: u32) {
        let dp = g.as_draw_preview();

M src/ui/layout/stack.rs => src/ui/layout/stack.rs +34 -30
@@ 1,30 1,34 @@
//use crate::ui::element::Element;
//use crate::ui::graphics::Graphics;
//use crate::ui::layout::LayoutManager;
//use crate::ui::panel::PanelElement;
//use crate::ui::rescap::ResizeCapabilities;
//
//pub struct StackLayout<R> {
//  elements: Vec<PanelElement<R, Box<dyn Element<R>>>>,
//}
//
//impl<R> StackLayout<R> {
//  pub fn new(elements: Vec<Box<dyn Element<R>>>) -> Self {
//    StackLayout {
//      elements: elements.into_iter().map(PanelElement::new).collect()
//    }
//  }
//}
//
//impl<R> LayoutManager<R> for StackLayout<R> {
//  fn relayout(&mut self, g: &Graphics, width: u32, height: u32) {
//    for el in self.elements.iter_mut() {
//      el.set_dimensions(0, 0, width, height);
//    }
//  }
//
//  fn get_resize_capabilities(&self, g: &Graphics) -> ResizeCapabilities {
//    self.elements.iter()
//      .fold(ResizeCapabilities::default(), |acc, a| acc.combine(a.drawable().get_resize_capabilities(g)))
//  }
//}
\ No newline at end of file
use std::marker::PhantomData;

use crate::ui::access::UiAccess;
use crate::ui::graphics::{DrawPreview, Graphics};
use crate::ui::layout::LayoutManager;
use crate::ui::rescap::ResizeCapabilities;

pub struct StackLayout<X, R> {
    elements: Vec<R>,
    _phantom_data: PhantomData<X>,
}

impl<X, R> StackLayout<X, R> {
    pub fn new(elements: Vec<R>) -> Self {
        StackLayout {
            elements,
            _phantom_data: PhantomData::default(),
        }
    }
}

impl<X, R> LayoutManager<X> for StackLayout<X, R>
    where X: UiAccess, R: LayoutManager<X> {
    fn relayout_at(&self, ui: &mut X, g: &Graphics, x: i32, y: i32, width: u32, height: u32) {
        for el in self.elements.iter() {
            el.relayout_at(ui, g, x, y, width, height);
        }
    }

    fn get_resize_capabilities(&self, ui: &X, g: &DrawPreview) -> ResizeCapabilities {
        self.elements.iter()
            .fold(ResizeCapabilities::default(), |acc, a| acc.combine(a.get_resize_capabilities(ui, g)))
    }
}
\ No newline at end of file

M src/ui/mod.rs => src/ui/mod.rs +49 -48
@@ 131,66 131,67 @@ impl<E: UiAccess + 'static, C: UiController<Elements=E>> GenUi<E, C> {

#[macro_export]
macro_rules! ui_def {
  ($vis:vis impl $ui_struct:ident, $acc_struct:ident for $el_struct:ty, $ctrl_struct:ty {
      $($variant:ident => $field:ident),* $(,)?
    ($vis:vis impl $ui_struct:ident, $acc_struct:ident for $el_struct:ty, $ctrl_struct:ty {
        $($variant:ident => $field:ident),* $(,)?
    }) => {
      _ui_def_inner!(
        $vis,
        $ui_struct,
        $el_struct,
        $ctrl_struct,
        $acc_struct,
        $($variant => $field),*
      );
        _ui_def_inner!(
            $vis,
            $ui_struct,
            $el_struct,
            $ctrl_struct,
            $acc_struct,
            $($variant => $field),*
        );
    }
}


macro_rules! _ui_def_inner {
  ($vis:vis, $ui_struct:ident, $el_struct:ty, $ctrl_struct:ty, $acc_struct:ident, $($variant:ident => $field:ident),* $(,)?) => {
    $vis type $ui_struct = $crate::ui::GenUi<$el_struct,$ctrl_struct>;
    ($vis:vis, $ui_struct:ident, $el_struct:ty, $ctrl_struct:ty, $acc_struct:ident, $($variant:ident => $field:ident),* $(,)?) => {
        $vis type $ui_struct = $crate::ui::GenUi<$el_struct,$ctrl_struct>;

    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
    $vis enum $acc_struct {
      $($variant),*
    }
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        $vis enum $acc_struct {
            $($variant),*
        }

    impl $crate::ui::layout::LayoutManager<$el_struct> for $acc_struct {
      fn relayout_at(&self, ui: &mut $el_struct, g: &$crate::ui::graphics::Graphics, x: i32, y: i32, width: u32, height: u32) {
        $crate::ui::access::UiAccess::get_element_mut(ui, *self).set_dimensions(x, y, width, height);
      }
        impl $crate::ui::layout::LayoutManager<$el_struct> for $acc_struct {
            fn relayout_at(&self, ui: &mut $el_struct, g: &$crate::ui::graphics::Graphics, x: i32, y: i32, width: u32, height: u32) {
                $crate::ui::access::UiAccess::get_element_mut(ui, *self).set_dimensions(x, y, width, height);
            }

      fn get_resize_capabilities(&self, ui: &$el_struct, g: &$crate::ui::graphics::DrawPreview) -> $crate::ui::rescap::ResizeCapabilities {
        $crate::ui::access::UiAccess::get_element(ui, *self).get_resize_capabilities(g)
      }
    }
            fn get_resize_capabilities(&self, ui: &$el_struct, g: &$crate::ui::graphics::DrawPreview) -> $crate::ui::rescap::ResizeCapabilities {
                $crate::ui::access::UiAccess::get_element(ui, *self).get_resize_capabilities(g)
            }
        }

    impl $crate::ui::access::Values for $acc_struct {
      fn values() -> &'static [Self] {
        &[$($acc_struct::$variant,)*]
      }
    }
        impl $crate::ui::access::Values for $acc_struct {
            fn values() -> &'static [Self] {
                &[$($acc_struct::$variant,)*]
            }
        }

    impl $crate::ui::access::UiAccess for $el_struct {
      type Access = $acc_struct;
        impl $crate::ui::access::UiAccess for $el_struct {
            type Access = $acc_struct;

      fn by_name(name: &str) -> Option<Self::Access> {
        match name {
          $(stringify!($field) => Some(Self::Access::$variant),)+
          _ => None
        }
      }
            fn by_name(name: &str) -> Option<Self::Access> {
                match name {
                    $(stringify!($field) => Some(Self::Access::$variant),)+
                    _ => None
                }
            }

      fn get_element(&self, access: Self::Access) -> &dyn $crate::ui::element::Positionable {
        match access {
          $(Self::Access::$variant => &self.$field,)+
        }
      }
            fn get_element(&self, access: Self::Access) -> &dyn $crate::ui::element::Positionable {
                match access {
                    $(Self::Access::$variant => &self.$field,)+
                }
            }

      fn get_element_mut(&mut self, access: Self::Access) -> &mut dyn $crate::ui::element::Positionable {
        match access {
          $(Self::Access::$variant => &mut self.$field,)+
            fn get_element_mut(&mut self, access: Self::Access) -> &mut dyn $crate::ui::element::Positionable {
                match access {
                    $(Self::Access::$variant => &mut self.$field,)+
                }
            }
        }
      }
    }
  };
    };
}
\ No newline at end of file