[−][src]Trait screen_13::Screen
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:
render: Provide aRenderinstance 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); } }