1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::{
    render::{
        error::RenderError,
        settings::{RendererSettings, WgpuSettings},
        Renderer,
    },
    window::{HeadedMapWindow, MapWindowConfig},
};

#[derive(Clone)]
pub struct RendererBuilder {
    wgpu_settings: Option<WgpuSettings>,
    renderer_settings: Option<RendererSettings>,
}

impl RendererBuilder {
    pub fn new() -> Self {
        Self {
            wgpu_settings: None,
            renderer_settings: None,
        }
    }

    pub fn with_renderer_settings(mut self, renderer_settings: RendererSettings) -> Self {
        self.renderer_settings = Some(renderer_settings);
        self
    }

    pub fn with_wgpu_settings(mut self, wgpu_settings: WgpuSettings) -> Self {
        self.wgpu_settings = Some(wgpu_settings);
        self
    }

    pub fn build(self) -> UninitializedRenderer {
        UninitializedRenderer {
            wgpu_settings: self.wgpu_settings.unwrap_or_default(),
            renderer_settings: self.renderer_settings.unwrap_or_default(),
        }
    }
}

impl Default for RendererBuilder {
    fn default() -> Self {
        Self::new()
    }
}

pub enum InitializationResult {
    Initialized(InitializedRenderer),
    Uninitialized(UninitializedRenderer),
    Gone,
}

impl Default for InitializationResult {
    fn default() -> Self {
        Self::Gone
    }
}

impl InitializationResult {
    pub fn unwrap_renderer(self) -> InitializedRenderer {
        match self {
            InitializationResult::Initialized(renderer) => renderer,
            InitializationResult::Uninitialized(_) => panic!("Renderer is not initialized"),
            InitializationResult::Gone => panic!("Initialization context is gone"),
        }
    }

    pub fn into_option(self) -> Option<Renderer> {
        match self {
            InitializationResult::Initialized(InitializedRenderer { renderer, .. }) => {
                Some(renderer)
            }
            InitializationResult::Uninitialized(_) => None,
            InitializationResult::Gone => panic!("Initialization context is gone"),
        }
    }
}

pub struct UninitializedRenderer {
    pub wgpu_settings: WgpuSettings,
    pub renderer_settings: RendererSettings,
}

impl UninitializedRenderer {
    /// Initializes the whole rendering pipeline for the given configuration.
    /// Returns the initialized map, ready to be run.
    pub async fn initialize_renderer<MWC>(
        self,
        existing_window: &MWC::MapWindow,
    ) -> Result<InitializationResult, RenderError>
    where
        MWC: MapWindowConfig,
        <MWC as MapWindowConfig>::MapWindow: HeadedMapWindow,
    {
        let renderer = Renderer::initialize(
            existing_window,
            self.wgpu_settings.clone(),
            self.renderer_settings,
        )
        .await?;
        Ok(InitializationResult::Initialized(InitializedRenderer {
            renderer,
        }))
    }
}

#[cfg(feature = "headless")]
impl UninitializedRenderer {
    pub(crate) async fn initialize_headless<MWC>(
        self,
        existing_window: &MWC::MapWindow,
    ) -> Result<Renderer, RenderError>
    where
        MWC: MapWindowConfig,
    {
        Renderer::initialize_headless(
            existing_window,
            self.wgpu_settings.clone(),
            self.renderer_settings,
        )
        .await
    }
}

pub struct InitializedRenderer {
    pub renderer: Renderer,
}