[][src]Trait screen_13::Screen

pub trait Screen {
    pub fn render(&self, gpu: &Gpu, dims: Extent) -> Render;
pub fn update(self: Box<Self>, gpu: &Gpu, input: &Input) -> DynScreen; }

A window-painting and user input handling type.

Types implementing Screen are able to present high-frequency images to the user and control the flow of the program by switching out Screen implementations on the fly. Instances of Screen are provided to Engine for normal use, but can also be owned in a parent-child relationship to create sub-screens or to dynamically render.

NOTE: See the fx module for some pre-built examples of such screen ownership structures.

While a program event loop is running the Screen functions are called repeatedly in this order:

  1. render: Provide a Render instance in which rendering operations have been recorded.
  2. update: Respond to window input and either return self (no change) or a new DynScreen.

Implementing Screen

Implementors of Screen invariably need to access resources loaded or read from the Gpu, such as bitmaps and models. To accomplish resource access you might either offer a loading function or perform the needed loads at runtime, using RefCell to gain interior mutability during the render(...) call.

Example load before render:

impl FooScreen {
    fn load(gpu: &Gpu, pak: &mut PakFile) -> Self {
        Self {
            bar: gpu.read_bitmap(gpu, &mut pak, "bar"),
        }
    }
}

Example load during render (update works too):

impl Screen for FooScreen {
    fn render(&self, gpu: &Gpu, dims: Extent) -> Render {
        *self.bar.borrow_mut() = Some(gpu.read_bitmap(gpu, self.pak.borrow_mut(), "bar"));
        ...
    }

    ...
}

Required methods

pub fn render(&self, gpu: &Gpu, dims: Extent) -> Render[src]

When paired with an Engine, generates images presented to the physical display adapter using a swapchain and fullscreen video mode or operating system window.

Examples

Calling render on another Screen:

let foo: DynScreen = ...
let gpu = Gpu::offscreen();

// Ask foo to render a document
let foo_doc = foo.render(&gpu, Extent::new(1024, 128));

// 🤮 Ugh! I didn't like it!
foo_doc.clear().record();

println!("{:?}", foo_doc);

Responding to render as a Screen implementation:

fn render(&self, gpu: &Gpu, dims: Extent) -> Render {
    let frame = gpu.render(dims);

    // 🥇 It's some of my best work!
    frame.clear().with_value(GREEN).record();

    frame
}

NOTE: It is considered undefined behavior to return a render which has not recorded any commands, as shown:

fn render(&self, gpu: &Gpu, dims: Extent) -> Render {
    // This is UB because the graphics hardware might have been using this render to store
    // an 8K atlas of 😸's, and it is not guaranteed to be initialized.
    // Hey, the more you know!
    gpu.render(dims)
}

pub fn update(self: Box<Self>, gpu: &Gpu, input: &Input) -> DynScreen[src]

Responds to user input and either provides a new DynScreen instance or self to indicate no-change. After update(...), render(...) will be called on the returned screen, and the previous screen will be dropped.

Examples

Render this screen forever, never responding to user input or exiting:

fn update(self: Box<Self>, gpu: &Gpu, input: &Input) -> DynScreen {
    // 🙈 Yolo!
    self
}

A kind of three way junction. Goes to BarScreen when Home is pressed, otherwise presents the current screen, rendering for five seconds before quitting:

fn update(self: Box<Self>, gpu: &Gpu, input: &Input) -> DynScreen {
    let wall_time = ...
    if input.keys.is_key_down(Key::Home) {
        Box::new(BarScreen)
    } else if wall_time < 5.0 {
        self
    } else {
        // 👋
        exit(0);
    }
}
Loading content...

Implementors

impl Screen for Fade[src]

impl Screen for Solid[src]

Loading content...