gym_rs/utils/renderer.rs
1use derive_new::new;
2use serde::Serialize;
3
4/// A structure which lazily invokes renders and stores the resulting frames.
5#[derive(Debug, Serialize, Clone)]
6pub struct Renderer {
7 /// A list of render modes which should not produce any frames.
8 no_returns_render: Vec<RenderMode>,
9 /// A list of render modes which produce exactly one frame when it's associated render closure
10 /// is called.
11 single_render: Vec<RenderMode>,
12 /// The render mode associated with the environment holding this render-responsible object.
13 mode: RenderMode,
14 /// The renders produced in cronological order.
15 render_list: Vec<RenderFrame>,
16}
17
18/// Describes a lifetime associated closure which takes in a render-mode,
19/// extracts the required details from the environment's state and produces the frame associated
20/// with the render-mode.
21type RenderFn<'a> = &'a mut dyn FnMut(RenderMode) -> Renders;
22
23/// Describes the render-specific operations.
24impl Renderer {
25 /// Constructs an instance of the Renderer object with an empty set of frames.
26 pub fn new(
27 mode: RenderMode,
28 no_returns_render: Option<Vec<RenderMode>>,
29 single_render: Option<Vec<RenderMode>>,
30 ) -> Self {
31 Self {
32 no_returns_render: no_returns_render.unwrap_or(RenderMode::NO_RETURNS_RENDER.to_vec()),
33 single_render: single_render.unwrap_or(RenderMode::SINGLE_RENDER.to_vec()),
34 mode,
35 render_list: Vec::new(),
36 }
37 }
38
39 /// Renders a frame using the given render closure if structure conditions are met.
40 pub fn render_step<'b>(&mut self, render: RenderFn<'b>) {
41 if self.mode != RenderMode::None && !self.single_render.contains(&self.mode) {
42 let render_return = render(self.mode);
43 if !self.no_returns_render.contains(&self.mode) {
44 match render_return {
45 Renders::SingleRgbArray(frame) => self.render_list.push(frame),
46 _ => (),
47 }
48 }
49 }
50 }
51
52 /// Supplies the list of frames collected thus far.
53 pub fn get_renders<'b>(&mut self, render: RenderFn<'b>) -> Renders {
54 if self.single_render.contains(&self.mode) {
55 render(self.mode)
56 } else if self.mode != RenderMode::None && !self.no_returns_render.contains(&self.mode) {
57 let renders = self.render_list.clone();
58 self.render_list = Vec::new();
59 Renders::RgbArray(renders)
60 } else {
61 Renders::None
62 }
63 }
64
65 /// Empties the collection of frames collected.
66 pub fn reset(&mut self) {
67 self.render_list = Vec::new();
68 }
69}
70
71/// Defines various palettes capabling of describing the colour of a pixel.
72#[derive(Debug, new, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
73pub enum RenderColor {
74 /// Holds the red-green-blue values of some pixel.
75 RGB(u8, u8, u8),
76}
77
78/// A surface which holds pixels describing the contents produced during a render.
79#[derive(Debug, new, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize)]
80pub struct RenderFrame(pub Vec<Vec<RenderColor>>);
81
82/// A collection of various formats describing the type of content produced during a render.
83#[derive(PartialEq, PartialOrd, Debug, Clone, Copy, Serialize, Eq, Ord)]
84pub enum RenderMode {
85 /// Indicates that that renderer should be done through the terminal or an external display.
86 Human,
87 /// Indicates that the renderer should produce a single frame containing RGB pixels which describe the
88 /// current state of the environment.
89 SingleRgbArray,
90 /// Indicates that the renderer should produce a list containing all the frames collected
91 /// starting from the last reset.
92 RgbArray,
93 /// Indicates that the renderer should produce a text-representation of the contents found in the
94 /// environments current state
95 Ansi,
96 /// Indicates that renderer should be skipped.
97 None,
98}
99
100impl Default for RenderMode {
101 fn default() -> Self {
102 Self::None
103 }
104}
105
106impl RenderMode {
107 /// Defines an empty set of render modes.
108 ///
109 /// This is useful for when you want to create an renderer which shouldn't
110 /// support any rendering at all.
111 pub const DEFAULT: &'static [RenderMode] = &[];
112
113 const NO_RETURNS_RENDER: &'static [RenderMode] = &[RenderMode::Human];
114 const SINGLE_RENDER: &'static [RenderMode] = &[RenderMode::SingleRgbArray];
115}
116
117/// Defines a collection of common structures produced during rendering.
118#[derive(PartialEq, PartialOrd, Debug, Clone, Serialize, Ord, Eq)]
119pub enum Renders {
120 /// Defines the structure produced during the use of the SingleRgbArray mode.
121 SingleRgbArray(RenderFrame),
122 /// Defines the collection of frames produced during the RgbArray mode.
123 RgbArray(Vec<RenderFrame>),
124 /// Defines the collection of row strings produced to represent the contents
125 /// of the environment when using Ansi mode.
126 Ansi(Vec<String>),
127 /// Indicates that no render has been produced.
128 ///
129 /// Most commonly used during Human or None mode.
130 None,
131}