Skip to main content

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}