use std::ffi::CString;
use std::os::raw::c_int;
use xplm_sys::{
xplmFont_Basic, xplm_Tex_GeneralInterface, XPLMBindTexture2d, XPLMDrawNumber, XPLMDrawString,
XPLMDrawTranslucentDarkBox, XPLMFontID, XPLMGenerateTextureNumbers, XPLMGetFontDimensions,
XPLMGetTexture, XPLMLocalToWorld, XPLMSetGraphicsState, XPLMTextureID, XPLMWorldToLocal,
};
#[cfg(feature = "XPLM200")]
use xplm_sys::{xplmFont_Proportional, XPLMMeasureString};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GraphicsState {
pub fog: bool,
pub texture_units: i32,
pub lighting: bool,
pub alpha_testing: bool,
pub alpha_blending: bool,
pub depth_testing: bool,
pub depth_writing: bool,
}
impl Default for GraphicsState {
fn default() -> Self {
Self {
fog: false,
texture_units: 1,
lighting: false,
alpha_testing: false,
alpha_blending: false,
depth_testing: false,
depth_writing: false,
}
}
}
impl GraphicsState {
pub fn apply(&self) {
unsafe {
XPLMSetGraphicsState(
self.fog as c_int,
self.texture_units,
self.lighting as c_int,
self.alpha_testing as c_int,
self.alpha_blending as c_int,
self.depth_testing as c_int,
self.depth_writing as c_int,
)
}
}
}
pub fn bind_texture_2d(texture_num: i32, texture_unit: i32) {
unsafe { XPLMBindTexture2d(texture_num, texture_unit) }
}
pub fn generate_texture_numbers(count: usize) -> Vec<i32> {
let mut ids = vec![0; count];
unsafe { XPLMGenerateTextureNumbers(ids.as_mut_ptr(), count as c_int) };
ids
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Texture {
GeneralInterface,
#[cfg(feature = "XPLM420")]
RadarPilot,
#[cfg(feature = "XPLM420")]
RadarCopilot,
#[cfg(feature = "deprecated")]
#[deprecated(note = "use the Widgets library instead, per XPLMGraphics.h")]
AircraftPaint,
#[cfg(feature = "deprecated")]
#[deprecated(note = "use the Widgets library instead, per XPLMGraphics.h")]
AircraftLiteMap,
}
impl From<Texture> for XPLMTextureID {
#[allow(deprecated)]
fn from(t: Texture) -> Self {
match t {
Texture::GeneralInterface => xplm_Tex_GeneralInterface,
#[cfg(feature = "XPLM420")]
Texture::RadarPilot => xplm_sys::xplm_Tex_Radar_Pilot,
#[cfg(feature = "XPLM420")]
Texture::RadarCopilot => xplm_sys::xplm_Tex_Radar_Copilot,
#[cfg(feature = "deprecated")]
Texture::AircraftPaint => xplm_sys::xplm_Tex_AircraftPaint,
#[cfg(feature = "deprecated")]
Texture::AircraftLiteMap => xplm_sys::xplm_Tex_AircraftLiteMap,
}
}
}
pub fn get_texture(texture: Texture) -> i32 {
unsafe { XPLMGetTexture(texture.into()) }
}
pub fn world_to_local(latitude: f64, longitude: f64, altitude: f64) -> (f64, f64, f64) {
let (mut x, mut y, mut z) = (0.0, 0.0, 0.0);
unsafe { XPLMWorldToLocal(latitude, longitude, altitude, &mut x, &mut y, &mut z) };
(x, y, z)
}
pub fn local_to_world(x: f64, y: f64, z: f64) -> (f64, f64, f64) {
let (mut latitude, mut longitude, mut altitude) = (0.0, 0.0, 0.0);
unsafe { XPLMLocalToWorld(x, y, z, &mut latitude, &mut longitude, &mut altitude) };
(latitude, longitude, altitude)
}
pub fn draw_translucent_dark_box(left: i32, top: i32, right: i32, bottom: i32) {
unsafe { XPLMDrawTranslucentDarkBox(left, top, right, bottom) }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Font {
Basic,
#[cfg(feature = "XPLM200")]
Proportional,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
Menus,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
Metal,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
Led,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
LedWide,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
PanelHud,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
PanelEfis,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
PanelGps,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosGa,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosBc,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosHm,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosGaNarrow,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosBcNarrow,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
RadiosHmNarrow,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
Timer,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
FullRound,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
SmallRound,
#[cfg(feature = "deprecated")]
#[deprecated(note = "per XPLMGraphics.h: deprecated, do not use")]
MenusLocalized,
}
impl From<Font> for XPLMFontID {
#[allow(deprecated)]
fn from(f: Font) -> Self {
match f {
Font::Basic => xplmFont_Basic,
#[cfg(feature = "XPLM200")]
Font::Proportional => xplmFont_Proportional,
#[cfg(feature = "deprecated")]
Font::Menus => xplm_sys::xplmFont_Menus,
#[cfg(feature = "deprecated")]
Font::Metal => xplm_sys::xplmFont_Metal,
#[cfg(feature = "deprecated")]
Font::Led => xplm_sys::xplmFont_Led,
#[cfg(feature = "deprecated")]
Font::LedWide => xplm_sys::xplmFont_LedWide,
#[cfg(feature = "deprecated")]
Font::PanelHud => xplm_sys::xplmFont_PanelHUD,
#[cfg(feature = "deprecated")]
Font::PanelEfis => xplm_sys::xplmFont_PanelEFIS,
#[cfg(feature = "deprecated")]
Font::PanelGps => xplm_sys::xplmFont_PanelGPS,
#[cfg(feature = "deprecated")]
Font::RadiosGa => xplm_sys::xplmFont_RadiosGA,
#[cfg(feature = "deprecated")]
Font::RadiosBc => xplm_sys::xplmFont_RadiosBC,
#[cfg(feature = "deprecated")]
Font::RadiosHm => xplm_sys::xplmFont_RadiosHM,
#[cfg(feature = "deprecated")]
Font::RadiosGaNarrow => xplm_sys::xplmFont_RadiosGANarrow,
#[cfg(feature = "deprecated")]
Font::RadiosBcNarrow => xplm_sys::xplmFont_RadiosBCNarrow,
#[cfg(feature = "deprecated")]
Font::RadiosHmNarrow => xplm_sys::xplmFont_RadiosHMNarrow,
#[cfg(feature = "deprecated")]
Font::Timer => xplm_sys::xplmFont_Timer,
#[cfg(feature = "deprecated")]
Font::FullRound => xplm_sys::xplmFont_FullRound,
#[cfg(feature = "deprecated")]
Font::SmallRound => xplm_sys::xplmFont_SmallRound,
#[cfg(feature = "deprecated")]
Font::MenusLocalized => xplm_sys::xplmFont_Menus_Localized,
}
}
}
pub fn draw_string(
color: [f32; 3],
x: i32,
y: i32,
text: &str,
word_wrap_width: Option<i32>,
font: Font,
) {
let Ok(c_text) = CString::new(text) else {
return;
};
let mut color = color;
let mut word_wrap_width = word_wrap_width;
unsafe {
XPLMDrawString(
color.as_mut_ptr(),
x,
y,
c_text.as_ptr() as *mut _,
word_wrap_width
.as_mut()
.map_or(std::ptr::null_mut(), |w| w as *mut i32),
font.into(),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn draw_number(
color: [f32; 3],
x: i32,
y: i32,
value: f64,
integer_digits: i32,
decimal_digits: i32,
show_sign: bool,
font: Font,
) {
let mut color = color;
unsafe {
XPLMDrawNumber(
color.as_mut_ptr(),
x,
y,
value,
integer_digits,
decimal_digits,
show_sign as c_int,
font.into(),
)
}
}
pub fn font_dimensions(font: Font) -> (i32, i32, bool) {
let (mut width, mut height, mut digits_only) = (0, 0, 0);
unsafe { XPLMGetFontDimensions(font.into(), &mut width, &mut height, &mut digits_only) };
(width, height, digits_only != 0)
}
#[cfg(feature = "XPLM200")]
pub fn measure_string(font: Font, text: &str) -> f32 {
unsafe { XPLMMeasureString(font.into(), text.as_ptr() as *const _, text.len() as c_int) }
}