<commit_before>extern crate camera_controllers;
extern crate collada;
extern crate dev_menu;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate gfx_gl as gl;
extern crate piston;
extern crate piston_window;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;


use gfx_debug_draw::DebugRenderer;

use piston::window::{
    WindowSettings,
};

use piston::event::*;

use vecmath::{Matrix4, mat4_id};

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::*;
use collada::document::ColladaDocument;

pub struct Settings {
    pub draw_skeleton: bool,
    pub draw_labels: bool,
    pub draw_mesh: bool,
    pub playback_speed: f32,

    pub params: HashMap<String, f32>,
}

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);
    let window = Rc::new(RefCell::new(Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Skeletal Animation Demo".to_string(),
            piston::window::Size { width: 640, height: 480 }
        ).exit_on_esc(true)
    )));

    let piston_window = piston_window::PistonWindow::new(window, piston_window::empty_app());

    let mut debug_renderer = DebugRenderer::from_canvas(
        &mut piston_window.canvas.borrow_mut(),
        [win_width as u32, win_height as u32],
        64,
        None,
        None,
    ).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();

    // TODO better.. we keep reloading the same document over and over for different things...
    let skeleton = {
        let skeleton_set = collada_document.get_skeletons().unwrap();
        Skeleton::from_collada(&skeleton_set[0])
    };

    let skeleton = Rc::new(skeleton);

    let mut asset_manager = AssetManager::new();
    asset_manager.load_animations("assets/clips.json");

    let controller_def = AssetManager::load_def_from_path("assets/human_controller.json").unwrap();
    let mut controller = AnimationController::new(controller_def, skeleton.clone(), &asset_manager.animation_clips);

    let mut skinned_renderer = SkinnedRenderer::from_collada(&mut piston_window.canvas.borrow_mut().factory, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    let mut settings = Settings {

        draw_skeleton: true,
        draw_labels: false,
        draw_mesh: true,
        playback_speed: 1.0,

        params: HashMap::new(),
    };

    let mut menu = dev_menu::Menu::<Settings>::new();

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Skeleton",
        Box::new( |ref mut settings| { settings.draw_skeleton = !settings.draw_skeleton; })
    ));

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Joint Labels",
        Box::new( |ref mut settings| { settings.draw_labels = !settings.draw_labels; })
    ));

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Mesh",
        Box::new( |ref mut settings| { settings.draw_mesh = !settings.draw_mesh; })
    ));

    menu.add_item(dev_menu::MenuItem::slider_item(
        "Playback Speed = ",
        [-5.0, 5.0],
        0.01,
        Box::new( |ref settings| { settings.playback_speed }),
        Box::new( |ref mut settings, value| { settings.playback_speed = value }),
    ));

    for (param, &value) in controller.get_parameters().iter() {
        settings.params.insert(param.clone(), value);

        // Apparently need to make our own string copies to move into each closure..
        let param_copy_1 = param.clone();
        let param_copy_2 = param.clone();

        menu.add_item(dev_menu::MenuItem::slider_item(
            &format!("Param[{}] = ", param)[..],
            [0.0, 1.0],
            0.01,
            Box::new( move |ref settings| {
                settings.params[&param_copy_1[..]]
            }),
            Box::new( move |ref mut settings, value| {
                settings.params.insert(param_copy_2.clone(), value);
            }),
        ));
    }

    for e in piston_window {

        orbit_zoom_camera.event(&e);
        menu.event(&e, &mut settings);

        e.resize(|width, height| {
            debug_renderer.resize(width, height);

            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        e.update(|args| {

            controller.set_playback_speed(settings.playback_speed as f64);

            for (param, &value) in settings.params.iter() {
                controller.set_param_value(param, value);
            }

            controller.update(args.dt);
        });

        e.draw_3d(|canvas| {

            let args = e.render_args().unwrap();<commit_msg>Assure it works with latest gfx-debug-draw<commit_after>extern crate camera_controllers;
extern crate collada;
extern crate dev_menu;
extern crate env_logger;
extern crate gfx;
extern crate gfx_debug_draw;
extern crate gfx_device_gl;
extern crate gfx_gl as gl;
extern crate piston;
extern crate piston_window;
extern crate sdl2;
extern crate sdl2_window;
extern crate shader_version;
extern crate skeletal_animation;
extern crate vecmath;

use std::path::Path;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;


use gfx_debug_draw::DebugRenderer;

use piston::window::{
    WindowSettings,
};

use piston::event::*;

use vecmath::{Matrix4, mat4_id};

use sdl2_window::Sdl2Window;

use camera_controllers::{
    OrbitZoomCamera,
    OrbitZoomCameraSettings,
    CameraPerspective,
    model_view_projection
};

use skeletal_animation::*;
use collada::document::ColladaDocument;

pub struct Settings {
    pub draw_skeleton: bool,
    pub draw_labels: bool,
    pub draw_mesh: bool,
    pub playback_speed: f32,

    pub params: HashMap<String, f32>,
}

fn main() {

    env_logger::init().unwrap();

    let (win_width, win_height) = (640, 480);
    let window = Rc::new(RefCell::new(Sdl2Window::new(
        shader_version::OpenGL::_3_2,
        WindowSettings::new(
            "Skeletal Animation Demo".to_string(),
            piston::window::Size { width: 640, height: 480 }
        ).exit_on_esc(true)
    )));

    let piston_window = piston_window::PistonWindow::new(window, piston_window::empty_app());

    let mut debug_renderer = DebugRenderer::from_canvas(
        &mut piston_window.canvas.borrow_mut(),
        64,
        None,
        None,
    ).ok().unwrap();

    // TODO - these are (usually) available in the COLLADA file, associated with a <mesh> element in a somewhat convoluted way
    let texture_paths = vec![
        "assets/young_lightskinned_male_diffuse.png",
        "assets/suit01lres_diffuse.png",
        "assets/male02_diffuse_black.png",
        "assets/brown_eye.png",
        "assets/eyebrow009.png",
        "assets/eyelashes01.png",
    ];

    let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap();

    // TODO better.. we keep reloading the same document over and over for different things...
    let skeleton = {
        let skeleton_set = collada_document.get_skeletons().unwrap();
        Skeleton::from_collada(&skeleton_set[0])
    };

    let skeleton = Rc::new(skeleton);

    let mut asset_manager = AssetManager::new();
    asset_manager.load_animations("assets/clips.json");

    let controller_def = AssetManager::load_def_from_path("assets/human_controller.json").unwrap();
    let mut controller = AnimationController::new(controller_def, skeleton.clone(), &asset_manager.animation_clips);

    let mut skinned_renderer = SkinnedRenderer::from_collada(&mut piston_window.canvas.borrow_mut().factory, collada_document, texture_paths).unwrap();

    let model = mat4_id();
    let mut projection = CameraPerspective {
        fov: 90.0f32,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();

    let mut orbit_zoom_camera: OrbitZoomCamera<f32> = OrbitZoomCamera::new(
        [0.0, 0.0, 0.0],
        OrbitZoomCameraSettings::default()
    );

    // Start event loop

    let mut settings = Settings {

        draw_skeleton: true,
        draw_labels: false,
        draw_mesh: true,
        playback_speed: 1.0,

        params: HashMap::new(),
    };

    let mut menu = dev_menu::Menu::<Settings>::new();

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Skeleton",
        Box::new( |ref mut settings| { settings.draw_skeleton = !settings.draw_skeleton; })
    ));

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Joint Labels",
        Box::new( |ref mut settings| { settings.draw_labels = !settings.draw_labels; })
    ));

    menu.add_item(dev_menu::MenuItem::action_item(
        "Toggle Mesh",
        Box::new( |ref mut settings| { settings.draw_mesh = !settings.draw_mesh; })
    ));

    menu.add_item(dev_menu::MenuItem::slider_item(
        "Playback Speed = ",
        [-5.0, 5.0],
        0.01,
        Box::new( |ref settings| { settings.playback_speed }),
        Box::new( |ref mut settings, value| { settings.playback_speed = value }),
    ));

    for (param, &value) in controller.get_parameters().iter() {
        settings.params.insert(param.clone(), value);

        // Apparently need to make our own string copies to move into each closure..
        let param_copy_1 = param.clone();
        let param_copy_2 = param.clone();

        menu.add_item(dev_menu::MenuItem::slider_item(
            &format!("Param[{}] = ", param)[..],
            [0.0, 1.0],
            0.01,
            Box::new( move |ref settings| {
                settings.params[&param_copy_1[..]]
            }),
            Box::new( move |ref mut settings, value| {
                settings.params.insert(param_copy_2.clone(), value);
            }),
        ));
    }

    for e in piston_window {

        orbit_zoom_camera.event(&e);
        menu.event(&e, &mut settings);

        e.resize(|width, height| {
            // Update projection matrix
            projection = CameraPerspective {
                fov: 90.0f32,
                near_clip: 0.1,
                far_clip: 1000.0,
                aspect_ratio: (width as f32) / (height as f32)
            }.projection();
        });

        e.update(|args| {

            controller.set_playback_speed(settings.playback_speed as f64);

            for (param, &value) in settings.params.iter() {
                controller.set_param_value(param, value);
            }

            controller.update(args.dt);
        });

        e.draw_3d(|canvas| {

            let args = e.render_args().unwrap();
{'fraction_non_alphanumeric': 0.12572631578947369, 'fraction_numerical': 0.017347368421052632, 'mean_word_length': 2.774952320406866, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6288306', 'n_tokens_mistral': 3896, 'n_tokens_neox': 3639, 'n_words': 798}