mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Adds fullscreen and window size settings and coverage based pixel art
scaling
This commit is contained in:
parent
ecf36cb778
commit
e5d841e62f
@ -43,6 +43,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Added a default map, which is used to speed up starting single player.
|
- Added a default map, which is used to speed up starting single player.
|
||||||
- Added a 3D renderered map, which is also used by the server to send the map
|
- Added a 3D renderered map, which is also used by the server to send the map
|
||||||
to the client.
|
to the client.
|
||||||
|
- Added fullscreen and window size to settings so that they can be persisted
|
||||||
|
- Added coverage based scaling for pixel art
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -212,6 +212,8 @@ pub enum Event {
|
|||||||
ChangeAudioDevice(String),
|
ChangeAudioDevice(String),
|
||||||
ChangeMaxFPS(u32),
|
ChangeMaxFPS(u32),
|
||||||
ChangeFOV(u16),
|
ChangeFOV(u16),
|
||||||
|
AdjustWindowSize([u16; 2]),
|
||||||
|
ToggleFullscreen,
|
||||||
ChangeAaMode(AaMode),
|
ChangeAaMode(AaMode),
|
||||||
ChangeCloudMode(CloudMode),
|
ChangeCloudMode(CloudMode),
|
||||||
ChangeFluidMode(FluidMode),
|
ChangeFluidMode(FluidMode),
|
||||||
@ -1758,6 +1760,12 @@ impl Hud {
|
|||||||
settings_window::Event::ChangeLanguage(language) => {
|
settings_window::Event::ChangeLanguage(language) => {
|
||||||
events.push(Event::ChangeLanguage(language));
|
events.push(Event::ChangeLanguage(language));
|
||||||
}
|
}
|
||||||
|
settings_window::Event::ToggleFullscreen => {
|
||||||
|
events.push(Event::ToggleFullscreen);
|
||||||
|
}
|
||||||
|
settings_window::Event::AdjustWindowSize(new_size) => {
|
||||||
|
events.push(Event::AdjustWindowSize(new_size));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,9 @@ widget_ids! {
|
|||||||
cloud_mode_list,
|
cloud_mode_list,
|
||||||
fluid_mode_text,
|
fluid_mode_text,
|
||||||
fluid_mode_list,
|
fluid_mode_list,
|
||||||
|
fullscreen_button,
|
||||||
|
fullscreen_label,
|
||||||
|
save_window_size_button,
|
||||||
audio_volume_slider,
|
audio_volume_slider,
|
||||||
audio_volume_text,
|
audio_volume_text,
|
||||||
sfx_volume_slider,
|
sfx_volume_slider,
|
||||||
@ -196,6 +199,8 @@ pub enum Event {
|
|||||||
ToggleMouseYInvert(bool),
|
ToggleMouseYInvert(bool),
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
AdjustFOV(u16),
|
AdjustFOV(u16),
|
||||||
|
AdjustWindowSize([u16; 2]),
|
||||||
|
ToggleFullscreen,
|
||||||
ChangeAaMode(AaMode),
|
ChangeAaMode(AaMode),
|
||||||
ChangeCloudMode(CloudMode),
|
ChangeCloudMode(CloudMode),
|
||||||
ChangeFluidMode(FluidMode),
|
ChangeFluidMode(FluidMode),
|
||||||
@ -1211,7 +1216,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.right_from(state.ids.mouse_zoom_invert_button, 10.0)
|
.right_from(state.ids.mouse_zoom_invert_button, 10.0)
|
||||||
.font_size(14)
|
.font_size(14)
|
||||||
.font_id(self.fonts.cyri)
|
.font_id(self.fonts.cyri)
|
||||||
.graphics_for(state.ids.button_help)
|
.graphics_for(state.ids.mouse_zoom_invert_button)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.mouse_zoom_invert_label, ui);
|
.set(state.ids.mouse_zoom_invert_label, ui);
|
||||||
|
|
||||||
@ -1241,7 +1246,7 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.right_from(state.ids.mouse_y_invert_button, 10.0)
|
.right_from(state.ids.mouse_y_invert_button, 10.0)
|
||||||
.font_size(14)
|
.font_size(14)
|
||||||
.font_id(self.fonts.cyri)
|
.font_id(self.fonts.cyri)
|
||||||
.graphics_for(state.ids.button_help)
|
.graphics_for(state.ids.mouse_y_invert_button)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.mouse_y_invert_label, ui);
|
.set(state.ids.mouse_y_invert_label, ui);
|
||||||
}
|
}
|
||||||
@ -1658,6 +1663,51 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
{
|
{
|
||||||
events.push(Event::ChangeFluidMode(mode_list[clicked]));
|
events.push(Event::ChangeFluidMode(mode_list[clicked]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fullscreen
|
||||||
|
Text::new("Fullscreen")
|
||||||
|
.font_size(14)
|
||||||
|
.font_id(self.fonts.cyri)
|
||||||
|
.down_from(state.ids.fluid_mode_list, 125.0)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.fullscreen_label, ui);
|
||||||
|
|
||||||
|
let fullscreen = ToggleButton::new(
|
||||||
|
self.global_state.settings.graphics.fullscreen,
|
||||||
|
self.imgs.checkbox,
|
||||||
|
self.imgs.checkbox_checked,
|
||||||
|
)
|
||||||
|
.w_h(18.0, 18.0)
|
||||||
|
.right_from(state.ids.fullscreen_label, 10.0)
|
||||||
|
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||||
|
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||||
|
.set(state.ids.fullscreen_button, ui);
|
||||||
|
|
||||||
|
if self.global_state.settings.graphics.fullscreen != fullscreen {
|
||||||
|
events.push(Event::ToggleFullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current screen size
|
||||||
|
if Button::image(self.imgs.settings_button)
|
||||||
|
.w_h(31.0 * 5.0, 12.0 * 2.0)
|
||||||
|
.hover_image(self.imgs.settings_button_hover)
|
||||||
|
.press_image(self.imgs.settings_button_press)
|
||||||
|
.down_from(state.ids.fullscreen_label, 12.0)
|
||||||
|
.label("Save window size")
|
||||||
|
.label_font_size(14)
|
||||||
|
.label_color(TEXT_COLOR)
|
||||||
|
.label_font_id(self.fonts.cyri)
|
||||||
|
.set(state.ids.save_window_size_button, ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
events.push(Event::AdjustWindowSize(
|
||||||
|
self.global_state
|
||||||
|
.window
|
||||||
|
.logical_size()
|
||||||
|
.map(|e| e as u16)
|
||||||
|
.into_array(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Sound Tab -----------------------------------
|
// 5) Sound Tab -----------------------------------
|
||||||
|
@ -38,7 +38,7 @@ impl PlayState for CharSelectionState {
|
|||||||
let mut current_client_state = self.client.borrow().get_client_state();
|
let mut current_client_state = self.client.borrow().get_client_state();
|
||||||
while let ClientState::Pending | ClientState::Registered = current_client_state {
|
while let ClientState::Pending | ClientState::Registered = current_client_state {
|
||||||
// Handle window events
|
// Handle window events
|
||||||
for event in global_state.window.fetch_events() {
|
for event in global_state.window.fetch_events(&mut global_state.settings) {
|
||||||
if self.char_selection_ui.handle_event(event.clone()) {
|
if self.char_selection_ui.handle_event(event.clone()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ impl PlayState for MainMenuState {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Handle window events.
|
// Handle window events.
|
||||||
for event in global_state.window.fetch_events() {
|
for event in global_state.window.fetch_events(&mut global_state.settings) {
|
||||||
match event {
|
match event {
|
||||||
Event::Close => return PlayStateResult::Shutdown,
|
Event::Close => return PlayStateResult::Shutdown,
|
||||||
// Pass events to ui.
|
// Pass events to ui.
|
||||||
|
@ -175,7 +175,7 @@ impl PlayState for SessionState {
|
|||||||
self.scene.set_select_pos(select_pos);
|
self.scene.set_select_pos(select_pos);
|
||||||
|
|
||||||
// Handle window events.
|
// Handle window events.
|
||||||
for event in global_state.window.fetch_events() {
|
for event in global_state.window.fetch_events(&mut global_state.settings) {
|
||||||
// Pass all events to the ui first.
|
// Pass all events to the ui first.
|
||||||
if self.hud.handle_event(event.clone(), global_state) {
|
if self.hud.handle_event(event.clone(), global_state) {
|
||||||
continue;
|
continue;
|
||||||
@ -583,6 +583,16 @@ impl PlayState for SessionState {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
localized_strings.log_missing_entries();
|
localized_strings.log_missing_entries();
|
||||||
}
|
}
|
||||||
|
HudEvent::ToggleFullscreen => {
|
||||||
|
global_state
|
||||||
|
.window
|
||||||
|
.toggle_fullscreen(&mut global_state.settings);
|
||||||
|
}
|
||||||
|
HudEvent::AdjustWindowSize(new_size) => {
|
||||||
|
global_state.window.set_size(new_size.into());
|
||||||
|
global_state.settings.graphics.window_size = new_size;
|
||||||
|
global_state.settings.save_to_file_warn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +195,8 @@ pub struct GraphicsSettings {
|
|||||||
pub aa_mode: AaMode,
|
pub aa_mode: AaMode,
|
||||||
pub cloud_mode: CloudMode,
|
pub cloud_mode: CloudMode,
|
||||||
pub fluid_mode: FluidMode,
|
pub fluid_mode: FluidMode,
|
||||||
|
pub window_size: [u16; 2],
|
||||||
|
pub fullscreen: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GraphicsSettings {
|
impl Default for GraphicsSettings {
|
||||||
@ -206,6 +208,8 @@ impl Default for GraphicsSettings {
|
|||||||
aa_mode: AaMode::Fxaa,
|
aa_mode: AaMode::Fxaa,
|
||||||
cloud_mode: CloudMode::Regular,
|
cloud_mode: CloudMode::Regular,
|
||||||
fluid_mode: FluidMode::Shiny,
|
fluid_mode: FluidMode::Shiny,
|
||||||
|
window_size: [1920, 1080],
|
||||||
|
fullscreen: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
mod pixel_art;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
|
|
||||||
use crate::render::{Renderer, Texture};
|
use crate::render::{Renderer, Texture};
|
||||||
@ -6,6 +7,7 @@ use guillotiere::{size2, SimpleAtlasAllocator};
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use image::{DynamicImage, RgbaImage};
|
use image::{DynamicImage, RgbaImage};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use pixel_art::resize_pixel_art;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -280,15 +282,11 @@ fn draw_graphic(graphic_map: &GraphicMap, graphic_id: Id, dims: Vec2<u16>) -> Op
|
|||||||
Some(Graphic::Blank) => None,
|
Some(Graphic::Blank) => None,
|
||||||
// Render image at requested resolution
|
// Render image at requested resolution
|
||||||
// TODO: Use source aabr.
|
// TODO: Use source aabr.
|
||||||
Some(Graphic::Image(ref image)) => Some(
|
Some(Graphic::Image(ref image)) => Some(resize_pixel_art(
|
||||||
image
|
&image.to_rgba(),
|
||||||
.resize_exact(
|
u32::from(dims.x),
|
||||||
u32::from(dims.x),
|
u32::from(dims.y),
|
||||||
u32::from(dims.y),
|
)),
|
||||||
image::FilterType::Nearest,
|
|
||||||
)
|
|
||||||
.to_rgba(),
|
|
||||||
),
|
|
||||||
Some(Graphic::Voxel(ref vox, trans, min_samples)) => Some(renderer::draw_vox(
|
Some(Graphic::Voxel(ref vox, trans, min_samples)) => Some(renderer::draw_vox(
|
||||||
&vox.as_ref().into(),
|
&vox.as_ref().into(),
|
||||||
dims,
|
dims,
|
||||||
|
146
voxygen/src/ui/graphic/pixel_art.rs
Normal file
146
voxygen/src/ui/graphic/pixel_art.rs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
use common::util::{linear_to_srgba, srgba_to_linear};
|
||||||
|
/// Pixel art scaling
|
||||||
|
/// Note: The current ui is locked to the pixel grid with little animation, if we want smoothly
|
||||||
|
/// moving pixel art this should be done in the shaders
|
||||||
|
use image::RgbaImage;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
const EPSILON: f32 = 0.0001;
|
||||||
|
|
||||||
|
// Averaging colors with alpha such that when blending with the background color the same color
|
||||||
|
// will be produced as when the individual colors were blended with the background and then
|
||||||
|
// averaged
|
||||||
|
// Say we have two areas that we are combining to form a single pixel
|
||||||
|
// A1 and A2 where these are the fraction of the area of the pixel each color contributes to
|
||||||
|
// Then if the colors were opaque we would say that the final color ouput color o3 is
|
||||||
|
// E1: o3 = A1 * o1 + A2 * o2
|
||||||
|
// where o1 and o2 are the opaque colors of the two areas
|
||||||
|
// now say the areas are actually translucent and these opaque colors are derived by blending with a
|
||||||
|
// common backgound color b
|
||||||
|
// E2: o1 = c1 * a1 + g * (1 - a1)
|
||||||
|
// E3: o2 = c2 * a2 + g * (1 - a2)
|
||||||
|
// we want to find the combined color (c3) and combined alpha (a3) such that
|
||||||
|
// E4: o3 = c3 * a3 + g * (1 - a3)
|
||||||
|
// substitution of E2 and E3 into E1 gives
|
||||||
|
// E5: o3 = A1 * (c1 * a1 + g * (1 - a1)) + A2 * (c2 * a2 + g * (1 - a2))
|
||||||
|
// combining E4 and E5 then separting like terms into separte equations gives
|
||||||
|
// E6: c3 * a3 = A1 * c1 * a1 + A2 * c2 * a2
|
||||||
|
// E7: g * (1 - a3) = A1 * g * (1 - a1) + A2 * g * (1 - a2)
|
||||||
|
// dropping g from E7 and solving for a3
|
||||||
|
// E8: a3 = 1 - A1 * (1 - a1) + A2 * (1 - a2)
|
||||||
|
// we can now calculate the combined alpha value
|
||||||
|
// and E6 can then be solved for c3
|
||||||
|
// E9: c3 = (A1 * c1 * a1 + A2 * c2 * a2) / a3
|
||||||
|
pub fn resize_pixel_art(image: &RgbaImage, new_width: u32, new_height: u32) -> RgbaImage {
|
||||||
|
let (width, height) = image.dimensions();
|
||||||
|
let mut new_image = RgbaImage::new(new_width, new_height);
|
||||||
|
|
||||||
|
// Ratio of old image dimensions to new dimensions
|
||||||
|
// Also the sampling dimensions within the old image for a single pixel in the new image
|
||||||
|
let wratio = width as f32 / new_width as f32;
|
||||||
|
let hratio = height as f32 / new_height as f32;
|
||||||
|
|
||||||
|
for x in 0..new_width {
|
||||||
|
// Calculate sampling strategy
|
||||||
|
let xsmin = x as f32 * wratio;
|
||||||
|
let xsmax = xsmin + wratio;
|
||||||
|
// Min and max pixels covered
|
||||||
|
let xminp = xsmin.floor() as u32;
|
||||||
|
let xmaxp = ((xsmax - EPSILON).ceil() as u32)
|
||||||
|
.checked_sub(1)
|
||||||
|
.unwrap_or(0);
|
||||||
|
// Fraction of first pixel to use
|
||||||
|
let first_x_frac = if xminp != xmaxp {
|
||||||
|
1.0 - xsmin.fract()
|
||||||
|
} else {
|
||||||
|
xsmax - xsmin
|
||||||
|
};
|
||||||
|
let last_x_frac = xsmax - xmaxp as f32;
|
||||||
|
for y in 0..new_height {
|
||||||
|
// Calculate sampling strategy
|
||||||
|
let ysmin = y as f32 * hratio;
|
||||||
|
let ysmax = ysmin + hratio;
|
||||||
|
// Min and max of pixels covered
|
||||||
|
let yminp = ysmin.floor() as u32;
|
||||||
|
let ymaxp = ((ysmax - EPSILON).ceil() as u32)
|
||||||
|
.checked_sub(1)
|
||||||
|
.unwrap_or(0);
|
||||||
|
// Fraction of first pixel to use
|
||||||
|
let first_y_frac = if yminp != ymaxp {
|
||||||
|
1.0 - ysmin.fract()
|
||||||
|
} else {
|
||||||
|
ysmax - ysmin
|
||||||
|
};
|
||||||
|
let last_y_frac = ysmax - ymaxp as f32;
|
||||||
|
|
||||||
|
let mut linear_color = Rgba::new(0.0, 0.0, 0.0, wratio * hratio);
|
||||||
|
// Left column
|
||||||
|
// First pixel sample (top left assuming that is the origin)
|
||||||
|
linear_color += get_linear_with_frac(image, xminp, yminp, first_x_frac * first_y_frac);
|
||||||
|
// Left edge
|
||||||
|
for j in yminp + 1..ymaxp {
|
||||||
|
linear_color += get_linear_with_frac(image, xminp, j, first_x_frac);
|
||||||
|
}
|
||||||
|
// Bottom left corner
|
||||||
|
if yminp != ymaxp {
|
||||||
|
linear_color +=
|
||||||
|
get_linear_with_frac(image, xminp, ymaxp, first_x_frac * last_y_frac);
|
||||||
|
}
|
||||||
|
// Interior columns
|
||||||
|
for i in xminp + 1..xmaxp {
|
||||||
|
// Top edge
|
||||||
|
linear_color += get_linear_with_frac(image, i, yminp, first_y_frac);
|
||||||
|
// Inner (entire pixel is encompassed by sample)
|
||||||
|
for j in yminp + 1..ymaxp {
|
||||||
|
linear_color += get_linear_with_frac(image, i, j, 1.0);
|
||||||
|
}
|
||||||
|
// Bottom edge
|
||||||
|
if yminp != ymaxp {
|
||||||
|
linear_color += get_linear_with_frac(image, xminp, ymaxp, last_y_frac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Right column
|
||||||
|
if xminp != xmaxp {
|
||||||
|
// Top right corner
|
||||||
|
linear_color +=
|
||||||
|
get_linear_with_frac(image, xmaxp, yminp, first_y_frac * last_x_frac);
|
||||||
|
// Right edge
|
||||||
|
for j in yminp + 1..ymaxp {
|
||||||
|
linear_color += get_linear_with_frac(image, xmaxp, j, last_x_frac);
|
||||||
|
}
|
||||||
|
// Bottom right corner
|
||||||
|
if yminp != ymaxp {
|
||||||
|
linear_color +=
|
||||||
|
get_linear_with_frac(image, xmaxp, ymaxp, last_x_frac * last_y_frac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Divide summed color by area sample covers and convert back to srgb
|
||||||
|
// I wonder if precalulating the inverse of these divs would have a significant effect
|
||||||
|
linear_color = linear_color / wratio / hratio;
|
||||||
|
linear_color =
|
||||||
|
Rgba::from_translucent(linear_color.rgb() / linear_color.a, linear_color.a);
|
||||||
|
new_image.put_pixel(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
image::Rgba(
|
||||||
|
linear_to_srgba(linear_color)
|
||||||
|
.map(|e| (e * 255.0).round() as u8)
|
||||||
|
.into_array(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_image
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_linear(image: &RgbaImage, x: u32, y: u32) -> Rgba<f32> {
|
||||||
|
srgba_to_linear(Rgba::<u8>::from(image.get_pixel(x, y).0).map(|e| e as f32 / 255.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// See comments above resize_pixel_art
|
||||||
|
fn get_linear_with_frac(image: &RgbaImage, x: u32, y: u32, frac: f32) -> Rgba<f32> {
|
||||||
|
let rgba = get_linear(image, x, y);
|
||||||
|
let adjusted_rgb = rgba.rgb() * rgba.a * frac;
|
||||||
|
let adjusted_alpha = -frac * (1.0 - rgba.a);
|
||||||
|
Rgba::from_translucent(adjusted_rgb, adjusted_alpha)
|
||||||
|
}
|
@ -287,9 +287,14 @@ impl Window {
|
|||||||
pub fn new(settings: &Settings) -> Result<Window, Error> {
|
pub fn new(settings: &Settings) -> Result<Window, Error> {
|
||||||
let events_loop = glutin::EventsLoop::new();
|
let events_loop = glutin::EventsLoop::new();
|
||||||
|
|
||||||
|
let size = settings.graphics.window_size;
|
||||||
|
|
||||||
let win_builder = glutin::WindowBuilder::new()
|
let win_builder = glutin::WindowBuilder::new()
|
||||||
.with_title("Veloren")
|
.with_title("Veloren")
|
||||||
.with_dimensions(glutin::dpi::LogicalSize::new(1920.0, 1080.0))
|
.with_dimensions(glutin::dpi::LogicalSize::new(
|
||||||
|
size[0] as f64,
|
||||||
|
size[1] as f64,
|
||||||
|
))
|
||||||
.with_maximized(true);
|
.with_maximized(true);
|
||||||
|
|
||||||
let ctx_builder = glutin::ContextBuilder::new()
|
let ctx_builder = glutin::ContextBuilder::new()
|
||||||
@ -413,7 +418,7 @@ impl Window {
|
|||||||
|
|
||||||
let keypress_map = HashMap::new();
|
let keypress_map = HashMap::new();
|
||||||
|
|
||||||
Ok(Self {
|
let mut this = Self {
|
||||||
events_loop,
|
events_loop,
|
||||||
renderer: Renderer::new(
|
renderer: Renderer::new(
|
||||||
device,
|
device,
|
||||||
@ -436,7 +441,11 @@ impl Window {
|
|||||||
keypress_map,
|
keypress_map,
|
||||||
supplement_events: vec![],
|
supplement_events: vec![],
|
||||||
focused: true,
|
focused: true,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
this.fullscreen(settings.graphics.fullscreen);
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn renderer(&self) -> &Renderer {
|
pub fn renderer(&self) -> &Renderer {
|
||||||
@ -446,7 +455,7 @@ impl Window {
|
|||||||
&mut self.renderer
|
&mut self.renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_events(&mut self) -> Vec<Event> {
|
pub fn fetch_events(&mut self, settings: &mut Settings) -> Vec<Event> {
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
events.append(&mut self.supplement_events);
|
events.append(&mut self.supplement_events);
|
||||||
// Refresh ui size (used when changing playstates)
|
// Refresh ui size (used when changing playstates)
|
||||||
@ -596,7 +605,7 @@ impl Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if toggle_fullscreen {
|
if toggle_fullscreen {
|
||||||
self.fullscreen(!self.is_fullscreen());
|
self.toggle_fullscreen(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
events
|
events
|
||||||
@ -618,6 +627,12 @@ impl Window {
|
|||||||
let _ = self.window.window().grab_cursor(grab);
|
let _ = self.window.window().grab_cursor(grab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_fullscreen(&mut self, settings: &mut Settings) {
|
||||||
|
self.fullscreen(!self.is_fullscreen());
|
||||||
|
settings.graphics.fullscreen = self.is_fullscreen();
|
||||||
|
settings.save_to_file_warn();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_fullscreen(&self) -> bool {
|
pub fn is_fullscreen(&self) -> bool {
|
||||||
self.fullscreen
|
self.fullscreen
|
||||||
}
|
}
|
||||||
@ -646,6 +661,15 @@ impl Window {
|
|||||||
Vec2::new(w, h)
|
Vec2::new(w, h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_size(&mut self, new_size: Vec2<u16>) {
|
||||||
|
self.window
|
||||||
|
.window()
|
||||||
|
.set_inner_size(glutin::dpi::LogicalSize::new(
|
||||||
|
new_size.x as f64,
|
||||||
|
new_size.y as f64,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send_supplement_event(&mut self, event: Event) {
|
pub fn send_supplement_event(&mut self, event: Event) {
|
||||||
self.supplement_events.push(event)
|
self.supplement_events.push(event)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user