use crate::core::math::{Matrix, Ray, Vector2};
use crate::core::{RaylibHandle, RaylibThread};
use crate::ffi;
use std::ffi::{CStr, CString, IntoStringError, NulError};
use std::os::raw::c_char;
#[cfg(not(feature = "with_serde"))]
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "with_serde")]
#[cfg(not(feature = "serde"))]
use serde::{Deserialize, Serialize};
#[cfg(feature = "with_serde")]
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MonitorInfo {
pub width: i32,
pub height: i32,
pub physical_width: i32,
pub physical_height: i32,
pub name: String,
pub position: Vector2,
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WindowState(i32);
impl WindowState {
pub fn vsync_hint(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_VSYNC_HINT as i32) != 0
}
pub fn set_vsync_hint(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_VSYNC_HINT as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_VSYNC_HINT as i32);
}
self
}
pub fn fullscreen_mode(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_FULLSCREEN_MODE as i32) != 0
}
pub fn set_fullscreen_mode(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_FULLSCREEN_MODE as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_FULLSCREEN_MODE as i32);
}
self
}
pub fn window_resizable(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_RESIZABLE as i32) != 0
}
pub fn set_window_resizable(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_RESIZABLE as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_RESIZABLE as i32);
}
self
}
pub fn window_undecorated(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_UNDECORATED as i32) != 0
}
pub fn set_window_undecorated(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_UNDECORATED as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_UNDECORATED as i32);
}
self
}
pub fn window_hidden(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_HIDDEN as i32) != 0
}
pub fn set_window_hidden(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_HIDDEN as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_HIDDEN as i32);
}
self
}
pub fn window_minimized(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_MINIMIZED as i32) != 0
}
pub fn set_window_minimized(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_MINIMIZED as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_MINIMIZED as i32);
}
self
}
pub fn window_maximized(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_MAXIMIZED as i32) != 0
}
pub fn set_window_maximized(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_MAXIMIZED as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_MAXIMIZED as i32);
}
self
}
pub fn window_unfocused(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_UNFOCUSED as i32) != 0
}
pub fn set_window_unfocused(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_UNFOCUSED as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_UNFOCUSED as i32);
}
self
}
pub fn window_topmost(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_TOPMOST as i32) != 0
}
pub fn set_window_topmost(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_TOPMOST as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_TOPMOST as i32);
}
self
}
pub fn window_always_run(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_ALWAYS_RUN as i32) != 0
}
pub fn set_window_always_run(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_ALWAYS_RUN as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_ALWAYS_RUN as i32);
}
self
}
pub fn window_transparent(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_TRANSPARENT as i32) != 0
}
pub fn set_window_transparent(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_TRANSPARENT as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_TRANSPARENT as i32);
}
self
}
pub fn window_highdpi(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_WINDOW_HIGHDPI as i32) != 0
}
pub fn set_window_highdpi(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_WINDOW_HIGHDPI as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_WINDOW_HIGHDPI as i32);
}
self
}
pub fn msaa(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_MSAA_4X_HINT as i32) != 0
}
pub fn set_msaa(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_MSAA_4X_HINT as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_MSAA_4X_HINT as i32);
}
self
}
pub fn interlaced_hint(&self) -> bool {
self.0 & (ffi::ConfigFlags::FLAG_INTERLACED_HINT as i32) != 0
}
pub fn set_interlaced_hint(mut self, enabled: bool) -> Self {
if enabled {
self.0 |= ffi::ConfigFlags::FLAG_INTERLACED_HINT as i32;
} else {
self.0 &= !(ffi::ConfigFlags::FLAG_INTERLACED_HINT as i32);
}
self
}
}
#[inline]
pub fn get_monitor_count() -> i32 {
unsafe { ffi::GetMonitorCount() }
}
#[inline]
pub fn get_current_monitor() -> i32 {
unsafe { ffi::GetCurrentMonitor() }
}
#[inline]
pub fn get_current_monitor_index() -> i32 {
unsafe { ffi::GetCurrentMonitor() }
}
#[inline]
pub fn get_monitor_refresh_rate(monitor: i32) -> i32 {
debug_assert!(
monitor < get_monitor_count() && monitor >= 0,
"monitor index out of range"
);
unsafe { ffi::GetMonitorRefreshRate(monitor) }
}
#[inline]
pub fn get_monitor_width(monitor: i32) -> i32 {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe { ffi::GetMonitorWidth(monitor) }
}
#[inline]
pub fn get_monitor_height(monitor: i32) -> i32 {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe { ffi::GetMonitorHeight(monitor) }
}
#[inline]
pub fn get_monitor_physical_width(monitor: i32) -> i32 {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe { ffi::GetMonitorPhysicalWidth(monitor) }
}
#[inline]
pub fn get_monitor_physical_height(monitor: i32) -> i32 {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe { ffi::GetMonitorPhysicalHeight(monitor) }
}
#[inline]
pub fn get_monitor_name(monitor: i32) -> Result<String, IntoStringError> {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
Ok(unsafe {
let c = CString::from_raw(ffi::GetMonitorName(monitor) as *mut c_char);
c.into_string()?
})
}
#[inline]
pub fn get_monitor_position(monitor: i32) -> Vector2 {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe { ffi::GetMonitorPosition(monitor).into() }
}
pub fn get_monitor_info(monitor: i32) -> Result<MonitorInfo, IntoStringError> {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
Ok(MonitorInfo {
width: get_monitor_width(monitor),
height: get_monitor_height(monitor),
physical_height: get_monitor_physical_height(monitor),
physical_width: get_monitor_physical_width(monitor),
name: get_monitor_name(monitor)?,
position: get_monitor_position(monitor),
})
}
pub fn get_camera_matrix(camera: impl Into<ffi::Camera>) -> Matrix {
unsafe { ffi::GetCameraMatrix(camera.into()).into() }
}
#[allow(non_snake_case)]
pub fn get_camera_matrix2D(camera: impl Into<ffi::Camera2D>) -> Matrix {
unsafe { ffi::GetCameraMatrix2D(camera.into()).into() }
}
impl RaylibHandle {
pub fn get_clipboard_text(&self) -> Result<String, std::str::Utf8Error> {
unsafe {
let c = ffi::GetClipboardText();
let c = CStr::from_ptr(c as *mut c_char);
c.to_str().map(|s| s.to_owned())
}
}
pub fn set_clipboard_text(&mut self, text: &str) -> Result<(), NulError> {
let s = CString::new(text)?;
unsafe {
ffi::SetClipboardText(s.as_ptr());
}
Ok(())
}
}
impl RaylibHandle {
pub fn get_screen_to_world_ray(
&self,
mouse_position: impl Into<ffi::Vector2>,
camera: impl Into<ffi::Camera>,
) -> Ray {
unsafe { ffi::GetScreenToWorldRay(mouse_position.into(), camera.into()).into() }
}
pub fn get_screen_to_world_ray_ex(
&self,
mouse_position: impl Into<ffi::Vector2>,
camera: impl Into<ffi::Camera>,
width: i32,
height: i32,
) -> Ray {
unsafe {
ffi::GetScreenToWorldRayEx(mouse_position.into(), camera.into(), width, height).into()
}
}
pub fn get_world_to_screen(
&self,
position: impl Into<ffi::Vector3>,
camera: impl Into<ffi::Camera>,
) -> Vector2 {
unsafe { ffi::GetWorldToScreen(position.into(), camera.into()).into() }
}
#[allow(non_snake_case)]
pub fn get_world_to_screen2D(
&self,
position: impl Into<ffi::Vector2>,
camera: impl Into<ffi::Camera2D>,
) -> Vector2 {
unsafe { ffi::GetWorldToScreen2D(position.into(), camera.into()).into() }
}
pub fn get_world_to_screen_ex(
&self,
position: impl Into<ffi::Vector3>,
camera: impl Into<ffi::Camera>,
width: i32,
height: i32,
) -> Vector2 {
unsafe { ffi::GetWorldToScreenEx(position.into(), camera.into(), width, height).into() }
}
#[allow(non_snake_case)]
pub fn get_screen_to_world2D(
&self,
position: impl Into<ffi::Vector2>,
camera: impl Into<ffi::Camera2D>,
) -> Vector2 {
unsafe { ffi::GetScreenToWorld2D(position.into(), camera.into()).into() }
}
}
impl RaylibHandle {
pub fn set_target_fps(&mut self, fps: u32) {
unsafe {
ffi::SetTargetFPS(fps as i32);
}
}
pub fn get_fps(&self) -> u32 {
unsafe { ffi::GetFPS() as u32 }
}
pub fn get_frame_time(&self) -> f32 {
unsafe { ffi::GetFrameTime() }
}
pub fn get_time(&self) -> f64 {
unsafe { ffi::GetTime() }
}
}
impl RaylibHandle {
#[inline]
pub fn window_should_close(&self) -> bool {
unsafe { ffi::WindowShouldClose() }
}
#[inline]
pub fn is_window_ready(&self) -> bool {
unsafe { ffi::IsWindowReady() }
}
#[inline]
pub fn maximize_window(&mut self) {
unsafe { ffi::MaximizeWindow() }
}
#[inline]
pub fn minimize_window(&mut self) {
unsafe { ffi::MinimizeWindow() }
}
#[inline]
pub fn restore_window(&mut self) {
unsafe { ffi::RestoreWindow() }
}
#[inline]
pub fn is_window_maximized(&self) -> bool {
unsafe { ffi::IsWindowMaximized() }
}
#[inline]
pub fn is_window_minimized(&self) -> bool {
unsafe { ffi::IsWindowMinimized() }
}
#[inline]
pub fn is_window_resized(&self) -> bool {
unsafe { ffi::IsWindowResized() }
}
#[inline]
pub fn is_window_hidden(&self) -> bool {
unsafe { ffi::IsWindowHidden() }
}
#[inline]
pub fn is_window_fullscreen(&self) -> bool {
unsafe { ffi::IsWindowFullscreen() }
}
#[inline]
pub fn is_window_focused(&self) -> bool {
unsafe { ffi::IsWindowFocused() }
}
#[inline]
pub fn get_window_scale_dpi(&self) -> Vector2 {
unsafe { ffi::GetWindowScaleDPI().into() }
}
#[inline]
pub fn is_cursor_on_screen(&self) -> bool {
unsafe { ffi::IsCursorOnScreen() }
}
#[inline]
pub fn set_mouse_cursor(&self, cursor: crate::consts::MouseCursor) {
unsafe { ffi::SetMouseCursor(cursor as i32) }
}
#[inline]
pub fn toggle_fullscreen(&mut self) {
unsafe {
ffi::ToggleFullscreen();
}
}
pub fn set_window_state(&mut self, state: WindowState) {
unsafe { ffi::SetWindowState(state.0 as u32) }
}
pub fn clear_window_state(&mut self, state: WindowState) {
unsafe { ffi::ClearWindowState(state.0 as u32) }
}
pub fn get_window_state(&self) -> WindowState {
let state = WindowState::default();
unsafe {
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_VSYNC_HINT as u32) {
state.set_vsync_hint(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_FULLSCREEN_MODE as u32) {
state.set_fullscreen_mode(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_RESIZABLE as u32) {
state.set_window_resizable(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_UNDECORATED as u32) {
state.set_window_undecorated(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_HIDDEN as u32) {
state.set_window_hidden(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_MINIMIZED as u32) {
state.set_window_minimized(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_MAXIMIZED as u32) {
state.set_window_maximized(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_UNFOCUSED as u32) {
state.set_window_unfocused(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_TOPMOST as u32) {
state.set_window_topmost(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_ALWAYS_RUN as u32) {
state.set_window_always_run(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_TRANSPARENT as u32) {
state.set_window_transparent(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_WINDOW_HIGHDPI as u32) {
state.set_window_highdpi(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_MSAA_4X_HINT as u32) {
state.set_msaa(true);
}
if ffi::IsWindowState(ffi::ConfigFlags::FLAG_INTERLACED_HINT as u32) {
state.set_interlaced_hint(true);
}
}
state
}
#[inline]
pub fn set_window_icon(&mut self, image: impl AsRef<ffi::Image>) {
unsafe {
ffi::SetWindowIcon(*image.as_ref());
}
}
#[inline]
pub fn set_window_icons(&mut self, images: &mut [raylib_sys::Image]) {
use std::convert::TryInto;
unsafe { ffi::SetWindowIcons(images.as_mut_ptr(), images.len().try_into().unwrap()) }
}
#[inline]
pub fn set_window_title(&self, _: &RaylibThread, title: &str) {
let c_title = CString::new(title).unwrap();
unsafe {
ffi::SetWindowTitle(c_title.as_ptr());
}
}
#[inline]
pub fn set_window_position(&mut self, x: i32, y: i32) {
unsafe {
ffi::SetWindowPosition(x, y);
}
}
#[inline]
pub fn set_window_monitor(&mut self, monitor: i32) {
let len = get_monitor_count();
debug_assert!(monitor < len && monitor >= 0, "monitor index out of range");
unsafe {
ffi::SetWindowMonitor(monitor);
}
}
#[inline]
pub fn set_window_min_size(&mut self, width: i32, height: i32) {
unsafe {
ffi::SetWindowMinSize(width, height);
}
}
#[inline]
pub fn set_window_max_size(&mut self, width: i32, height: i32) {
unsafe {
ffi::SetWindowMaxSize(width, height);
}
}
#[inline]
pub fn set_window_size(&mut self, width: i32, height: i32) {
unsafe {
ffi::SetWindowSize(width, height);
}
}
#[inline]
pub fn set_window_opacity(&mut self, opacity: f32) {
unsafe { ffi::SetWindowOpacity(opacity) }
}
#[inline]
pub fn get_render_width(&self) -> i32 {
unsafe { ffi::GetRenderWidth() }
}
#[inline]
pub fn get_render_height(&self) -> i32 {
unsafe { ffi::GetRenderHeight() }
}
#[inline]
pub fn get_screen_width(&self) -> i32 {
unsafe { ffi::GetScreenWidth() }
}
#[inline]
pub fn get_screen_height(&self) -> i32 {
unsafe { ffi::GetScreenHeight() }
}
#[inline]
pub fn get_window_position(&self) -> Vector2 {
unsafe { ffi::GetWindowPosition().into() }
}
pub fn toggle_borderless_windowed(&self) {
unsafe { ffi::ToggleBorderlessWindowed() }
}
pub fn set_window_focused(&self) {
unsafe { ffi::SetWindowFocused() }
}
}
impl RaylibHandle {
#[inline]
pub fn show_cursor(&mut self) {
unsafe {
ffi::ShowCursor();
}
}
#[inline]
pub fn hide_cursor(&mut self) {
unsafe {
ffi::HideCursor();
}
}
#[inline]
pub fn is_cursor_hidden(&self) -> bool {
unsafe { ffi::IsCursorHidden() }
}
#[inline]
pub fn enable_cursor(&mut self) {
unsafe {
ffi::EnableCursor();
}
}
#[inline]
pub fn disable_cursor(&mut self) {
unsafe {
ffi::DisableCursor();
}
}
#[inline]
pub unsafe fn get_window_handle(&mut self) -> *mut ::std::os::raw::c_void {
ffi::GetWindowHandle()
}
}
impl RaylibHandle {
#[cfg(feature = "custom_frame_control")]
pub fn swap_screen_buffer(&self) {
unsafe { ffi::SwapScreenBuffer() }
}
#[cfg(feature = "custom_frame_control")]
pub fn poll_input_events(&self) {
unsafe { ffi::PollInputEvents() }
}
#[cfg(feature = "custom_frame_control")]
pub fn wait_time(&self, seconds: f64) {
unsafe { ffi::WaitTime(seconds) }
}
}