<commit_before>
//! Various utilities for rendering and resource management

pub mod graphics {
    //! Wrappers for unsafe OpenGL calls

    use gl;
    use gl::types::*;
    use color::Color;

    /// Sets the opengl viewport
    pub fn viewport(x: u32, y: u32, width: u32, height: u32) {
        unsafe {
            gl::Viewport(x as GLint, y as GLint, width as GLsizei, height as GLsizei);
        }
    }

    /// Prints all OpenGL errors
    pub fn print_errors() {
        unsafe {
            while let Some(error) = get_error_message(gl::GetError()) {
                println!("OpenGL error: {}", error);
            }
        }
    }

    /// Retrieves the strign asscociated with the given OpenGL error. Returns None
    /// if there if no error occured.
    pub fn get_error_message(error: GLenum) -> Option<String> {
        let value = match error {
            gl::INVALID_VALUE                   => "Invalid value",
            gl::INVALID_ENUM                    => "Invalid enum",
            gl::INVALID_OPERATION               => "Invalid operation",
            gl::INVALID_FRAMEBUFFER_OPERATION   => "Invalid framebuffer operation",
            gl::OUT_OF_MEMORY                   => "Out of memory",

            gl::NO_ERROR                        => return None,
            _                                   => return Some(format!("Invalid error code: {:x}", error)),
        };
        Some(String::from(value))
    }
    
    /// Clears the currently bound framebuffer to the given color. If no color is specified
    /// only the backbuffer is cleared
    pub fn clear(color: Option<Color>, depth: bool, stencil: bool) {
        unsafe {
            if let Some(color) = color {
                gl::ClearColor(color.r, color.g, color.b, color.a);
            }
            let mut mask = 0;
            if color.is_some() { mask |= gl::COLOR_BUFFER_BIT }
            if depth           { mask |= gl::DEPTH_BUFFER_BIT }
            if stencil         { mask |= gl::STENCIL_BUFFER_BIT }
            gl::Clear(mask);
        }
    }<commit_msg>Added culling utilities<commit_after>
//! Various utilities for rendering and resource management

pub mod graphics {
    //! Wrappers for unsafe OpenGL calls

    use gl;
    use gl::types::*;
    use color::Color;

    /// Sets the opengl viewport
    pub fn viewport(x: u32, y: u32, width: u32, height: u32) {
        unsafe {
            gl::Viewport(x as GLint, y as GLint, width as GLsizei, height as GLsizei);
        }
    }

    /// Prints all OpenGL errors
    pub fn print_errors() {
        unsafe {
            while let Some(error) = get_error_message(gl::GetError()) {
                println!("OpenGL error: {}", error);
            }
        }
    }

    /// Retrieves the strign asscociated with the given OpenGL error. Returns None
    /// if there if no error occured.
    pub fn get_error_message(error: GLenum) -> Option<String> {
        let value = match error {
            gl::INVALID_VALUE                   => "Invalid value",
            gl::INVALID_ENUM                    => "Invalid enum",
            gl::INVALID_OPERATION               => "Invalid operation",
            gl::INVALID_FRAMEBUFFER_OPERATION   => "Invalid framebuffer operation",
            gl::OUT_OF_MEMORY                   => "Out of memory",

            gl::NO_ERROR                        => return None,
            _                                   => return Some(format!("Invalid error code: {:x}", error)),
        };
        Some(String::from(value))
    }

    /// Sets which side of a face to treat as the front face and which side of a face to cull. If
    /// `None` is passed this disables culling.
    ///
    /// For simplicity, you can simply call `graphics::set_culling(Some(Default::default()))`,
    /// which will set the winding order to counter-clockwise and cull-face to the back face.
    pub fn set_culling(mode: Option<(WindingOrder, FaceSide)>) {
        unsafe { match mode {
            Some((winding_order, face_side)) => {
                gl::Enable(gl::CULL_FACE);
                match winding_order {
                    WindingOrder::Clockwise => gl::FrontFace(gl::CW),
                    WindingOrder::CounterClockwise => gl::FrontFace(gl::CCW),
                }
                match face_side {
                    FaceSide::Front => gl::CullFace(gl::FRONT),
                    FaceSide::Back => gl::CullFace(gl::BACK),
                }
            },
            None => {
                gl::Disable(gl::CULL_FACE);
            },
        } }
    }

    #[derive(Debug, Copy, Clone)]
    pub enum WindingOrder {
        Clockwise, CounterClockwise,
    } 
    #[derive(Debug, Copy, Clone)]
    pub enum FaceSide {
        Front, Back
    }

    impl Default for WindingOrder { 
        /// The default winding order is counter-clockwise.
        fn default() -> WindingOrder { WindingOrder::CounterClockwise } 
    }
    impl Default for FaceSide { 
        /// The default face side is back, as this is the face you want to cull by default.
        fn default() -> FaceSide { FaceSide::Back } 
    }
    
    /// Clears the currently bound framebuffer to the given color. If no color is specified
    /// only the backbuffer is cleared
    pub fn clear(color: Option<Color>, depth: bool, stencil: bool) {
        unsafe {
            if let Some(color) = color {
                gl::ClearColor(color.r, color.g, color.b, color.a);
            }
            let mut mask = 0;
            if color.is_some() { mask |= gl::COLOR_BUFFER_BIT }
            if depth           { mask |= gl::DEPTH_BUFFER_BIT }
            if stencil         { mask |= gl::STENCIL_BUFFER_BIT }
            gl::Clear(mask);
        }
    }
{'fraction_non_alphanumeric': 0.10808926080892609, 'fraction_numerical': 0.0031380753138075313, 'mean_word_length': 1.6745920745920746, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4278953', 'n_tokens_mistral': 1605, 'n_tokens_neox': 1546, 'n_words': 470}