sfml 0.24.0

Rust binding for sfml
Documentation
use {
    glu_sys as gl,
    sfml::{
        graphics::{
            Color, Font, IntRect, RenderTarget, RenderWindow, Sprite, Text, Texture, Transformable,
        },
        system::Clock,
        window::{ContextSettings, Event, Key, Style},
        SfResult,
    },
    std::{ffi::c_void, mem::size_of},
};

include!("../example_common.rs");

fn main() -> SfResult<()> {
    example_ensure_right_working_dir();

    let mut exit = false;
    let mut srgb = false;

    while !exit {
        let ctx_sett = ContextSettings {
            depth_bits: 24,
            srgb_capable: srgb,
            ..Default::default()
        };

        let mut window = RenderWindow::new(
            (800, 600),
            "SFML graphics with OpenGL",
            Style::default(),
            &ctx_sett,
        )?;
        window.set_vertical_sync_enabled(true);

        let mut bg_tex = Texture::new()?;
        bg_tex.set_srgb(srgb);
        bg_tex.load_from_file("opengl-background.jpg", IntRect::default())?;
        let bg_sprite = Sprite::with_texture(&bg_tex);

        let font = Font::from_file("sansation.ttf")?;
        let mut text = Text::new("SFML / OpenGL demo", &font, 32);
        let mut srgb_instr = Text::new("Press space to toggle sRGB conversion", &font, 32);
        let mut mipmap_instr = Text::new("Press return to toggle mipmapping", &font, 32);
        text.set_fill_color(Color::rgba(255, 255, 255, 170));
        srgb_instr.set_fill_color(Color::rgba(255, 255, 255, 170));
        mipmap_instr.set_fill_color(Color::rgba(255, 255, 255, 170));
        text.set_position((250., 450.));
        srgb_instr.set_position((150., 500.));
        mipmap_instr.set_position((180., 550.));

        let mut texture = Texture::from_file("texture.jpg")?;
        texture.generate_mipmap()?;
        window.set_active(true)?;
        unsafe {
            gl::glEnable(gl::GL_DEPTH_TEST);
            gl::glDepthMask(gl::GL_TRUE as _);
            gl::glClearDepth(1.);
            gl::glDisable(gl::GL_LIGHTING);
            gl::glViewport(0, 0, window.size().x as _, window.size().y as _);
            gl::glMatrixMode(gl::GL_PROJECTION);
            gl::glLoadIdentity();
            let ratio = (window.size().x / window.size().y) as gl::GLdouble;
            gl::glFrustum(-ratio, ratio, -1., 1., 1., 500.);
            gl::glEnable(gl::GL_TEXTURE_2D);
            Texture::bind(&texture);
        }

        let cube: [f32; 180] = [
            -20., -20., -20., 0., 0., -20., 20., -20., 1., 0., -20., -20., 20., 0., 1., -20., -20.,
            20., 0., 1., -20., 20., -20., 1., 0., -20., 20., 20., 1., 1., 20., -20., -20., 0., 0.,
            20., 20., -20., 1., 0., 20., -20., 20., 0., 1., 20., -20., 20., 0., 1., 20., 20., -20.,
            1., 0., 20., 20., 20., 1., 1., -20., -20., -20., 0., 0., 20., -20., -20., 1., 0., -20.,
            -20., 20., 0., 1., -20., -20., 20., 0., 1., 20., -20., -20., 1., 0., 20., -20., 20.,
            1., 1., -20., 20., -20., 0., 0., 20., 20., -20., 1., 0., -20., 20., 20., 0., 1., -20.,
            20., 20., 0., 1., 20., 20., -20., 1., 0., 20., 20., 20., 1., 1., -20., -20., -20., 0.,
            0., 20., -20., -20., 1., 0., -20., 20., -20., 0., 1., -20., 20., -20., 0., 1., 20.,
            -20., -20., 1., 0., 20., 20., -20., 1., 1., -20., -20., 20., 0., 0., 20., -20., 20.,
            1., 0., -20., 20., 20., 0., 1., -20., 20., 20., 0., 1., 20., -20., 20., 1., 0., 20.,
            20., 20., 1., 1.,
        ];

        unsafe {
            gl::glEnableClientState(gl::GL_VERTEX_ARRAY);
            gl::glEnableClientState(gl::GL_TEXTURE_COORD_ARRAY);
            gl::glVertexPointer(
                3,
                gl::GL_FLOAT,
                5 * size_of::<gl::GLfloat>() as i32,
                cube.as_ptr() as *const c_void,
            );
            gl::glTexCoordPointer(
                2,
                gl::GL_FLOAT,
                5 * size_of::<gl::GLfloat>() as i32,
                cube.as_ptr().offset(3) as *const c_void,
            );

            // Disable normal and color vertex components
            gl::glDisableClientState(gl::GL_NORMAL_ARRAY);
            gl::glDisableClientState(gl::GL_COLOR_ARRAY);
        }

        window.set_active(false)?;
        let clock = Clock::start()?;
        let mut mipmap_enabled = true;

        while window.is_open() {
            while let Some(event) = window.poll_event() {
                match event {
                    Event::Closed
                    | Event::KeyPressed {
                        code: Key::Escape, ..
                    } => {
                        exit = true;
                        window.close();
                    }
                    Event::KeyPressed {
                        code: Key::Enter, ..
                    } => {
                        if mipmap_enabled {
                            texture = Texture::from_file("texture.jpg")?;
                            mipmap_enabled = false;
                            window.set_active(true)?;
                            Texture::bind(&texture);
                            window.set_active(false)?;
                        } else {
                            texture.generate_mipmap()?;
                            mipmap_enabled = true;
                        }
                    }
                    Event::KeyPressed {
                        code: Key::Space, ..
                    } => {
                        srgb = !srgb;
                        window.close();
                    }
                    Event::Resized { width, height } => {
                        window.set_active(true)?;
                        unsafe {
                            gl::glViewport(0, 0, width as _, height as _);
                        }
                        window.set_active(false)?;
                    }
                    _ => {}
                }
            }
            window.push_gl_states();
            window.draw(&bg_sprite);
            window.pop_gl_states();

            if let Err(e) = window.set_active(true) {
                eprintln!("Failed to set window as active: {e}");
            }

            unsafe {
                gl::glClear(gl::GL_DEPTH_BUFFER_BIT);
                let x: f32 =
                    window.mouse_position().x as f32 * 200. / window.size().x as f32 - 100.;
                let y: f32 =
                    -window.mouse_position().y as f32 * 200. / window.size().y as f32 + 100.;

                gl::glMatrixMode(gl::GL_MODELVIEW);
                gl::glLoadIdentity();
                gl::glTranslatef(x, y, -100.);
                gl::glRotatef(clock.elapsed_time().as_seconds() * 50., 1., 0., 0.);
                gl::glRotatef(clock.elapsed_time().as_seconds() * 30., 0., 1., 0.);
                gl::glRotatef(clock.elapsed_time().as_seconds() * 90., 0., 0., 1.);
                gl::glDrawArrays(gl::GL_TRIANGLES, 0, 36);
            }
            if let Err(e) = window.set_active(false) {
                eprintln!("Failed to set window as active: {e}");
            }
            window.push_gl_states();
            window.draw(&text);
            window.draw(&srgb_instr);
            window.draw(&mipmap_instr);
            window.pop_gl_states();
            window.display();
        }
    }
    Ok(())
}