elikar 0.1.9

A rust asynchronous ECS game engine
use crate::common::{Result, SdlError};
use crate::window::window::Window;
use parking_lot::RwLock;
use sdl2_sys::*;
use xecs::{ EntityId, World};
use std::ffi::CString;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;

pub struct Builder {
    title: String,
    x: i32,
    y: i32,
    w: i32,
    h: i32,
    flags: u32,
    world : Arc<RwLock<World>>
}

impl Debug for Builder {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Builder")
            .field("title", &self.title)
            .field("x", &self.x)
            .field("y", &self.y)
            .field("w", &self.w)
            .field("h", &self.h)
            .field("flags", &self.flags)
            .finish()
    }
}

impl Builder {
    pub fn from_world(world : Arc<RwLock<World>>) -> Builder {
        Builder {
            title: "elikar".to_string(),
            x: SDL_WINDOWPOS_UNDEFINED_MASK as i32,
            y: SDL_WINDOWPOS_UNDEFINED_MASK as i32,
            w: 1280,
            h: 768,
            flags: SDL_WindowFlags::SDL_WINDOW_SHOWN as u32,
            world,
        }
    }

    pub fn title(mut self, text: &str) -> Self {
        self.title = text.to_owned();
        self
    }

    pub fn position(mut self, x: i32, y: i32) -> Self {
        self.x = x;
        self.y = y;
        self
    }

    pub fn position_default(mut self) -> Self {
        self.x = SDL_WINDOWPOS_UNDEFINED_MASK as i32;
        self.y = SDL_WINDOWPOS_UNDEFINED_MASK as i32;
        self
    }

    pub fn position_centred(mut self) -> Self {
        self.x = SDL_WINDOWPOS_CENTERED_MASK as i32;
        self.y = SDL_WINDOWPOS_CENTERED_MASK as i32;
        self
    }

    pub fn size(mut self, w: u32, h: u32) -> Self {
        self.w = w as i32;
        self.h = h as i32;
        self
    }

    pub fn fullscreen(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_FULLSCREEN as u32;
        self
    }

    pub fn fullscreen_desktop(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_FULLSCREEN_DESKTOP as u32;
        self
    }

    pub fn opengl(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_OPENGL as u32;
        self
    }
    pub fn vulkan(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_VULKAN as u32;
        self
    }
    pub fn hidden(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_HIDDEN as u32;
        self
    }
    pub fn borderless(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_BORDERLESS as u32;
        self
    }
    pub fn resizable(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_RESIZABLE as u32;
        self
    }
    pub fn minimized(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_MINIMIZED as u32;
        self
    }
    pub fn maximized(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_MAXIMIZED as u32;
        self
    }
    pub fn input_grabbed(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_INPUT_GRABBED as u32;
        self
    }
    pub fn input_focus(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_INPUT_FOCUS as u32;
        self
    }
    pub fn mouse_focus(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_MOUSE_FOCUS as u32;
        self
    }
    pub fn allow_high_dpi(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_ALLOW_HIGHDPI as u32;
        self
    }
    pub fn mouse_capture(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_MOUSE_CAPTURE as u32;
        self
    }
    pub fn always_on_top(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_ALWAYS_ON_TOP as u32;
        self
    }
    pub fn skip_taskbar(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_SKIP_TASKBAR as u32;
        self
    }
    pub fn utility(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_UTILITY as u32;
        self
    }
    pub fn tooltip(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_TOOLTIP as u32;
        self
    }
    pub fn popup_menu(mut self) -> Self {
        self.flags |= SDL_WindowFlags::SDL_WINDOW_POPUP_MENU as u32;
        self
    }

    pub fn build(self) -> Result<EntityId> {
        let title_str = CString::new(self.title.clone()).unwrap();
        let window_ptr: *mut SDL_Window = unsafe {
            SDL_CreateWindow(
                title_str.as_ptr(),
                self.x,
                self.y,
                self.w,
                self.h,
                self.flags,
            )
        };
        if window_ptr.is_null() {
            return Err(SdlError::get());
        } else {
            let window = unsafe { Window::from_ptr(window_ptr) };
            let world = self.world.read();
            let id = world.create_entity()
                .attach(window)
                .into_id();
            Ok(id)
        }
    }
}