d7engine/
lib.rs

1//! d7engine dokumentation
2//! basic setup
3
4pub mod core;
5
6use gl;
7use sdl2::surface::Surface;
8use sdl2::keyboard::Keycode;
9use std::collections::HashSet;
10use crate::core::mouse;
11use crate::core::project::Performance;
12
13/*
14entry function for every project
15supply the config and runtime structs
16
17init sdl and opengl and run the gameloop
18*/
19pub fn init(config: crate::core::project::Config, runtime: &mut impl crate::core::project::Runtime) {
20    // init sdl and the video subsystem
21    let sdl = sdl2::init().unwrap();
22    let video_subsystem = sdl.video().unwrap();
23
24    // opengl settings
25    let gl_attr = video_subsystem.gl_attr();
26    gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
27    // version
28    gl_attr.set_context_version(3, 3);
29    // double buffering
30    gl_attr.set_double_buffer(true);
31
32    // create the window using opengl and make it resizable
33    let mut window = video_subsystem
34        .window(&config.title, config.width, config.height)
35        .opengl()
36        .resizable()
37        .build()
38        .unwrap();
39
40    // create an opengl context
41    let _gl_context = window.gl_create_context().unwrap();
42
43    // set the window icon
44    if let Ok(window_icon) = Surface::load_bmp("icon.bmp") {
45        window.set_icon(window_icon);
46    }
47
48    // tell opengl where the video subsystem is on the memeory
49    let _gl = gl::load_with(
50        |ptr| video_subsystem.gl_get_proc_address(ptr) as *const _
51    );
52
53    // set vsync
54    video_subsystem.gl_set_swap_interval(1).unwrap();
55
56    // set the viewport to a the initial values
57    set_viewport(config.width as i32, config.height as i32);
58
59    // event_pump holds all user input events like key or mouse button clicks
60    let mut event_pump = sdl.event_pump().unwrap();
61
62    unsafe {
63        // set the default background color
64        let color = config.background_color;
65        gl::ClearColor(color.r, color.g, color.b, 1.0);
66        // enable alpha drawing
67        gl::Enable(gl::BLEND);
68        gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
69    }
70
71    // create the window struct with width and height
72    let mut win = core::window::Window::new(config.width as f32, config.height as f32);
73
74    // create the performance object
75    let mut performance = Performance::new();
76
77    // call the projects load funtion
78    runtime.load();
79  
80    'main: loop {
81        let mut mws = crate::core::mouse::MouseWheelState::None;
82      
83        // handling of events
84        for event in event_pump.poll_iter() {
85            match event {
86                sdl2::event::Event::Quit{..} => break 'main,
87                _ => {}
88            }
89
90            // resize the viewport after resizing the window
91            if let sdl2::event::Event::Window { win_event, .. } = event {
92                if let sdl2::event::WindowEvent::Resized(width, height) = win_event {
93                    // create the window struct with width and height
94                    win = core::window::Window::new(width as f32, height as f32);
95                    set_viewport(width, height);
96                }
97            }
98           
99            // handle the mouse wheel, check if y greater or less than 0 
100            if let sdl2::event::Event::MouseWheel {y, ..} = event {
101                mws = if y < 0 {
102                    crate::core::mouse::MouseWheelState::Down
103                } else {
104                    crate::core::mouse::MouseWheelState::Up
105                };
106            }
107        }
108
109        // create a new mouse struct thats holds the data for our draw struct
110        let mouse_state = event_pump.mouse_state();
111        let mouse = mouse::Mouse::new(
112            mouse_state.x() as f32, 
113            mouse_state.y() as f32, 
114            mouse_state.left(), 
115            mouse_state.right(), 
116            mws
117        );
118
119        // Create a set of pressed Keys.
120        let hashset_keys: HashSet<Keycode> = event_pump
121            .keyboard_state()
122            .pressed_scancodes()
123            .filter_map(Keycode::from_scancode)
124            .collect();
125
126        // Create a vec of Strings to 
127        // pass to draw functions
128        let mut keys = vec![];
129        for key in hashset_keys {
130            keys.push(key.to_string());
131        }
132
133        // create the draw struct 
134        // that will be passed to draw functions
135        let draw = crate::core::project::Draw {
136            performance: performance.clone(),
137            window: win,
138            mouse: mouse,
139            keys: keys,
140        };
141     
142        unsafe {
143            // clear the screen
144            gl::Clear(gl::COLOR_BUFFER_BIT);
145        }
146
147        // call the projects draw method
148        runtime.update(&draw);
149        
150        // sdl will change the window its draing to
151        window.gl_swap_window();
152
153        // performance tick
154        performance.frame();
155    }
156
157}
158
159/*
160always set the viewport to be a square so 
161rects on different resolutions are the same ratio
162*/
163fn set_viewport(width: i32, height: i32) {
164    unsafe {
165        gl::Viewport(0, 0, width, height);
166    }
167}