[−][src]Trait screen_13::Screen
A window-painting and user input handling type.
Types implementing Screen
are able to render frames to the presentation buffers and
optionally update the current screen. 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:
render
: Provide aRender
instance in which rendering operations have been recorded.update
: Respond to window input and either returnself
(no change) or a newDynScreen
.
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); } }