use crate::{
prelude::*,
renderer::{Rendering, WindowRenderer},
};
use bitflags::bitflags;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DrawMode {
Corner,
Center,
}
pub type RectMode = DrawMode;
pub type EllipseMode = DrawMode;
pub type ImageMode = DrawMode;
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ArcMode {
Default,
Pie,
}
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BlendMode {
None,
Blend,
Add,
Mod,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AngleMode {
Radians,
Degrees,
}
bitflags! {
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct FontStyle: i32 {
const NORMAL = 0x00;
const BOLD = 0x01;
const ITALIC = 0x02;
const UNDERLINE = 0x04;
const STRIKETHROUGH = 0x08;
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub(crate) struct Settings {
pub(crate) background: Color,
pub(crate) fill: Option<Color>,
pub(crate) stroke: Option<Color>,
pub(crate) stroke_weight: u16,
pub(crate) font_size: u32,
pub(crate) font_style: FontStyle,
#[cfg_attr(feature = "serde", serde(skip))]
pub(crate) font_family: Font,
pub(crate) text_shadow: Option<u16>,
pub(crate) smooth: bool,
pub(crate) bezier_detail: i32,
pub(crate) wrap_width: Option<u32>,
pub(crate) clip: Option<Rect<i32>>,
pub(crate) running: bool,
pub(crate) show_frame_rate: bool,
pub(crate) target_frame_rate: Option<usize>,
pub(crate) target_delta_time: Option<Duration>,
pub(crate) scale_x: f32,
pub(crate) scale_y: f32,
pub(crate) rect_mode: RectMode,
pub(crate) ellipse_mode: EllipseMode,
pub(crate) image_mode: ImageMode,
pub(crate) image_tint: Option<Color>,
pub(crate) arc_mode: ArcMode,
pub(crate) angle_mode: AngleMode,
pub(crate) blend_mode: BlendMode,
pub(crate) cursor: Option<Cursor>,
pub(crate) disabled: bool,
}
impl Default for Settings {
fn default() -> Self {
Self {
background: Color::BLACK,
fill: Some(Color::WHITE),
stroke: None,
stroke_weight: 1,
font_size: 14,
font_style: FontStyle::NORMAL,
font_family: Font::default(),
text_shadow: None,
smooth: true,
bezier_detail: 20,
wrap_width: None,
clip: None,
running: true,
show_frame_rate: false,
target_frame_rate: None,
target_delta_time: None,
scale_x: 1.0,
scale_y: 1.0,
rect_mode: RectMode::Corner,
ellipse_mode: EllipseMode::Center,
image_mode: ImageMode::Corner,
image_tint: None,
arc_mode: ArcMode::Default,
angle_mode: AngleMode::Radians,
blend_mode: BlendMode::None,
cursor: Some(Cursor::default()),
disabled: false,
}
}
}
impl PixState {
#[inline]
pub fn background<C>(&mut self, color: C)
where
C: Into<Color>,
{
self.settings.background = color.into();
let _result = self.clear(); }
#[inline]
pub fn fill<C>(&mut self, color: C)
where
C: Into<Option<Color>>,
{
self.settings.fill = color.into();
}
#[inline]
pub fn stroke<C>(&mut self, color: C)
where
C: Into<Option<Color>>,
{
self.settings.stroke = color.into();
}
#[inline]
pub fn stroke_weight(&mut self, weight: u16) {
self.settings.stroke_weight = weight;
}
#[inline]
pub fn font_size(&mut self, size: u32) -> PixResult<()> {
self.settings.font_size = size;
self.theme.font_size = size;
self.renderer.font_size(size)
}
#[inline]
pub fn font_style(&mut self, style: FontStyle) {
self.settings.font_style = style;
self.renderer.font_style(style);
}
#[inline]
pub fn font_family(&mut self, font: Font) -> PixResult<()> {
self.settings.font_family = font;
self.renderer.font_family(&self.settings.font_family)
}
#[inline]
pub fn text_shadow<D>(&mut self, distance: D)
where
D: Into<Option<u16>>,
{
self.settings.text_shadow = distance.into();
}
#[inline]
pub fn smooth(&mut self, val: bool) {
self.settings.smooth = val;
}
#[inline]
pub fn bezier_detail(&mut self, detail: i32) {
self.settings.bezier_detail = detail;
}
#[inline]
pub fn wrap<W>(&mut self, width: W)
where
W: Into<Option<u32>>,
{
self.settings.wrap_width = width.into();
}
#[inline]
pub fn clip<R>(&mut self, rect: R) -> PixResult<()>
where
R: Into<Option<Rect<i32>>>,
{
self.settings.clip = rect.into();
self.renderer.clip(self.settings.clip)
}
#[inline]
pub fn fullscreen(&mut self, val: bool) -> PixResult<()> {
self.renderer.set_fullscreen(val)
}
#[inline]
pub fn toggle_fullscreen(&mut self) -> PixResult<()> {
let is_fullscreen = self.renderer.fullscreen()?;
self.renderer.set_fullscreen(!is_fullscreen)
}
#[inline]
pub fn vsync(&mut self, val: bool) -> PixResult<WindowId> {
self.renderer.set_vsync(val)
}
#[inline]
pub fn toggle_vsync(&mut self) -> PixResult<WindowId> {
let vsync_enabled = self.renderer.vsync();
self.renderer.set_vsync(vsync_enabled)
}
#[inline]
pub fn cursor<C>(&mut self, cursor: C) -> PixResult<()>
where
C: Into<Option<Cursor>>,
{
self.settings.cursor = cursor.into();
self.renderer.cursor(self.settings.cursor.as_ref())
}
pub fn disable(&mut self, disabled: bool) {
self.settings.disabled = disabled;
self.ui.disabled = disabled;
}
#[inline]
#[must_use]
pub fn running(&mut self) -> bool {
self.settings.running
}
#[inline]
pub fn run(&mut self, val: bool) {
self.settings.running = val;
}
#[inline]
pub fn show_frame_rate(&mut self, show: bool) {
self.settings.show_frame_rate = show;
}
#[inline]
#[must_use]
pub fn target_frame_rate(&mut self) -> Option<usize> {
self.settings.target_frame_rate
}
#[inline]
pub fn frame_rate<R>(&mut self, frame_rate: R)
where
R: Into<Option<usize>>,
{
let frame_rate = frame_rate.into();
self.settings.target_frame_rate = frame_rate;
self.settings.target_delta_time =
frame_rate.map(|frame_rate| Duration::from_secs(1) / frame_rate as u32);
}
#[inline]
pub fn scale(&mut self, x: f32, y: f32) -> PixResult<()> {
let s = &mut self.settings;
s.scale_x = x;
s.scale_y = y;
self.renderer.scale(s.scale_x, s.scale_y)
}
#[inline]
pub fn rect_mode(&mut self, mode: RectMode) {
self.settings.rect_mode = mode;
}
#[inline]
pub fn ellipse_mode(&mut self, mode: EllipseMode) {
self.settings.ellipse_mode = mode;
}
#[inline]
pub fn image_mode(&mut self, mode: ImageMode) {
self.settings.image_mode = mode;
}
#[inline]
pub fn image_tint<C>(&mut self, tint: C)
where
C: Into<Option<Color>>,
{
self.settings.image_tint = tint.into();
}
#[inline]
pub fn arc_mode(&mut self, mode: ArcMode) {
self.settings.arc_mode = mode;
}
#[inline]
pub fn angle_mode(&mut self, mode: AngleMode) {
self.settings.angle_mode = mode;
}
#[inline]
pub fn blend_mode(&mut self, mode: BlendMode) {
self.settings.blend_mode = mode;
self.renderer.blend_mode(mode);
}
#[inline]
pub fn push(&mut self) {
self.setting_stack.push(self.settings.clone());
}
#[inline]
pub fn pop(&mut self) {
if let Some(settings) = self.setting_stack.pop() {
self.settings = settings;
self.ui.disabled = self.settings.disabled;
}
let s = &self.settings;
let _ = self.renderer.clip(s.clip);
let _ = self.renderer.font_size(s.font_size);
self.renderer.font_style(s.font_style);
let _ = self.renderer.font_family(&s.font_family);
self.renderer.blend_mode(s.blend_mode);
}
}
impl PixState {
#[inline]
pub(crate) fn frame_cursor(&mut self, cursor: &Cursor) -> PixResult<()> {
self.renderer.cursor(Some(cursor))
}
#[inline]
pub(crate) fn target_delta_time(&self) -> Option<Duration> {
self.settings.target_delta_time
}
#[inline]
pub(crate) fn vsync_enabled(&self) -> bool {
self.renderer.vsync()
}
}