<commit_before>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Load, LoadError, ResCache};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }

  /// Sample a spline at a given time.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  pub fn sample(&self, t: Time) -> Option<T>
      where T: Interpolate {
    let keys = &self.keys;
    let i = search_lower_cp(keys, t);

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }
}

impl<T> Load for Spline<T> where T: Deserialize {
  type Args = ();

  const TY_STR: &'static str = "splines";

  fn load<P>(path: P, _: &mut ResCache, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys))
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time.
fn search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let mut i = 0;
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<commit_msg>Added Spline::clamped_sample.<commit_after>use serde::Deserialize;
use serde_json::from_reader;
use std::f32::consts;
use std::fs::File;
use std::ops::{Add, Div, Mul, Sub};
use std::path::Path;

use linear::{UnitQuaternion, Vector2, Vector3, Vector4};
use resource::{Load, LoadError, ResCache};

/// Time used as sampling type in splines.
pub type Time = f32;

/// A spline control point.
///
/// This type associates a value at a given time. It also contains an interpolation object used to
/// determine how to interpolate values on the segment defined by this key and the next one.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Key<T> {
  /// Time at which the `Key` should be reached.
  pub t: Time,
  /// Actual value.
  pub value: T,
  /// Interpolation mode.
  #[serde(default)]
  pub interpolation: Interpolation
}

impl<T> Key<T> {
  /// Create a new key.
  pub fn new(t: Time, value: T, interpolation: Interpolation) -> Self {
    Key {
      t: t,
      value: value,
      interpolation: interpolation
    }
  }
}

/// Interpolation mode.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub enum Interpolation {
  /// Hold a `Key` until the time passes the normalized step threshold, in which case the next
  /// key is used.
  ///
  /// *Note: if you set the threshold to `0.5`, the first key will be used until the time is half
  /// between the two keys; the second key will be in used afterwards. If you set it to `1.0`, the
  /// first key will be kept until the next key.*
  #[serde(rename = "step")]
  Step(f32),
  /// Linear interpolation between a key and the next one.
  #[serde(rename = "linear")]
  Linear,
  /// Cosine interpolation between a key and the next one.
  #[serde(rename = "cosine")]
  Cosine,
  /// Catmull-Rom interpolation.
  #[serde(rename = "catmull_rom")]
  CatmullRom
}

impl Default for Interpolation {
  /// `Interpolation::Linear` is the default.
  fn default() -> Self {
    Interpolation::Linear
  }
}

/// Spline curve used to provide interpolation between control points (keys).
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Spline<T> {
  keys: Vec<Key<T>>,
}

impl<T> Spline<T> {
  /// Create a new spline out of keys. The keys don’t have to be sorted because they’re sorted by
  /// this function.
  pub fn from_keys(mut keys: Vec<Key<T>>) -> Self {
    keys.sort_by(|k0, k1| k0.t.partial_cmp(&k1.t).unwrap());

    Spline {
      keys: keys
    }
  }

  /// Sample a spline at a given time.
  ///
  /// # Return
  ///
  /// `None` if you try to sample a value at a time that has no key associated with. That can also
  /// happen if you try to sample between two keys with a specific interpolation mode that make the
  /// sampling impossible. For instance, `Interpolate::CatmullRom` requires *four* keys. If you’re
  /// near the beginning of the spline or its end, ensure you have enough keys around to make the
  /// sampling.
  pub fn sample(&self, t: Time) -> Option<T> where T: Interpolate {
    let keys = &self.keys;
    let i = search_lower_cp(keys, t);

    let i = match i {
      Some(i) => i,
      None => return None
    };

    let cp0 = &keys[i];

    match cp0.interpolation {
      Interpolation::Step(threshold) => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        Some(if nt < threshold { cp0.value } else { cp1.value })
      },
      Interpolation::Linear => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);

        Some(Interpolate::lerp(cp0.value, cp1.value, nt))
      },
      Interpolation::Cosine => {
        let cp1 = &keys[i+1];
        let nt = normalize_time(t, cp0, cp1);
        let cos_nt = (1. - f32::cos(nt * consts::PI)) * 0.5;

        Some(Interpolate::lerp(cp0.value, cp1.value, cos_nt))
      },
      Interpolation::CatmullRom => {
        // We need at least four points for Catmull Rom; ensure we have them, otherwise, return
        // None.
        if i == 0 || i >= keys.len() - 2 {
          None
        } else {
          let cp1 = &keys[i+1];
          let cpm0 = &keys[i-1];
          let cpm1 = &keys[i+2];
          let nt = normalize_time(t, cp0, cp1);

          Some(Interpolate::cubic_hermite((cpm0.value, cpm0.t), (cp0.value, cp0.t), (cp1.value, cp1.t), (cpm1.value, cpm1.t), nt))
        }
      }
    }
  }

  /// Sample a spline at a given time with clamping.
  ///
  /// # Return
  ///
  /// If you sample before the first key or after the last one,
  /// return the first key or the last one, respectively.
  ///
  /// # Panic
  ///
  /// This function panics if you have no key.
  pub fn clamped_sample(&self, t: Time) -> T where T: Interpolate {
    let first = self.keys.first().unwrap();
    let last = self.keys.last().unwrap();

    if t <= first.t {
      return first.value;
    } else if t >= last.t {
      return last.value;
    }

    self.sample(t).unwrap()
  }
}

impl<T> Load for Spline<T> where T: Deserialize {
  type Args = ();

  const TY_STR: &'static str = "splines";

  fn load<P>(path: P, _: &mut ResCache, _: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading spline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let keys = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(Spline::from_keys(keys))
  }
}

/// Iterator over spline keys.
pub struct SplineIterator<'a, T> where T: 'a {
  anim_param: &'a Spline<T>,
  i: usize
}

impl<'a, T> Iterator for SplineIterator<'a, T> {
  type Item = &'a Key<T>;

  fn next(&mut self) -> Option<Self::Item> {
    let r = self.anim_param.keys.get(self.i);

    if let Some(_) = r {
      self.i += 1;
    }

    r
  }
}

impl<'a, T> IntoIterator for &'a Spline<T> {
  type Item = &'a Key<T>;
  type IntoIter = SplineIterator<'a, T>;

  fn into_iter(self) -> Self::IntoIter {
    SplineIterator {
      anim_param: self,
      i: 0
    }
  }
}

/// Keys that can be interpolated between. Implementing this trait is required to perform sampling
/// on splines.
pub trait Interpolate: Copy {
  /// Linear interpolation.
  fn lerp(a: Self, b: Self, t: Time) -> Self;
  /// Cubic hermite interpolation.
  ///
  /// Default to `Self::lerp`.
  fn cubic_hermite(_: (Self, Time), a: (Self, Time), b: (Self, Time), _: (Self, Time), t: Time) -> Self {
    Self::lerp(a.0, b.0, t)
  }
}

impl Interpolate for f32 {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector2<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector3<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for Vector4<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    lerp(a, b, t)
  }

  fn cubic_hermite(x: (Self, Time), a: (Self, Time), b: (Self, Time), y: (Self, Time), t: Time) -> Self {
    cubic_hermite(x, a, b, y, t)
  }
}

impl Interpolate for UnitQuaternion<f32> {
  fn lerp(a: Self, b: Self, t: Time) -> Self {
    a * UnitQuaternion::new(&(UnitQuaternion::new(&a.quaternion().conjugate()) * b).quaternion().powf(t))
  }
}

// Default implementation of Interpolate::lerp.
pub fn lerp<T>(a: T, b: T, t: Time) -> T where T: Add<Output = T> + Mul<Time, Output = T> {
  a * (1. - t) + b * t
}

// Default implementation of Interpolate::cubic_hermit.
pub fn cubic_hermite<T>(x: (T, Time), a: (T, Time), b: (T, Time), y: (T, Time), t: Time) -> T
    where T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Time, Output = T> + Div<Time, Output = T> {
  // time stuff
  let t2 = t * t;
  let t3 = t2 * t;
  let two_t3 = 2. * t3;
  let three_t2 = 3. * t2;

  // tangents
  let m0 = (b.0 - x.0) / (b.1 - x.1);
	let m1 = (y.0 - a.0) / (y.1 - a.1);

  a.0 * (two_t3 - three_t2 + 1.) + m0 * (t3 - 2. * t2 + t) + b.0 * (-two_t3 + three_t2) + m1 * (t3 - t2)
}

// Normalize a time ([0;1]) given two control points.
pub fn normalize_time<T>(t: Time, cp: &Key<T>, cp1: &Key<T>) -> Time {
  (t - cp.t) / (cp1.t - cp.t)
}

// Find the lower control point corresponding to a given time.
fn search_lower_cp<T>(cps: &[Key<T>], t: Time) -> Option<usize> {
  let mut i = 0;
  let len = cps.len();

  if len < 2 {
    return None;
  }

  loop {
    let cp = &cps[i];
    let cp1 = &cps[i+1];

    if t >= cp1.t {
      if i >= len - 2 {
        return None;
      }

      i += 1;
    } else if t < cp.t {
      if i == 0 {
        return None;
      }

      i -= 1;
    } else {
      break; // found
    }
  }

  Some(i)
}
<|endoftext|>


<commit_before>/*
  As you can see, our module hierarchy is now two modules deep. There is the crate root, which contains your main() function, and the module farm. The module farm also contains a function and a module white_animals, which futher contains two functions.
  However, somehow the following code does not compile due to the visibility problem. How would you change the code?
*/

mod farm {
  fn pig() { println("Heng heng"); }
  mod white_animals {
    fn cow() { println("Mooo"); }
    fn fox() { println("Ahh..."); }
  }
}

fn main() {
  ::farm::pig();
  ::farm::white_animals::cow();
}

/*Answer:

mod farm {
  pub fn pig() { println("Heng heng"); }
  mod white_animals {
    pub fn cow() { println("Mooo"); }
    pub fn fox() { println("Ahh..."); }
  }
}

fn main() {
  ::farm::pig();
  ::farm::white_animals::cow();
}
*/
<commit_msg>Delete invisible.rs<commit_after><|endoftext|>


<commit_before>// TODO: remove some warnings
#![allow(unstable)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
#![allow(non_snake_case)]
#![allow(improper_ctypes)]

extern crate libc;

use libc::{c_int, c_uchar};
use std::io::fs::PathExtensions;
use std::io::{Reader, File};

#[link(name = "stb_truetype")]
extern { }

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        if !font_path.exists() {
            panic!("Wrong font path: {}", font_path.display());
        }
        Font::from_reader(&mut File::open(font_path), height)
    }

    pub fn from_reader(reader: &mut Reader, height: f32) -> Font {
        let data = reader.read_to_end().unwrap();
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(&data[0] as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, &data[0] as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            Vec::from_raw_buf(buf, (w * h) as usize)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Updated for Rust c5961ad06 2015-01-28 21:49:38<commit_after>// TODO: remove some warnings
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
#![allow(non_snake_case)]
#![allow(improper_ctypes)]
#![feature(io, libc, collections)]

extern crate libc;

use libc::{c_int, c_uchar};
use std::old_io::fs::PathExtensions;
use std::old_io::{Reader, File};

#[link(name = "stb_truetype")]
extern { }

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        if !font_path.exists() {
            panic!("Wrong font path: {}", font_path.display());
        }
        Font::from_reader(&mut File::open(font_path), height)
    }

    pub fn from_reader(reader: &mut Reader, height: f32) -> Font {
        let data = reader.read_to_end().unwrap();
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(&data[0] as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, &data[0] as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            Vec::from_raw_buf(buf, (w * h) as usize)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use nom;
use nom::{Err, IResult};

use metadata;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  pub fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                                   -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}
<commit_msg>Add iteration based decoding<commit_after>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

pub struct Stream {
  info: StreamInfo,
  pub metadata: Vec<Metadata>,
  pub frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  pub fn info(&self) -> StreamInfo {
    self.info
  }

  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  pub fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  pub fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                                   -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}
<|endoftext|>


<commit_before>use rutorch::*;
use std::ops::{Index, IndexMut, Deref, DerefMut};
//use std::convert::From;
use std::cmp::max;

use storage::*;
use rand;
use std::marker::PhantomData;
use {Ixs, RcMut};

pub struct Tensor<T> {
    value: RcMut<TensorImpl<T, Output = T>>,
}

impl<'a, T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}
/*
impl<'a> Tensor<'a> {
    fn view<'a>(&self, dims: &[i32]) -> Tensor<'a> {
    }
}
*/
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}
<commit_msg>fix compile warnings<commit_after>use rutorch::*;
use std::ops::{Index, IndexMut, Deref, DerefMut};
//use std::convert::From;
use std::cmp::max;

use storage::*;
use rand;
use {Ixs, RcMut};

pub struct Tensor<T> {
    value: RcMut<TensorImpl<T, Output = T>>,
}

impl<'a, T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}
/*
impl<'a> Tensor<'a> {
    fn view<'a>(&self, dims: &[i32]) -> Tensor<'a> {
    }
}
*/
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::collections::btree_map::Iter;
use std::path::{PathBuf, Path};
use std::fmt::{Display, Formatter, Result};
use std::ops::Add;

/// Used to track the state of logical conditions
#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct LogicState {
    /// Whether the condition has been observed as true
    pub been_true: bool,
    /// Whether the condition has been observed as false
    pub been_false: bool,
}

impl<'a> Add for &'a LogicState {
    type Output = LogicState;

    fn add(self, other: &'a LogicState) -> LogicState {
        LogicState {
            been_true: self.been_true | other.been_true,
            been_false: self.been_false | other.been_false,
        }
    }
}

/// Shows what type of coverage data is being collected by a given trace
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub enum CoverageStat {
    /// Line coverage data (whether line has been hit)
    Line(u64),
    /// Branch coverage data (whether branch has been true and false
    Branch(LogicState),
    /// Condition coverage data (each boolean subcondition true and false)
    Condition(Vec<LogicState>),
}

impl Add for CoverageStat {
    type Output = CoverageStat;

    fn add(self, other: CoverageStat) -> CoverageStat {
        match (self, other) {
            (CoverageStat::Line(ref l), CoverageStat::Line(ref r)) => {
                CoverageStat::Line(l+r)
            },
            (CoverageStat::Branch(ref l), CoverageStat::Branch(ref r)) => {
                CoverageStat::Branch(l + r)
            },
            t @ _ => t.0,
        }
    }
}

impl Display for CoverageStat {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self {
            &CoverageStat::Line(x) => {
                write!(f, "hits: {}", x)
            },
            _ => write!(f, ""),
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    /// Line the trace is on in the file
    pub line: u64,
    /// Optional address showing location in the test artefact
    pub address: Option<u64>,
    /// Length of the instruction (useful to get entire condition/branch)
    pub length: usize,
    /// Coverage stats
    pub stats: CoverageStat,
}

/// Stores all the program traces mapped to files and provides an interface to
/// add, query and change traces.
pub struct TraceMap {
    /// Traces in the program mapped to the given file
    traces: BTreeMap<PathBuf, Vec<Trace>>,
}

impl TraceMap {
    /// Create a new TraceMap
    pub fn new() -> TraceMap {
        TraceMap {
            traces: BTreeMap::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.traces.is_empty()
    }

    pub fn iter(&self) -> Iter<PathBuf, Vec<Trace>> {
        self.traces.iter()
    }

    pub fn merge(&mut self, other: &TraceMap) {
        for ( k,  values) in other.iter() {
            if !self.traces.contains_key(k) {
                self.traces.insert(k.to_path_buf(), values.to_vec());
            } else {
                let mut existing = self.traces.get_mut(k).unwrap();
                for ref v in values.iter() {
                    let mut added = false;
                    if let Some(ref mut t) = existing.iter_mut().find(|ref x| x.line == v.line) {
                        t.stats = t.stats.clone() + v.stats.clone();
                        added = true;
                    }
                    if !added {
                        existing.push((*v).clone());
                    }
                }
            }
        }
    }

    /// Add a trace to the tracemap for the given file
    pub fn add_trace(&mut self, file: &Path, trace: Trace) {
        if self.traces.contains_key(file) {
            if let Some(trace_vec) = self.traces.get_mut(file) {
                trace_vec.push(trace);
            }
        } else {
            self.traces.insert(file.to_path_buf(), vec![trace]);
        }
    }

    /// Gets an immutable reference to a trace from an address. Returns None if
    /// there is no trace at that address
    pub fn get_trace(&self, address: u64) -> Option<&Trace> {
        self.all_traces()
            .iter()
            .find(|x| x.address == Some(address))
            .map(|x| *x)
    }

    /// Gets a mutable reference to a trace at a given address
    /// Returns None if there is no trace at that address
    pub fn get_trace_mut(&mut self, address: u64) -> Option<&mut Trace> {
        for val in self.all_traces_mut() {
            if val.address == Some(address) {
                return Some(val);
            }
        }
        None
    }

    /// Returns true if the location described by file and line number is present
    /// in the tracemap
    pub fn contains_location(&self, file: &Path, line: u64) -> bool {
        match self.traces.get(file) {
            Some(traces) => traces.iter().any(|x| x.line == line),
            None => false,
        }
    }

    /// Gets all traces below a certain path
    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }

    /// Gets all traces
    pub fn all_traces(&self) -> Vec<&Trace> {
        self.traces.values().flat_map(|ref x| x.iter()).collect()
    }

    /// Gets a vector of all the traces to mutate
    fn all_traces_mut(&mut self) -> Vec<&mut Trace> {
        self.traces.values_mut().flat_map(|x| x.iter_mut()).collect()
    }

    pub fn files(&self) -> Vec<&PathBuf> {
        self.traces.keys().collect()
    }

    pub fn coverable_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    pub fn covered_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Give the total amount of coverable points in the code. This will vary
    /// based on the statistics available for line coverage it will be total
    /// line whereas for condition or decision it will count the number of
    /// conditions available
    pub fn total_coverable(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    /// From all the coverable data return the amount covered
    pub fn total_covered(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Returns coverage percentage ranging from 0.0-1.0
    pub fn coverage_percentage(&self) -> f64 {
        (self.total_covered() as f64) / (self.total_coverable() as f64)
    }

}
<commit_msg>Added line sorting back in<commit_after>use std::collections::BTreeMap;
use std::collections::btree_map::Iter;
use std::path::{PathBuf, Path};
use std::fmt::{Display, Formatter, Result};
use std::ops::Add;
use std::cmp::{Ord, Ordering};

/// Used to track the state of logical conditions
#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, PartialOrd)]
pub struct LogicState {
    /// Whether the condition has been observed as true
    pub been_true: bool,
    /// Whether the condition has been observed as false
    pub been_false: bool,
}

impl<'a> Add for &'a LogicState {
    type Output = LogicState;

    fn add(self, other: &'a LogicState) -> LogicState {
        LogicState {
            been_true: self.been_true | other.been_true,
            been_false: self.been_false | other.been_false,
        }
    }
}

/// Shows what type of coverage data is being collected by a given trace
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub enum CoverageStat {
    /// Line coverage data (whether line has been hit)
    Line(u64),
    /// Branch coverage data (whether branch has been true and false
    Branch(LogicState),
    /// Condition coverage data (each boolean subcondition true and false)
    Condition(Vec<LogicState>),
}

impl Add for CoverageStat {
    type Output = CoverageStat;

    fn add(self, other: CoverageStat) -> CoverageStat {
        match (self, other) {
            (CoverageStat::Line(ref l), CoverageStat::Line(ref r)) => {
                CoverageStat::Line(l+r)
            },
            (CoverageStat::Branch(ref l), CoverageStat::Branch(ref r)) => {
                CoverageStat::Branch(l + r)
            },
            t @ _ => t.0,
        }
    }
}

impl Display for CoverageStat {
    fn fmt(&self, f: &mut Formatter) -> Result {
        match self {
            &CoverageStat::Line(x) => {
                write!(f, "hits: {}", x)
            },
            _ => write!(f, ""),
        }
    }
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd)]
pub struct Trace {
    /// Line the trace is on in the file
    pub line: u64,
    /// Optional address showing location in the test artefact
    pub address: Option<u64>,
    /// Length of the instruction (useful to get entire condition/branch)
    pub length: usize,
    /// Coverage stats
    pub stats: CoverageStat,
}

/// Implemented to allow Traces to be sorted by line number
impl Ord for Trace {
    fn cmp(&self, other: &Trace) -> Ordering {
        self.line.cmp(&other.line)
    }
    fn max(self, other: Trace) -> Trace {
        if self.line > other.line {
            self
        } else {
            other
        }
    }
    fn min(self, other: Trace) -> Trace {
        if self.line < other.line {
            self
        } else {
            other
        }
    }
}

/// Stores all the program traces mapped to files and provides an interface to
/// add, query and change traces.
pub struct TraceMap {
    /// Traces in the program mapped to the given file
    traces: BTreeMap<PathBuf, Vec<Trace>>,
}

impl TraceMap {
    /// Create a new TraceMap
    pub fn new() -> TraceMap {
        TraceMap {
            traces: BTreeMap::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.traces.is_empty()
    }

    pub fn iter(&self) -> Iter<PathBuf, Vec<Trace>> {
        self.traces.iter()
    }

    pub fn merge(&mut self, other: &TraceMap) {
        for ( k,  values) in other.iter() {
            if !self.traces.contains_key(k) {
                self.traces.insert(k.to_path_buf(), values.to_vec());
            } else {
                let mut existing = self.traces.get_mut(k).unwrap();
                for ref v in values.iter() {
                    let mut added = false;
                    if let Some(ref mut t) = existing.iter_mut().find(|ref x| x.line == v.line) {
                        t.stats = t.stats.clone() + v.stats.clone();
                        added = true;
                    }
                    if !added {
                        existing.push((*v).clone());
                        existing.sort_unstable();
                    }
                }
            }
        }
    }

    /// Add a trace to the tracemap for the given file
    pub fn add_trace(&mut self, file: &Path, trace: Trace) {
        if self.traces.contains_key(file) {
            if let Some(trace_vec) = self.traces.get_mut(file) {
                trace_vec.push(trace);
                trace_vec.sort_unstable();
            }
        } else {
            self.traces.insert(file.to_path_buf(), vec![trace]);
        }
    }

    /// Gets an immutable reference to a trace from an address. Returns None if
    /// there is no trace at that address
    pub fn get_trace(&self, address: u64) -> Option<&Trace> {
        self.all_traces()
            .iter()
            .find(|x| x.address == Some(address))
            .map(|x| *x)
    }

    /// Gets a mutable reference to a trace at a given address
    /// Returns None if there is no trace at that address
    pub fn get_trace_mut(&mut self, address: u64) -> Option<&mut Trace> {
        for val in self.all_traces_mut() {
            if val.address == Some(address) {
                return Some(val);
            }
        }
        None
    }

    /// Returns true if the location described by file and line number is present
    /// in the tracemap
    pub fn contains_location(&self, file: &Path, line: u64) -> bool {
        match self.traces.get(file) {
            Some(traces) => traces.iter().any(|x| x.line == line),
            None => false,
        }
    }

    /// Gets all traces below a certain path
    pub fn get_child_traces(&self, root: &Path) -> Vec<&Trace> {
        self.traces.iter()
                   .filter(|&(ref k, _)| k.starts_with(root))
                   .flat_map(|(_, ref v)| v.iter())
                   .collect()
    }

    /// Gets all traces
    pub fn all_traces(&self) -> Vec<&Trace> {
        self.traces.values().flat_map(|ref x| x.iter()).collect()
    }

    /// Gets a vector of all the traces to mutate
    fn all_traces_mut(&mut self) -> Vec<&mut Trace> {
        self.traces.values_mut().flat_map(|x| x.iter_mut()).collect()
    }

    pub fn files(&self) -> Vec<&PathBuf> {
        self.traces.keys().collect()
    }

    pub fn coverable_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    pub fn covered_in_path(&self, path: &Path) -> usize {
        let mut result = 0usize;
        for t in self.get_child_traces(path) {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Give the total amount of coverable points in the code. This will vary
    /// based on the statistics available for line coverage it will be total
    /// line whereas for condition or decision it will count the number of
    /// conditions available
    pub fn total_coverable(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(_) => {
                    2usize
                },
                CoverageStat::Condition(ref x) => {
                    x.len() * 2usize
                }
                _ => 1usize
            };
        }
        result
    }

    /// From all the coverable data return the amount covered
    pub fn total_covered(&self) -> usize {
        let mut result = 0usize;
        for t in self.all_traces() {
            result += match t.stats {
                CoverageStat::Branch(ref x) => {
                    (x.been_true as usize) + (x.been_false as usize)
                },
                CoverageStat::Condition(ref x) => {
                    x.iter()
                     .fold(0, |acc, ref x| acc + (x.been_true as usize) + (x.been_false as usize))
                }
                CoverageStat::Line(ref x) => {
                    (x > &0) as usize
                }
            };
        }
        result
    }

    /// Returns coverage percentage ranging from 0.0-1.0
    pub fn coverage_percentage(&self) -> f64 {
        (self.total_covered() as f64) / (self.total_coverable() as f64)
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}
<commit_msg>Add vector magnitude<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use extra::json;
use std::hashmap::HashMap;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;
use core::{
  Core,
  Unit,
  UnitId,
  PlayerId,
  CommandEndTurn,
  CommandMove,
  EventView,
  EventViewMove,
  EventViewEndTurn,
  MapPos,
};
use core_types::{
  Size2,
  Int,
  Bool,
};
use gl_types::{
  SceneNode,
  Scene,
  VertexCoord,
  TextureCoord,
  Float,
  Point2,
};
use event_visualizer::{
  EventVisualizer,
  EventMoveVisualizer,
  EventEndTurnVisualizer,
};

fn build_hex_mesh(&geom: &Geom, map_size: Size2<Int>) -> ~[VertexCoord] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new(map_size) {
    let pos = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0 as Int, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      vertex_data.push(pos + vertex);
      vertex_data.push(pos + next_vertex);
      vertex_data.push(pos + Vec3::zero());
    }
  }
  vertex_data
}

fn build_hex_tex_coord(map_size: Size2<Int>) -> ~[TextureCoord] {
  let mut vertex_data = ~[];
  for _ in TileIterator::new(map_size) {
    for _ in range(0, 6) {
      vertex_data.push(Vec2{x: 0.0, y: 0.0});
      vertex_data.push(Vec2{x: 1.0, y: 0.0});
      vertex_data.push(Vec2{x: 0.5, y: 0.5});
    }
  }
  vertex_data
}

fn read_win_size(config_path: &str) -> Size2<Int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<Int> = Decodable::decode(&mut decoder);
  size
}

fn init_win(win_size: Size2<Int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

pub struct Visualizer<'a> {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: glfw::Window,
  mouse_pos: Point2<Float>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<MapPos>,
  selected_unit_id: Option<UnitId>,
  geom: Geom,
  scenes: HashMap<PlayerId, Scene>,
  core: Core<'a>,
  event_visualizer: Option<~EventVisualizer>,
}

impl<'a> Visualizer<'a> {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: win,
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(win_size),
      selected_tile_pos: None,
      selected_unit_id: None,
      geom: geom,
      scenes: {
        let mut m = HashMap::new();
        m.insert(0 as PlayerId, HashMap::new());
        m.insert(1 as PlayerId, HashMap::new());
        m
      },
      core: Core::new(),
      event_visualizer: None,
    };
    vis.init_opengl();
    vis.picker.init(&geom, vis.core.map_size);
    vis.init_models();
    vis.init_units();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    &self.win
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let vertex_coordinates_attr = glh::get_attr(
      self.program, "in_vertex_coordinates");
    gl::EnableVertexAttribArray(vertex_coordinates_attr);
    glh::vertex_attrib_pointer(vertex_coordinates_attr, 3);
    let texture_coords_attr = glh::get_attr(
      self.program, "in_texture_coordinates");
    gl::EnableVertexAttribArray(texture_coords_attr);
    glh::vertex_attrib_pointer(texture_coords_attr, 3);
    let map_vertex_data = build_hex_mesh(&self.geom, self.core.map_size);
    self.map_mesh.set_vertex_coords(map_vertex_data);
    self.map_mesh.set_texture_coords(build_hex_tex_coord(self.core.map_size));
    self.map_mesh.set_texture(glh::load_texture(~"data/floor.png"));
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.set_vertex_coords(unit_obj.build());
    self.unit_mesh.set_texture_coords(unit_obj.build_tex_coord());
    self.unit_mesh.set_texture(glh::load_texture(~"data/tank.png"));
  }

  fn scene<'a>(&'a self) -> &'a Scene {
    self.scenes.get(&self.core.current_player_id)
  }

  fn add_unit(&mut self, id: UnitId, pos: MapPos) {
    for (_, scene) in self.scenes.mut_iter() {
      let world_pos = self.geom.map_pos_to_world_pos(pos);
      scene.insert(id, SceneNode{pos: world_pos});
      self.core.units.push(Unit{id: id, pos: pos});
    }
  }

  fn init_units(&mut self) {
    self.add_unit(0, Vec2{x: 0, y: 0});
    self.add_unit(1, Vec2{x: 0, y: 1});
    self.add_unit(2, Vec2{x: 1, y: 0});
    self.add_unit(2, Vec2{x: 1, y: 1});
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
    gl::Enable(gl::DEPTH_TEST);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_units(&self) {
    gl::UseProgram(self.program);
    for (_, unit) in self.scene().iter() {
      let m = glh::tr(self.camera.mat(), unit.pos);
      glh::uniform_mat4f(self.mat_id, &m);
      self.unit_mesh.draw(self.program);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&mut self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    if !self.event_visualizer.is_none() {
      let scene = self.scenes.get_mut(&self.core.current_player_id);
      self.event_visualizer.get_mut_ref().draw(&self.geom, scene);
    }
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> Bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeyT => {
        self.core.do_command(CommandEndTurn);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      glfw::KeyMinus => self.camera.zoom += 1.0,
      glfw::KeyEqual => self.camera.zoom -= 1.0,
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Point2<Float>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
      self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
    }
    self.mouse_pos = pos;
  }

  fn handle_mouse_button_event(&mut self) {
    if self.selected_tile_pos.is_some() {
      let pos = self.selected_tile_pos.unwrap();
      if self.core.is_unit_at(pos) {
        let unit = self.core.unit_at_mut(pos);
        self.selected_unit_id = Some(unit.id);
      } else if self.selected_unit_id.is_some() {
        let unit_id = self.selected_unit_id.unwrap();
        self.core.do_command(CommandMove(unit_id, pos));
      }
    }
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent] {
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as Float, y: y as Float};
        self.handle_cursor_pos_event(p);
      },
      glfw::MouseButtonEvent(glfw::MouseButtonLeft, glfw::Press, _) => {
        self.handle_mouse_button_event();
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
        self.picker.set_win_size(Size2{x: w, y: h});
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as Int,
      y: self.mouse_pos.y as Int,
    };
    self.selected_tile_pos = self.picker.pick_tile(&self.camera, mouse_pos);
  }

  pub fn make_event_visualizer(
    &mut self,
    event_view: EventView
  ) -> ~EventVisualizer {
    match event_view {
      EventViewMove(unit_id, path) => {
        EventMoveVisualizer::new(unit_id, path)
      },
      EventViewEndTurn(_, _) => {
        EventEndTurnVisualizer::new()
      },
    }
  }

  pub fn logic(&mut self) {
    if self.event_visualizer.is_none() {
      let player_id = self.core.current_player_id;
      if self.core.event_view_lists.get(&player_id).len() != 0 {
        let event_view = {
          let event_view_list = self.core.event_view_lists.get_mut(&player_id);
          event_view_list.shift().unwrap()
        };
        self.event_visualizer = Some(self.make_event_visualizer(event_view));
      }
    } else if self.event_visualizer.get_ref().is_finished() {
      let scene = self.scenes.get_mut(&self.core.current_player_id);
      self.event_visualizer.get_mut_ref().end(&self.geom, scene);
      self.event_visualizer = None;
    }
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.logic();
    self.pick_tile();
    self.draw();
  }
}

impl<'a> Drop for Visualizer<'a> {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Visualizer: Fixed add_unit and init_units<commit_after>// See LICENSE file for copyright and license details.

use extra::json;
use std::hashmap::HashMap;
use serialize::Decodable;
use glfw;
use gl;
use gl::types::{
  GLint,
  GLuint,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use glh = gl_helpers;
use camera::Camera;
use map::TileIterator;
use geom::Geom;
use tile_picker::TilePicker;
use obj;
use mesh::Mesh;
use misc::read_file;
use core::{
  Core,
  Unit,
  UnitId,
  PlayerId,
  CommandEndTurn,
  CommandMove,
  EventView,
  EventViewMove,
  EventViewEndTurn,
  MapPos,
};
use core_types::{
  Size2,
  Int,
  Bool,
};
use gl_types::{
  SceneNode,
  Scene,
  VertexCoord,
  TextureCoord,
  Float,
  Point2,
};
use event_visualizer::{
  EventVisualizer,
  EventMoveVisualizer,
  EventEndTurnVisualizer,
};

fn build_hex_mesh(&geom: &Geom, map_size: Size2<Int>) -> ~[VertexCoord] {
  let mut vertex_data = ~[];
  for tile_pos in TileIterator::new(map_size) {
    let pos = geom.map_pos_to_world_pos(tile_pos);
    for num in range(0 as Int, 6) {
      let vertex = geom.index_to_hex_vertex(num);
      let next_vertex = geom.index_to_hex_vertex(num + 1);
      vertex_data.push(pos + vertex);
      vertex_data.push(pos + next_vertex);
      vertex_data.push(pos + Vec3::zero());
    }
  }
  vertex_data
}

fn build_hex_tex_coord(map_size: Size2<Int>) -> ~[TextureCoord] {
  let mut vertex_data = ~[];
  for _ in TileIterator::new(map_size) {
    for _ in range(0, 6) {
      vertex_data.push(Vec2{x: 0.0, y: 0.0});
      vertex_data.push(Vec2{x: 1.0, y: 0.0});
      vertex_data.push(Vec2{x: 0.5, y: 0.5});
    }
  }
  vertex_data
}

fn read_win_size(config_path: &str) -> Size2<Int> {
  let path = Path::new(config_path);
  let json = json::from_str(read_file(&path)).unwrap();
  let mut decoder = json::Decoder::new(json);
  let size: Size2<Int> = Decodable::decode(&mut decoder);
  size
}

fn init_win(win_size: Size2<Int>) -> glfw::Window {
  glfw::set_error_callback(~glfw::LogErrorHandler);
  let init_status = glfw::init();
  if !init_status.is_ok() {
    fail!("Failed to initialize GLFW");
  }
  let win = glfw::Window::create(
    win_size.x as u32,
    win_size.y as u32,
    "Marauder",
    glfw::Windowed,
  ).unwrap();
  win.make_context_current();
  win.set_all_polling(true);
  win
}

pub struct Visualizer<'a> {
  program: GLuint,
  map_mesh: Mesh,
  unit_mesh: Mesh,
  mat_id: GLint,
  win: glfw::Window,
  mouse_pos: Point2<Float>,
  camera: Camera,
  picker: TilePicker,
  selected_tile_pos: Option<MapPos>,
  selected_unit_id: Option<UnitId>,
  geom: Geom,
  scenes: HashMap<PlayerId, Scene>,
  core: Core<'a>,
  event_visualizer: Option<~EventVisualizer>,
}

impl<'a> Visualizer<'a> {
  pub fn new() -> ~Visualizer {
    let win_size = read_win_size("config.json");
    let win = init_win(win_size);
    let geom = Geom::new();
    let mut vis = ~Visualizer {
      program: 0,
      map_mesh: Mesh::new(),
      unit_mesh: Mesh::new(),
      mat_id: 0,
      win: win,
      mouse_pos: Vec2::zero(),
      camera: Camera::new(),
      picker: TilePicker::new(win_size),
      selected_tile_pos: None,
      selected_unit_id: None,
      geom: geom,
      scenes: {
        let mut m = HashMap::new();
        m.insert(0 as PlayerId, HashMap::new());
        m.insert(1 as PlayerId, HashMap::new());
        m
      },
      core: Core::new(),
      event_visualizer: None,
    };
    vis.init_opengl();
    vis.picker.init(&geom, vis.core.map_size);
    vis.init_models();
    vis.init_units();
    vis
  }

  fn win<'a>(&'a self) -> &'a glfw::Window {
    &self.win
  }

  fn init_models(&mut self) {
    self.program = glh::compile_program(
      read_file(&Path::new("normal.vs.glsl")),
      read_file(&Path::new("normal.fs.glsl")),
    );
    gl::UseProgram(self.program);
    self.mat_id = glh::get_uniform(self.program, "mvp_mat");
    let vertex_coordinates_attr = glh::get_attr(
      self.program, "in_vertex_coordinates");
    gl::EnableVertexAttribArray(vertex_coordinates_attr);
    glh::vertex_attrib_pointer(vertex_coordinates_attr, 3);
    let texture_coords_attr = glh::get_attr(
      self.program, "in_texture_coordinates");
    gl::EnableVertexAttribArray(texture_coords_attr);
    glh::vertex_attrib_pointer(texture_coords_attr, 3);
    let map_vertex_data = build_hex_mesh(&self.geom, self.core.map_size);
    self.map_mesh.set_vertex_coords(map_vertex_data);
    self.map_mesh.set_texture_coords(build_hex_tex_coord(self.core.map_size));
    self.map_mesh.set_texture(glh::load_texture(~"data/floor.png"));
    let unit_obj = obj::Model::new("data/tank.obj");
    self.unit_mesh.set_vertex_coords(unit_obj.build());
    self.unit_mesh.set_texture_coords(unit_obj.build_tex_coord());
    self.unit_mesh.set_texture(glh::load_texture(~"data/tank.png"));
  }

  fn scene<'a>(&'a self) -> &'a Scene {
    self.scenes.get(&self.core.current_player_id)
  }

  fn add_unit(&mut self, id: UnitId, pos: MapPos) {
    for (_, scene) in self.scenes.mut_iter() {
      let world_pos = self.geom.map_pos_to_world_pos(pos);
      scene.insert(id, SceneNode{pos: world_pos});
    }
    self.core.units.push(Unit{id: id, pos: pos});
  }

  fn init_units(&mut self) {
    // TODO: generate unique ids
    self.add_unit(0, Vec2{x: 0, y: 0});
    self.add_unit(1, Vec2{x: 0, y: 1});
    self.add_unit(2, Vec2{x: 1, y: 0});
    self.add_unit(3, Vec2{x: 1, y: 1});
  }

  fn init_opengl(&mut self) {
    gl::load_with(glfw::get_proc_address);
    gl::Enable(gl::DEPTH_TEST);
  }

  fn cleanup_opengl(&self) {
    gl::DeleteProgram(self.program);
  }

  fn draw_units(&self) {
    gl::UseProgram(self.program);
    for (_, unit) in self.scene().iter() {
      let m = glh::tr(self.camera.mat(), unit.pos);
      glh::uniform_mat4f(self.mat_id, &m);
      self.unit_mesh.draw(self.program);
    }
  }

  fn draw_map(&self) {
    glh::uniform_mat4f(self.mat_id, &self.camera.mat());
    self.map_mesh.draw(self.program);
  }

  fn draw(&mut self) {
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
    gl::UseProgram(self.program);
    self.draw_units();
    self.draw_map();
    if !self.event_visualizer.is_none() {
      let scene = self.scenes.get_mut(&self.core.current_player_id);
      self.event_visualizer.get_mut_ref().draw(&self.geom, scene);
    }
    self.win().swap_buffers();
  }

  pub fn is_running(&self) -> Bool {
    return !self.win().should_close()
  }

  fn handle_key_event(&mut self, key: glfw::Key) {
    match key {
      glfw::KeyEscape | glfw::KeyQ => {
        self.win().set_should_close(true);
      },
      glfw::KeyT => {
        self.core.do_command(CommandEndTurn);
      },
      glfw::KeySpace => println!("space"),
      glfw::KeyUp => self.camera.move(270.0),
      glfw::KeyDown => self.camera.move(90.0),
      glfw::KeyRight => self.camera.move(0.0),
      glfw::KeyLeft => self.camera.move(180.0),
      glfw::KeyMinus => self.camera.zoom += 1.0,
      glfw::KeyEqual => self.camera.zoom -= 1.0,
      _ => {},
    }
  }

  fn handle_cursor_pos_event(&mut self, pos: Point2<Float>) {
    let button = self.win().get_mouse_button(glfw::MouseButtonRight);
    if button == glfw::Press {
      self.camera.z_angle += (self.mouse_pos.x - pos.x) / 2.0;
      self.camera.x_angle += (self.mouse_pos.y - pos.y) / 2.0;
    }
    self.mouse_pos = pos;
  }

  fn handle_mouse_button_event(&mut self) {
    if self.selected_tile_pos.is_some() {
      let pos = self.selected_tile_pos.unwrap();
      if self.core.is_unit_at(pos) {
        let unit = self.core.unit_at_mut(pos);
        self.selected_unit_id = Some(unit.id);
      } else if self.selected_unit_id.is_some() {
        let unit_id = self.selected_unit_id.unwrap();
        self.core.do_command(CommandMove(unit_id, pos));
      }
    }
  }

  fn get_events(&mut self) -> ~[glfw::WindowEvent] {
    glfw::poll_events();
    let mut events = ~[];
    for (_, event) in self.win().flush_events() {
      events.push(event);
    }
    events
  }

  fn handle_event(&mut self, event: glfw::WindowEvent) {
    match event {
      glfw::KeyEvent(key, _, glfw::Press, _) => {
        self.handle_key_event(key);
      },
      glfw::CursorPosEvent(x, y) => {
        let p = Vec2{x: x as Float, y: y as Float};
        self.handle_cursor_pos_event(p);
      },
      glfw::MouseButtonEvent(glfw::MouseButtonLeft, glfw::Press, _) => {
        self.handle_mouse_button_event();
      },
      glfw::SizeEvent(w, h) => {
        gl::Viewport(0, 0, w, h);
        self.picker.set_win_size(Size2{x: w, y: h});
      },
      _ => {},
    }
  }

  fn handle_events(&mut self) {
    for event in self.get_events().iter() {
      self.handle_event(*event);
    }
  }

  fn pick_tile(&mut self) {
    let mouse_pos = Vec2 {
      x: self.mouse_pos.x as Int,
      y: self.mouse_pos.y as Int,
    };
    self.selected_tile_pos = self.picker.pick_tile(&self.camera, mouse_pos);
  }

  pub fn make_event_visualizer(
    &mut self,
    event_view: EventView
  ) -> ~EventVisualizer {
    match event_view {
      EventViewMove(unit_id, path) => {
        EventMoveVisualizer::new(unit_id, path)
      },
      EventViewEndTurn(_, _) => {
        EventEndTurnVisualizer::new()
      },
    }
  }

  pub fn logic(&mut self) {
    if self.event_visualizer.is_none() {
      let player_id = self.core.current_player_id;
      if self.core.event_view_lists.get(&player_id).len() != 0 {
        let event_view = {
          let event_view_list = self.core.event_view_lists.get_mut(&player_id);
          event_view_list.shift().unwrap()
        };
        self.event_visualizer = Some(self.make_event_visualizer(event_view));
      }
    } else if self.event_visualizer.get_ref().is_finished() {
      let scene = self.scenes.get_mut(&self.core.current_player_id);
      self.event_visualizer.get_mut_ref().end(&self.geom, scene);
      self.event_visualizer = None;
    }
  }

  pub fn tick(&mut self) {
    self.handle_events();
    self.logic();
    self.pick_tile();
    self.draw();
  }
}

impl<'a> Drop for Visualizer<'a> {
  fn drop(&mut self) {
    self.cleanup_opengl();
  }
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<|endoftext|>