139 lines
5.6 KiB
Rust
139 lines
5.6 KiB
Rust
|
use godot::prelude::*;
|
||
|
use godot::classes::{ConfigFile, Engine, DisplayServer, display_server::{WindowFlags, WindowMode, VSyncMode}, window::WindowInitialPosition};
|
||
|
#[derive(GodotClass)]
|
||
|
#[class(base=Node)]
|
||
|
|
||
|
struct Config {
|
||
|
// DISCUSSION: Should we expose these in-editor so the default values can be modified?
|
||
|
|
||
|
#[export(file = "")]
|
||
|
config_path: GString,
|
||
|
#[var]
|
||
|
window_height: i32,
|
||
|
#[var]
|
||
|
window_width: i32,
|
||
|
#[var]
|
||
|
is_fullscreen: bool,
|
||
|
#[var]
|
||
|
is_borderless: bool,
|
||
|
#[var]
|
||
|
monitor: i32,
|
||
|
#[var]
|
||
|
window_position_x: i32,
|
||
|
#[var]
|
||
|
window_position_y: i32,
|
||
|
#[var]
|
||
|
max_framerate: i32,
|
||
|
#[var]
|
||
|
vertical_sync: bool,
|
||
|
#[var]
|
||
|
resolution_scale: f32,
|
||
|
|
||
|
|
||
|
base: Base<Node>,
|
||
|
}
|
||
|
|
||
|
#[godot_api]
|
||
|
impl INode for Config {
|
||
|
fn init(base: Base<Node>) -> Self {
|
||
|
|
||
|
Self {
|
||
|
config_path: GString::from("res://config.toml"),
|
||
|
window_height: 600,
|
||
|
window_width: 400,
|
||
|
is_fullscreen: false,
|
||
|
is_borderless: true,
|
||
|
monitor: 0,
|
||
|
window_position_x: 0,
|
||
|
window_position_y: 0,
|
||
|
max_framerate: 60,
|
||
|
vertical_sync: true,
|
||
|
resolution_scale: 1.0,
|
||
|
|
||
|
base,
|
||
|
|
||
|
}
|
||
|
}
|
||
|
fn enter_tree(&mut self) {
|
||
|
let editor_hint = Engine::singleton().is_editor_hint();
|
||
|
|
||
|
let mut config = ConfigFile::new_gd();
|
||
|
|
||
|
let res = config.load(GString::from("res://config.toml"));
|
||
|
|
||
|
if res != godot::global::Error::OK {
|
||
|
godot_error!("Failed to load config file");
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
//TODO This could be improved
|
||
|
//// GDext doesn's support defining defaults at this moment, and there's no way in hell I'm implementing checks for each config key.
|
||
|
//// If a config field is missing, it should throw an error, but not halt the whole demo
|
||
|
//
|
||
|
// We can get the keys and sections with get_sections() and get_section_keys() and then iterate over each one and load them if they match with the Config struct
|
||
|
//
|
||
|
self.window_width = config.get_value(GString::from("window"), GString::from("width")).to::<i32>();
|
||
|
self.window_height = config.get_value(GString::from("window"), GString::from("height")).to::<i32>();
|
||
|
self.is_fullscreen = config.get_value(GString::from("window"), GString::from("fullscreen")).to::<bool>();
|
||
|
self.is_borderless = config.get_value(GString::from("window"), GString::from("borderless")).to::<bool>();
|
||
|
self.window_position_x = config.get_value(GString::from("window"), GString::from("position_x")).to::<i32>();
|
||
|
self.window_position_y = config.get_value(GString::from("window"), GString::from("position_y")).to::<i32>();
|
||
|
self.monitor = config.get_value(GString::from("window"), GString::from("monitor")).to::<i32>();
|
||
|
|
||
|
self.max_framerate = config.get_value(GString::from("graphics"), GString::from("max_framerate")).to::<i32>();
|
||
|
self.vertical_sync = config.get_value(GString::from("graphics"), GString::from("vertical_sync")).to::<bool>();
|
||
|
self.resolution_scale = config.get_value(GString::from("graphics"), GString::from("resolution_scale")).to::<f32>();
|
||
|
}
|
||
|
if !editor_hint {
|
||
|
// THIS CHECK IS VERY IMPORTANT!!! I don't want to fuck my godot up again by resizing the editor and moving it out of bounds..
|
||
|
Self::apply_video_settings(self);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[godot_api]
|
||
|
impl Config {
|
||
|
#[func]
|
||
|
fn apply_video_settings(&mut self) {
|
||
|
let mut disp_server = DisplayServer::singleton();
|
||
|
let mut window = self.base().get_window().unwrap();
|
||
|
let mut engine = Engine::singleton();
|
||
|
let initial_window_size = disp_server.window_get_size();
|
||
|
|
||
|
let window_offset_after_resize: Vector2i = Vector2i::from_array([(self.window_width - initial_window_size.x) / 2, (self.window_height - initial_window_size.y) / 2]);
|
||
|
if self.is_fullscreen {
|
||
|
disp_server.window_set_mode(WindowMode::FULLSCREEN)
|
||
|
}
|
||
|
else {
|
||
|
disp_server.window_set_mode(WindowMode::WINDOWED)
|
||
|
}
|
||
|
|
||
|
if self.vertical_sync {
|
||
|
disp_server.window_set_vsync_mode(VSyncMode::ENABLED);
|
||
|
}
|
||
|
else {
|
||
|
disp_server.window_set_vsync_mode(VSyncMode::DISABLED);
|
||
|
}
|
||
|
|
||
|
disp_server.window_set_flag(WindowFlags::BORDERLESS, self.is_borderless);
|
||
|
disp_server.window_set_current_screen(self.monitor);
|
||
|
disp_server.window_set_size(Vector2i::from_array([self.window_width, self.window_height]));
|
||
|
|
||
|
//FIXME: Doesn't seem to work on Linux, at least not on KDE+Wayland. Most likely an issue with Godot itself
|
||
|
// as trying to set the window position from GDscript doesn't work either...
|
||
|
// EDIT: It worked for a moment, then broke again... weird
|
||
|
window.set_initial_position(WindowInitialPosition::ABSOLUTE);
|
||
|
|
||
|
if cfg!(debug_assertions) {
|
||
|
godot_print!("WINDOW SIZE: {}, {}", initial_window_size.x, initial_window_size.y);
|
||
|
godot_print!("Initial size: {}, {}", initial_window_size.x, initial_window_size.y);
|
||
|
godot_print!("offset: {}, {}", window_offset_after_resize.x, window_offset_after_resize.y);
|
||
|
godot_print!("New pos: {}, {}", self.window_position_x - window_offset_after_resize.x, self.window_position_y - window_offset_after_resize.y);
|
||
|
}
|
||
|
|
||
|
window.set_position(Vector2i::from_array([self.window_position_x - window_offset_after_resize.x, initial_window_size.y - window_offset_after_resize.y]));
|
||
|
engine.set_max_fps(self.max_framerate);
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|