<commit_before>use callback::Callable;
use frame::Frameable;
use label::{ FontSize, Labelable };
use color::{ Color, Colorable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use position::Positionable;
use rectangle;
use ui_context::{ UIID, UiContext };
use vecmath::vec2_add;
use graphics::Graphics;
use graphics::character::CharacterCache;
use widget::Widget;

/// Tuple / Callback params.
pub type Idx = usize;
pub type Len = usize;

/// Represents the state of the menu.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Closed(DrawState),
    Open(DrawState),
}

/// Represents the state of the DropDownList widget.
#[derive(PartialEq, Clone, Copy)]
pub enum DrawState {
    Normal,
    Highlighted(Idx, Len),
    Clicked(Idx, Len),
}

impl DrawState {
    /// Translate the DropDownList's DrawState to the equivalent rectangle::State.
    fn as_rect_state(&self) -> rectangle::State {
        match self {
            &DrawState::Normal => rectangle::State::Normal,
            &DrawState::Highlighted(_, _) => rectangle::State::Highlighted,
            &DrawState::Clicked(_, _) => rectangle::State::Clicked,
        }
    }
}

impl State {
    /// Translate the DropDownList's State to the equivalent rectangle::State.
    fn as_rect_state(&self) -> rectangle::State {
        match self {
            &State::Open(draw_state) | &State::Closed(draw_state) => draw_state.as_rect_state(),
        }
    }
}

widget_fns!(DropDownList, State, Widget::DropDownList(State::Closed(DrawState::Normal)));

/// Is the cursor currently over the widget? If so which item?
fn is_over(pos: Point,
           mouse_pos: Point,
           dim: Dimensions,
           state: State,
           len: Len) -> Option<Idx> {
    match state {
        State::Closed(_) => {
            match rectangle::is_over(pos, mouse_pos, dim) {
                false => None,
                true => Some(0),
            }
        },
        State::Open(_) => {
            let total_h = dim[1] * len as f64;
            match rectangle::is_over(pos, mouse_pos, [dim[0], total_h]) {
                false => None,
                true => Some((((mouse_pos[1] - pos[1]) / total_h) * len as f64) as usize),
            }
        },
    }
}

/// Determine and return the new State by comparing the mouse state
/// and position to the previous State.
fn get_new_state(is_over_idx: Option<Idx>,
                 len: Len,
                 state: State,
                 mouse: Mouse) -> State {
    use self::DrawState::{Normal, Clicked, Highlighted};
    use mouse::ButtonState::{Down, Up};
    match state {
        State::Closed(draw_state) => {
            match is_over_idx {
                Some(_) => {
                    match (draw_state, mouse.left) {
                        (Normal,            Down) => State::Closed(Normal),
                        (Normal,            Up)   |
                        (Highlighted(_, _), Up)   => State::Closed(Highlighted(0, len)),
                        (Highlighted(_, _), Down) => State::Closed(Clicked(0, len)),
                        (Clicked(_, _),     Down) => State::Closed(Clicked(0, len)),
                        (Clicked(_, _),     Up)   => State::Open(Normal),
                    }
                },
                None => State::Closed(Normal),
            }
        },
        State::Open(draw_state) => {
            match is_over_idx {
                Some(idx) => {
                    match (draw_state, mouse.left) {
                        (Normal,            Down) => State::Open(Normal),
                        (Normal,            Up)   |
                        (Highlighted(_, _), Up)   => State::Open(Highlighted(idx, len)),
                        (Highlighted(_, _), Down) => State::Open(Clicked(idx, len)),
                        (Clicked(p_idx, _), Down) => State::Open(Clicked(p_idx, len)),
                        (Clicked(_, _),     Up)   => State::Closed(Normal),
                    }
                },
                None => {
                    match (draw_state, mouse.left) {
                        (Highlighted(p_idx, _), Up) => State::Open(Highlighted(p_idx, len)),
                        _ => State::Closed(Normal),
                    }
                },
            }
        }
    }
}

/// A context on which the builder pattern can be implemented.
pub struct DropDownList<'a, F> {
    ui_id: UIID,
    strings: &'a mut Vec<String>,
    selected: &'a mut Option<Idx>,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl<'a, F> DropDownList<'a, F> {
    pub fn new(ui_id: UIID,
               strings: &'a mut Vec<String>,
               selected: &'a mut Option<Idx>) -> DropDownList<'a, F> {
        DropDownList {
            ui_id: ui_id,
            strings: strings,
            selected: selected,
            pos: [0.0, 0.0],
            dim: [128.0, 32.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, F> Colorable for DropDownList<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for DropDownList<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Callable<F> for DropDownList<'a, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

impl<'a, F> Labelable<'a> for DropDownList<'a, F>
{
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, F> Positionable for DropDownList<'a, F> {
    fn point(mut self, pos: Point) -> Self {
        self.pos = pos;
        self
    }
}

/*
quack! {
    list: DropDownList['a, F]
    get:
        fn () -> Size [] { Size(list.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(
                Widget::DropDownList(State::Closed(DrawState::Normal))
            )
        }
        fn () -> Id [] { Id(list.ui_id) }
    set:
        fn (val: Size) [] { list.dim = val.0 }
    action:
}
*/

impl<'a, F> ::draw::Drawable for DropDownList<'a, F>
    where
        F: FnMut(&mut Option<Idx>, Idx, String) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over_idx = is_over(self.pos, mouse.pos, self.dim, state, self.strings.len());
        let new_state = get_new_state(is_over_idx, self.strings.len(), state, mouse);

        let sel = match *self.selected {
            Some(idx) if idx < self.strings.len() => { Some(idx) },
            _ => None,
        };
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let t_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
        let t_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);

        // Call the `callback` closure if mouse was released
        // on one of the DropDownMenu items.
        match (state, new_state) {
            (State::Open(o_d_state), State::Closed(c_d_state)) => {
                match (o_d_state, c_d_state) {
                    (DrawState::Clicked(idx, _), DrawState::Normal) => {
                        match self.maybe_callback {
                            Some(ref mut callback) => (*callback)(self.selected, idx, (*self.strings)[idx].clone()),
                            None => (),
                        }
                    }, _ => (),
                }
            }, _ => (),
        }

        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };

        match new_state {

            State::Closed(_) => {
                let rect_state = new_state.as_rect_state();
                let text = match sel {
                    Some(idx) => &(*self.strings)[idx][..],
                    None => match self.maybe_label {
                        Some(text) => text,
                        None => &(*self.strings)[0][..],
                    },
                };
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, t_size, t_color
                )
            },

            State::Open(draw_state) => {
                for (i, string) in self.strings.iter().enumerate() {
                    let rect_state = match sel {
                        None => {
                            match draw_state {
                                DrawState::Normal => rectangle::State::Normal,
                                DrawState::Highlighted(idx, _) => {
                                    if i == idx { rectangle::State::Highlighted }
                                    else { rectangle::State::Normal }
                                },
                                DrawState::Clicked(idx, _) => {
                                    if i == idx { rectangle::State::Clicked }
                                    else { rectangle::State::Normal }
                                },
                            }
                        },
                        Some(sel_idx) => {
                            if sel_idx == i { rectangle::State::Clicked }
                            else {
                                match draw_state {
                                    DrawState::Normal => rectangle::State::Normal,
                                    DrawState::Highlighted(idx, _) => {
                                        if i == idx { rectangle::State::Highlighted }
                                        else { rectangle::State::Normal }
                                    },
                                    DrawState::Clicked(idx, _) => {
                                        if i == idx { rectangle::State::Clicked }
                                        else { rectangle::State::Normal }
                                    },
                                }
                            }
                        },
                    };
                    let idx_y = self.dim[1] * i as f64 - i as f64 * frame_w;
                    let idx_pos = vec2_add(self.pos, [0.0, idx_y]);
                    rectangle::draw_with_centered_label(
                        uic.win_w, uic.win_h, graphics, uic, rect_state, idx_pos,
                        self.dim, maybe_frame, color, &string,
                        t_size, t_color
                    )
                }
            },

        }

        set_state(uic, self.ui_id, Widget::DropDownList(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implemented `Shapeable` for `DropDownList`<commit_after>use callback::Callable;
use frame::Frameable;
use label::{ FontSize, Labelable };
use color::{ Color, Colorable };
use dimensions::Dimensions;
use mouse::Mouse;
use point::Point;
use position::Positionable;
use shape::Shapeable;
use rectangle;
use ui_context::{ UIID, UiContext };
use vecmath::vec2_add;
use graphics::Graphics;
use graphics::character::CharacterCache;
use widget::Widget;

/// Tuple / Callback params.
pub type Idx = usize;
pub type Len = usize;

/// Represents the state of the menu.
#[derive(PartialEq, Clone, Copy)]
pub enum State {
    Closed(DrawState),
    Open(DrawState),
}

/// Represents the state of the DropDownList widget.
#[derive(PartialEq, Clone, Copy)]
pub enum DrawState {
    Normal,
    Highlighted(Idx, Len),
    Clicked(Idx, Len),
}

impl DrawState {
    /// Translate the DropDownList's DrawState to the equivalent rectangle::State.
    fn as_rect_state(&self) -> rectangle::State {
        match self {
            &DrawState::Normal => rectangle::State::Normal,
            &DrawState::Highlighted(_, _) => rectangle::State::Highlighted,
            &DrawState::Clicked(_, _) => rectangle::State::Clicked,
        }
    }
}

impl State {
    /// Translate the DropDownList's State to the equivalent rectangle::State.
    fn as_rect_state(&self) -> rectangle::State {
        match self {
            &State::Open(draw_state) | &State::Closed(draw_state) => draw_state.as_rect_state(),
        }
    }
}

widget_fns!(DropDownList, State, Widget::DropDownList(State::Closed(DrawState::Normal)));

/// Is the cursor currently over the widget? If so which item?
fn is_over(pos: Point,
           mouse_pos: Point,
           dim: Dimensions,
           state: State,
           len: Len) -> Option<Idx> {
    match state {
        State::Closed(_) => {
            match rectangle::is_over(pos, mouse_pos, dim) {
                false => None,
                true => Some(0),
            }
        },
        State::Open(_) => {
            let total_h = dim[1] * len as f64;
            match rectangle::is_over(pos, mouse_pos, [dim[0], total_h]) {
                false => None,
                true => Some((((mouse_pos[1] - pos[1]) / total_h) * len as f64) as usize),
            }
        },
    }
}

/// Determine and return the new State by comparing the mouse state
/// and position to the previous State.
fn get_new_state(is_over_idx: Option<Idx>,
                 len: Len,
                 state: State,
                 mouse: Mouse) -> State {
    use self::DrawState::{Normal, Clicked, Highlighted};
    use mouse::ButtonState::{Down, Up};
    match state {
        State::Closed(draw_state) => {
            match is_over_idx {
                Some(_) => {
                    match (draw_state, mouse.left) {
                        (Normal,            Down) => State::Closed(Normal),
                        (Normal,            Up)   |
                        (Highlighted(_, _), Up)   => State::Closed(Highlighted(0, len)),
                        (Highlighted(_, _), Down) => State::Closed(Clicked(0, len)),
                        (Clicked(_, _),     Down) => State::Closed(Clicked(0, len)),
                        (Clicked(_, _),     Up)   => State::Open(Normal),
                    }
                },
                None => State::Closed(Normal),
            }
        },
        State::Open(draw_state) => {
            match is_over_idx {
                Some(idx) => {
                    match (draw_state, mouse.left) {
                        (Normal,            Down) => State::Open(Normal),
                        (Normal,            Up)   |
                        (Highlighted(_, _), Up)   => State::Open(Highlighted(idx, len)),
                        (Highlighted(_, _), Down) => State::Open(Clicked(idx, len)),
                        (Clicked(p_idx, _), Down) => State::Open(Clicked(p_idx, len)),
                        (Clicked(_, _),     Up)   => State::Closed(Normal),
                    }
                },
                None => {
                    match (draw_state, mouse.left) {
                        (Highlighted(p_idx, _), Up) => State::Open(Highlighted(p_idx, len)),
                        _ => State::Closed(Normal),
                    }
                },
            }
        }
    }
}

/// A context on which the builder pattern can be implemented.
pub struct DropDownList<'a, F> {
    ui_id: UIID,
    strings: &'a mut Vec<String>,
    selected: &'a mut Option<Idx>,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl<'a, F> DropDownList<'a, F> {
    pub fn new(ui_id: UIID,
               strings: &'a mut Vec<String>,
               selected: &'a mut Option<Idx>) -> DropDownList<'a, F> {
        DropDownList {
            ui_id: ui_id,
            strings: strings,
            selected: selected,
            pos: [0.0, 0.0],
            dim: [128.0, 32.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, F> Colorable for DropDownList<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for DropDownList<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Callable<F> for DropDownList<'a, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

impl<'a, F> Labelable<'a> for DropDownList<'a, F>
{
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, F> Positionable for DropDownList<'a, F> {
    fn point(mut self, pos: Point) -> Self {
        self.pos = pos;
        self
    }
}

impl<'a, F> Shapeable for DropDownList<'a, F> {
    fn get_dim(&self) -> Dimensions { self.dim }
    fn dim(mut self, dim: Dimensions) -> Self { self.dim = dim; self }
}

/*
quack! {
    list: DropDownList['a, F]
    get:
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(
                Widget::DropDownList(State::Closed(DrawState::Normal))
            )
        }
        fn () -> Id [] { Id(list.ui_id) }
    set:
    action:
}
*/

impl<'a, F> ::draw::Drawable for DropDownList<'a, F>
    where
        F: FnMut(&mut Option<Idx>, Idx, String) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let is_over_idx = is_over(self.pos, mouse.pos, self.dim, state, self.strings.len());
        let new_state = get_new_state(is_over_idx, self.strings.len(), state, mouse);

        let sel = match *self.selected {
            Some(idx) if idx < self.strings.len() => { Some(idx) },
            _ => None,
        };
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        let t_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
        let t_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);

        // Call the `callback` closure if mouse was released
        // on one of the DropDownMenu items.
        match (state, new_state) {
            (State::Open(o_d_state), State::Closed(c_d_state)) => {
                match (o_d_state, c_d_state) {
                    (DrawState::Clicked(idx, _), DrawState::Normal) => {
                        match self.maybe_callback {
                            Some(ref mut callback) => (*callback)(self.selected, idx, (*self.strings)[idx].clone()),
                            None => (),
                        }
                    }, _ => (),
                }
            }, _ => (),
        }

        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };

        match new_state {

            State::Closed(_) => {
                let rect_state = new_state.as_rect_state();
                let text = match sel {
                    Some(idx) => &(*self.strings)[idx][..],
                    None => match self.maybe_label {
                        Some(text) => text,
                        None => &(*self.strings)[0][..],
                    },
                };
                rectangle::draw_with_centered_label(
                    uic.win_w, uic.win_h, graphics, uic, rect_state,
                    self.pos, self.dim, maybe_frame, color,
                    text, t_size, t_color
                )
            },

            State::Open(draw_state) => {
                for (i, string) in self.strings.iter().enumerate() {
                    let rect_state = match sel {
                        None => {
                            match draw_state {
                                DrawState::Normal => rectangle::State::Normal,
                                DrawState::Highlighted(idx, _) => {
                                    if i == idx { rectangle::State::Highlighted }
                                    else { rectangle::State::Normal }
                                },
                                DrawState::Clicked(idx, _) => {
                                    if i == idx { rectangle::State::Clicked }
                                    else { rectangle::State::Normal }
                                },
                            }
                        },
                        Some(sel_idx) => {
                            if sel_idx == i { rectangle::State::Clicked }
                            else {
                                match draw_state {
                                    DrawState::Normal => rectangle::State::Normal,
                                    DrawState::Highlighted(idx, _) => {
                                        if i == idx { rectangle::State::Highlighted }
                                        else { rectangle::State::Normal }
                                    },
                                    DrawState::Clicked(idx, _) => {
                                        if i == idx { rectangle::State::Clicked }
                                        else { rectangle::State::Normal }
                                    },
                                }
                            }
                        },
                    };
                    let idx_y = self.dim[1] * i as f64 - i as f64 * frame_w;
                    let idx_pos = vec2_add(self.pos, [0.0, idx_y]);
                    rectangle::draw_with_centered_label(
                        uic.win_w, uic.win_h, graphics, uic, rect_state, idx_pos,
                        self.dim, maybe_frame, color, &string,
                        t_size, t_color
                    )
                }
            },

        }

        set_state(uic, self.ui_id, Widget::DropDownList(new_state), self.pos, self.dim);

    }
}
<|endoftext|>


<commit_before>use approxeq::ApproxEq;
use num_traits::Float;
use trig::Trig;
use {TypedRotation3D, TypedTransform3D, TypedVector3D, UnknownUnit};

/// A rigid transformation. All lengths are preserved under such a transformation.
///
///
/// Internally, this is a rotation and a translation, with the rotation
/// applied first (i.e. `Translation * Rotation`)
///
/// This can be more efficient to use over full matrices, especially if you
/// have to deal with the decomposed quantities often.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct TypedRigidTransform3D<T, U> {
    pub rotation: TypedRotation3D<T, U, U>,
    pub translation: TypedVector3D<T, U>,
}

pub type RigidTransform3D<T> = TypedRigidTransform3D<T, UnknownUnit>;

impl<T: Float + ApproxEq<T>, U> TypedRigidTransform3D<T, U> {
    /// Construct a new rigid transformation, where the `rotation` applies first
    pub fn new(rotation: TypedRotation3D<T, U, U>, translation: TypedVector3D<T, U>) -> Self {
        Self {
            rotation,
            translation,
        }
    }

    /// Construct a new rigid transformation, where the `translation` applies first
    pub fn new_from_reversed(
        translation: TypedVector3D<T, U>,
        rotation: TypedRotation3D<T, U, U>,
    ) -> Self {
        (Self {
            rotation,
            translation,
        })
        .reverse()
    }

    pub fn from_rotation(rotation: TypedRotation3D<T, U, U>) -> Self {
        Self {
            rotation,
            translation: TypedVector3D::zero(),
        }
    }

    pub fn from_translation(translation: TypedVector3D<T, U>) -> Self {
        Self {
            translation,
            rotation: TypedRotation3D::identity(),
        }
    }

    /// Provide the equivalent rigid transformation obtained by applying self's translation first
    /// and rotation second
    pub fn reverse(&self) -> Self {
        // R * T
        //   = R * T * (R^-1 * R)
        //   = (R * T * R^-1) * R
        //   = T' * R
        //
        // T' = (R * T * R^-1) is also a translation matrix
        // It is equivalent to the translation matrix obtained by rotating the
        // translation by R

        let translation = self.rotation.rotate_vector3d(&self.translation);
        Self {
            rotation: self.rotation,
            translation,
        }
    }

    /// Decompose this into a position and an orientation to be applied in the opposite order
    pub fn decompose_reversed(&self) -> (TypedVector3D<T, U>, TypedRotation3D<T, U, U>) {
        // self = T * R
        //      = R * R^-1 * T * R
        //      = R * (R^-1 * T * R)
        //      = R * T'
        //
        // T' = (R^-1 * T * R) is T rotated by R^-1

        let translation = self.rotation.inverse().rotate_vector3d(&self.translation);
        (translation, self.rotation)
    }

    /// Returns the multiplication of the two transforms such that
    /// other's transformation applies after self's transformation.
    ///
    /// i.e., this produces `other * self`, postmultiplying self to other
    pub fn post_mul(&self, other: &Self) -> Self {
        // self = T1 * R1
        // other = T2 * R2
        // result = T2 * R2 * T1 * R1
        //        = T2 * R2 * R1 * R1^-1 * T1 * R1
        //        = T2 * R2 * R1 * (R1^-1 * T1 * R1)
        //        = T2 * R' * T'
        //        = T2 * R' * T' * R'^-1 * R'
        //        = T2 * (R' * T' * R'^-1) * R'
        //        = T2 * T'' * R'
        //        = T'' * R'
        //
        // (R1^-1 * T1 * R1) = T' = T1 rotated by R1^-1
        // R2 * R1  = R'
        // (R' * T' * R'^-1) = T'' = T' rotated by R'
        // T2 * T'' = T''' = T2 + T'

        let t_prime = self.rotation.inverse().rotate_vector3d(&self.translation);
        let r_prime = self.rotation.post_rotate(&other.rotation);
        let t_prime2 = r_prime.rotate_vector3d(&t_prime);
        let t_prime3 = t_prime2 + other.translation;
        Self {
            rotation: r_prime,
            translation: t_prime3,
        }
    }

    /// Returns the multiplication of the two transforms such that
    /// self's transformation applies after other's transformation.
    ///
    /// i.e., this produces `self * other`, premultiplying self to other
    pub fn pre_mul(&self, other: &Self) -> Self {
        other.post_mul(&self)
    }

    /// Inverts the transformation
    pub fn inverse(&self) -> Self {
        // result = (self)^-1
        //        = (T * R)^-1
        //        = R^-1 * T^-1
        //        = R^-1 * T^-1 * R * R^-1
        //        = (R^-1 * T^-1 * R) * R^-1
        //        = T' * R'
        //
        // T' = (R^-1 * T^-1 * R) = (-T) rotated by R^-1
        // R' = R^-1
        //
        // An easier way of writing this is to use new_from_reversed() with R^-1 and T^-1

        Self::new_from_reversed(-self.translation, self.rotation.inverse())
    }

    pub fn to_transform(&self) -> TypedTransform3D<T, U, U>
    where
        T: Trig,
    {
        self.translation
            .to_transform()
            .pre_mul(&self.rotation.to_transform())
    }
}

impl<T: Float + ApproxEq<T>, U> From<TypedRotation3D<T, U, U>> for TypedRigidTransform3D<T, U> {
    fn from(rot: TypedRotation3D<T, U, U>) -> Self {
        Self::from_rotation(rot)
    }
}

impl<T: Float + ApproxEq<T>, U> From<TypedVector3D<T, U>> for TypedRigidTransform3D<T, U> {
    fn from(t: TypedVector3D<T, U>) -> Self {
        Self::from_translation(t)
    }
}
<commit_msg>Add tests for rigid transformations<commit_after>use approxeq::ApproxEq;
use num_traits::Float;
use trig::Trig;
use {TypedRotation3D, TypedTransform3D, TypedVector3D, UnknownUnit};

/// A rigid transformation. All lengths are preserved under such a transformation.
///
///
/// Internally, this is a rotation and a translation, with the rotation
/// applied first (i.e. `Translation * Rotation`)
///
/// This can be more efficient to use over full matrices, especially if you
/// have to deal with the decomposed quantities often.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct TypedRigidTransform3D<T, U> {
    pub rotation: TypedRotation3D<T, U, U>,
    pub translation: TypedVector3D<T, U>,
}

pub type RigidTransform3D<T> = TypedRigidTransform3D<T, UnknownUnit>;

impl<T: Float + ApproxEq<T>, U> TypedRigidTransform3D<T, U> {
    /// Construct a new rigid transformation, where the `rotation` applies first
    pub fn new(rotation: TypedRotation3D<T, U, U>, translation: TypedVector3D<T, U>) -> Self {
        Self {
            rotation,
            translation,
        }
    }

    /// Construct an identity transform
    pub fn identity() -> Self {
        Self {
            rotation: TypedRotation3D::identity(),
            translation: TypedVector3D::zero(),
        }
    }

    /// Construct a new rigid transformation, where the `translation` applies first
    pub fn new_from_reversed(
        translation: TypedVector3D<T, U>,
        rotation: TypedRotation3D<T, U, U>,
    ) -> Self {
        (Self {
            rotation,
            translation,
        })
        .reverse()
    }

    pub fn from_rotation(rotation: TypedRotation3D<T, U, U>) -> Self {
        Self {
            rotation,
            translation: TypedVector3D::zero(),
        }
    }

    pub fn from_translation(translation: TypedVector3D<T, U>) -> Self {
        Self {
            translation,
            rotation: TypedRotation3D::identity(),
        }
    }

    /// Provide the equivalent rigid transformation obtained by applying self's translation first
    /// and rotation second
    pub fn reverse(&self) -> Self {
        // R * T
        //   = R * T * (R^-1 * R)
        //   = (R * T * R^-1) * R
        //   = T' * R
        //
        // T' = (R * T * R^-1) is also a translation matrix
        // It is equivalent to the translation matrix obtained by rotating the
        // translation by R

        let translation = self.rotation.rotate_vector3d(&self.translation);
        Self {
            rotation: self.rotation,
            translation,
        }
    }

    /// Decompose this into a position and an orientation to be applied in the opposite order
    pub fn decompose_reversed(&self) -> (TypedVector3D<T, U>, TypedRotation3D<T, U, U>) {
        // self = T * R
        //      = R * R^-1 * T * R
        //      = R * (R^-1 * T * R)
        //      = R * T'
        //
        // T' = (R^-1 * T * R) is T rotated by R^-1

        let translation = self.rotation.inverse().rotate_vector3d(&self.translation);
        (translation, self.rotation)
    }

    /// Returns the multiplication of the two transforms such that
    /// other's transformation applies after self's transformation.
    ///
    /// i.e., this produces `other * self`, postmultiplying self to other
    pub fn post_mul(&self, other: &Self) -> Self {
        // self = T1 * R1
        // other = T2 * R2
        // result = T2 * R2 * T1 * R1
        //        = T2 * R2 * R1 * R1^-1 * T1 * R1
        //        = T2 * R2 * R1 * (R1^-1 * T1 * R1)
        //        = T2 * R' * T'
        //        = T2 * R' * T' * R'^-1 * R'
        //        = T2 * (R' * T' * R'^-1) * R'
        //        = T2 * T'' * R'
        //        = T'' * R'
        //
        // (R1^-1 * T1 * R1) = T' = T1 rotated by R1^-1
        // R2 * R1  = R'
        // (R' * T' * R'^-1) = T'' = T' rotated by R'
        // T2 * T'' = T''' = T2 + T'

        let t_prime = self.rotation.inverse().rotate_vector3d(&self.translation);
        let r_prime = self.rotation.post_rotate(&other.rotation);
        let t_prime2 = r_prime.rotate_vector3d(&t_prime);
        let t_prime3 = t_prime2 + other.translation;
        Self {
            rotation: r_prime,
            translation: t_prime3,
        }
    }

    /// Returns the multiplication of the two transforms such that
    /// self's transformation applies after other's transformation.
    ///
    /// i.e., this produces `self * other`, premultiplying self to other
    pub fn pre_mul(&self, other: &Self) -> Self {
        other.post_mul(&self)
    }

    /// Inverts the transformation
    pub fn inverse(&self) -> Self {
        // result = (self)^-1
        //        = (T * R)^-1
        //        = R^-1 * T^-1
        //        = R^-1 * T^-1 * R * R^-1
        //        = (R^-1 * T^-1 * R) * R^-1
        //        = T' * R'
        //
        // T' = (R^-1 * T^-1 * R) = (-T) rotated by R^-1
        // R' = R^-1
        //
        // An easier way of writing this is to use new_from_reversed() with R^-1 and T^-1

        Self::new_from_reversed(-self.translation, self.rotation.inverse())
    }

    pub fn to_transform(&self) -> TypedTransform3D<T, U, U>
    where
        T: Trig,
    {
        self.translation
            .to_transform()
            .pre_mul(&self.rotation.to_transform())
    }
}

impl<T: Float + ApproxEq<T>, U> From<TypedRotation3D<T, U, U>> for TypedRigidTransform3D<T, U> {
    fn from(rot: TypedRotation3D<T, U, U>) -> Self {
        Self::from_rotation(rot)
    }
}

impl<T: Float + ApproxEq<T>, U> From<TypedVector3D<T, U>> for TypedRigidTransform3D<T, U> {
    fn from(t: TypedVector3D<T, U>) -> Self {
        Self::from_translation(t)
    }
}

#[cfg(test)]
mod test {
    use super::RigidTransform3D;
    use {Rotation3D, TypedTransform3D, Vector3D};

    #[test]
    fn test_rigid_construction() {
        let translation = Vector3D::new(12.1, 17.8, -5.5);
        let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);

        let rigid = RigidTransform3D::new(rotation, translation);
        assert!(rigid
            .to_transform()
            .approx_eq(&translation.to_transform().pre_mul(&rotation.to_transform())));

        let rigid = RigidTransform3D::new_from_reversed(translation, rotation);
        assert!(rigid.to_transform().approx_eq(
            &translation
                .to_transform()
                .post_mul(&rotation.to_transform())
        ));
    }

    #[test]
    fn test_rigid_decomposition() {
        let translation = Vector3D::new(12.1, 17.8, -5.5);
        let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);

        let rigid = RigidTransform3D::new(rotation, translation);
        let (t2, r2) = rigid.decompose_reversed();
        assert!(rigid
            .to_transform()
            .approx_eq(&t2.to_transform().post_mul(&r2.to_transform())));
    }

    #[test]
    fn test_rigid_inverse() {
        let translation = Vector3D::new(12.1, 17.8, -5.5);
        let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);

        let rigid = RigidTransform3D::new(rotation, translation);
        let inverse = rigid.inverse();
        assert!(rigid
            .post_mul(&inverse)
            .to_transform()
            .approx_eq(&TypedTransform3D::identity()));
        assert!(inverse
            .to_transform()
            .approx_eq(&rigid.to_transform().inverse().unwrap()));
    }

    #[test]
    fn test_rigid_multiply() {
        let translation = Vector3D::new(12.1, 17.8, -5.5);
        let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);
        let translation2 = Vector3D::new(9.3, -3.9, 1.1);
        let rotation2 = Rotation3D::unit_quaternion(0.1, 0.2, 0.3, -0.4);
        let rigid = RigidTransform3D::new(rotation, translation);
        let rigid2 = RigidTransform3D::new(rotation2, translation2);

        assert!(rigid
            .post_mul(&rigid2)
            .to_transform()
            .approx_eq(&rigid.to_transform().post_mul(&rigid2.to_transform())));
        assert!(rigid
            .pre_mul(&rigid2)
            .to_transform()
            .approx_eq(&rigid.to_transform().pre_mul(&rigid2.to_transform())));
    }
}
<|endoftext|>


<commit_before>//! Module containing bindings to the `rand` library.

extern crate rand;
extern crate rand_xorshift;

use self::rand::{Rng, SeedableRng};

use crate::vm::{
    self,
    api::{RuntimeResult, IO},
    thread::Thread,
    types::VmInt,
    ExternModule,
};

#[derive(Clone, Debug, Userdata, Trace, VmType)]
#[gluon(vm_type = "std.random.XorShiftRng")]
#[gluon(crate_name = "::vm")]
#[gluon_trace(skip)]
struct XorShiftRng(self::rand_xorshift::XorShiftRng);

field_decl! { value, gen }

fn next_int(_: ()) -> IO<VmInt> {
    IO::Value(rand::thread_rng().gen())
}

fn next_float(_: ()) -> IO<f64> {
    IO::Value(rand::thread_rng().gen())
}

fn gen_int_range(low: VmInt, high: VmInt) -> IO<VmInt> {
    IO::Value(rand::thread_rng().gen_range(low, high))
}

type RngNext<G> = record_type! {
    value => VmInt,
    gen => G
};

fn xor_shift_new(seed: &[u8]) -> RuntimeResult<XorShiftRng, String> {
    if seed.len() == 16 {
        let seed = unsafe { *(seed.as_ptr() as *const [u8; 16]) };
        RuntimeResult::Return(XorShiftRng(self::rand_xorshift::XorShiftRng::from_seed(
            seed,
        )))
    } else {
        RuntimeResult::Panic("Expected xorshift seed to have 16 elements".to_string())
    }
}

fn xor_shift_next(gen: &XorShiftRng) -> RngNext<XorShiftRng> {
    let mut gen = gen.clone();
    record_no_decl! {
        value => gen.0.gen(),
        gen => gen
    }
}

mod std {
    pub mod random {
        pub use crate::std_lib::random as prim;
    }
}

pub fn load(vm: &Thread) -> vm::Result<ExternModule> {
    vm.register_type::<XorShiftRng>("std.random.XorShiftRng", &[])?;

    ExternModule::new(
        vm,
        record! {
            type std::random::XorShiftRng => XorShiftRng,
            next_int => primitive!(1, std::random::prim::next_int),
            next_float => primitive!(1, std::random::prim::next_float),
            gen_int_range => primitive!(2, std::random::prim::gen_int_range),
            xor_shift_new => primitive!(1, std::random::prim::xor_shift_new),
            xor_shift_next => primitive!(1, std::random::prim::xor_shift_next)
        },
    )
}
<commit_msg>fix #872 XorShiftRng cannot clone<commit_after>//! Module containing bindings to the `rand` library.

extern crate rand;
extern crate rand_xorshift;

use self::rand::{Rng, SeedableRng};

use crate::vm::{
    self,
    api::{RuntimeResult, IO},
    thread::Thread,
    types::VmInt,
    ExternModule,
};

#[derive(Clone, Debug, Userdata, Trace, VmType)]
#[gluon(vm_type = "std.random.XorShiftRng")]
#[gluon_userdata(clone)]
#[gluon(crate_name = "::vm")]
#[gluon_trace(skip)]
struct XorShiftRng(self::rand_xorshift::XorShiftRng);

field_decl! { value, gen }

fn next_int(_: ()) -> IO<VmInt> {
    IO::Value(rand::thread_rng().gen())
}

fn next_float(_: ()) -> IO<f64> {
    IO::Value(rand::thread_rng().gen())
}

fn gen_int_range(low: VmInt, high: VmInt) -> IO<VmInt> {
    IO::Value(rand::thread_rng().gen_range(low, high))
}

type RngNext<G> = record_type! {
    value => VmInt,
    gen => G
};

fn xor_shift_new(seed: &[u8]) -> RuntimeResult<XorShiftRng, String> {
    if seed.len() == 16 {
        let seed = unsafe { *(seed.as_ptr() as *const [u8; 16]) };
        RuntimeResult::Return(XorShiftRng(self::rand_xorshift::XorShiftRng::from_seed(
            seed,
        )))
    } else {
        RuntimeResult::Panic("Expected xorshift seed to have 16 elements".to_string())
    }
}

fn xor_shift_next(gen: &XorShiftRng) -> RngNext<XorShiftRng> {
    let mut gen = gen.clone();
    record_no_decl! {
        value => gen.0.gen(),
        gen => gen
    }
}

mod std {
    pub mod random {
        pub use crate::std_lib::random as prim;
    }
}

pub fn load(vm: &Thread) -> vm::Result<ExternModule> {
    vm.register_type::<XorShiftRng>("std.random.XorShiftRng", &[])?;

    ExternModule::new(
        vm,
        record! {
            type std::random::XorShiftRng => XorShiftRng,
            next_int => primitive!(1, std::random::prim::next_int),
            next_float => primitive!(1, std::random::prim::next_float),
            gen_int_range => primitive!(2, std::random::prim::gen_int_range),
            xor_shift_new => primitive!(1, std::random::prim::xor_shift_new),
            xor_shift_next => primitive!(1, std::random::prim::xor_shift_next)
        },
    )
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::Write;
use std::str::from_utf8;
use std::ascii::AsciiExt;

use byteorder::{BigEndian, ByteOrder};

use {Error};

/// The DNS name as stored in the original packet
///
/// This is contains just a reference to a slice that contains the data.
/// You may turn this into a string using `.to_string()`
#[derive(Debug)]
pub struct Name<'a>{
    labels: &'a [u8],
    /// This is the original buffer size. The compressed names in original
    /// are calculated in this buffer
    original: &'a [u8],
}

impl<'a> Name<'a> {
    pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> {
        let mut pos = 0;
        loop {
            if data.len() <= pos {
                return Err(Error::UnexpectedEOF);
            }
            let byte = data[pos];
            if byte == 0 {
                return Ok(Name { labels: &data[..pos+1], original: original });
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                if data.len() < pos+2 {
                    return Err(Error::UnexpectedEOF);
                }
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if off >= original.len() {
                    return Err(Error::UnexpectedEOF);
                }
                // Validate referred to location
                try!(Name::scan(&original[off..], original));
                return Ok(Name { labels: &data[..pos+2], original: original });
            } else if byte & 0b1100_0000 == 0 {
                let end = pos + byte as usize + 1;
                if !data[pos+1..end].is_ascii() {
                    return Err(Error::LabelIsNotAscii);
                }
                pos = end;
                if data.len() <= pos {
                    return Err(Error::UnexpectedEOF);
                }
                continue;
            } else {
                return Err(Error::UnknownLabelFormat);
            }
        }
    }
    pub fn byte_len(&self) -> usize {
        self.labels.len()
    }
}

impl<'a> fmt::Display for Name<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let data = self.labels;
        let original = self.original;
        let mut pos = 0;
        loop {
            let byte = data[pos];
            if byte == 0 {
                return Ok(());
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                return fmt::Display::fmt(
                    &Name::scan(&original[off..], original).unwrap(), fmt)
            } else if byte & 0b1100_0000 == 0 {
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                let end = pos + byte as usize + 1;
                try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap()));
                pos = end;
                continue;
            } else {
                unreachable!();
            }
        }
    }
}
<commit_msg>Fix parsing of compressed names, make Name Copy'able<commit_after>use std::fmt;
use std::fmt::Write;
use std::str::from_utf8;
use std::ascii::AsciiExt;

use byteorder::{BigEndian, ByteOrder};

use {Error};

/// The DNS name as stored in the original packet
///
/// This is contains just a reference to a slice that contains the data.
/// You may turn this into a string using `.to_string()`
#[derive(Debug, Clone, Copy)]
pub struct Name<'a>{
    labels: &'a [u8],
    /// This is the original buffer size. The compressed names in original
    /// are calculated in this buffer
    original: &'a [u8],
}

impl<'a> Name<'a> {
    pub fn scan(data: &'a[u8], original: &'a[u8]) -> Result<Name<'a>, Error> {
        let mut pos = 0;
        loop {
            if data.len() <= pos {
                return Err(Error::UnexpectedEOF);
            }
            let byte = data[pos];
            if byte == 0 {
                return Ok(Name { labels: &data[..pos+1], original: original });
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                if data.len() < pos+2 {
                    return Err(Error::UnexpectedEOF);
                }
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if off >= original.len() {
                    return Err(Error::UnexpectedEOF);
                }
                // Validate referred to location
                try!(Name::scan(&original[off..], original));
                return Ok(Name { labels: &data[..pos+2], original: original });
            } else if byte & 0b1100_0000 == 0 {
                let end = pos + byte as usize + 1;
                if !data[pos+1..end].is_ascii() {
                    return Err(Error::LabelIsNotAscii);
                }
                pos = end;
                if data.len() <= pos {
                    return Err(Error::UnexpectedEOF);
                }
                continue;
            } else {
                return Err(Error::UnknownLabelFormat);
            }
        }
    }
    pub fn byte_len(&self) -> usize {
        self.labels.len()
    }
}

impl<'a> fmt::Display for Name<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let data = self.labels;
        let original = self.original;
        let mut pos = 0;
        loop {
            let byte = data[pos];
            if byte == 0 {
                return Ok(());
            } else if byte & 0b1100_0000 == 0b1100_0000 {
                let off = (BigEndian::read_u16(&data[pos..pos+2])
                           & !0b1100_0000_0000_0000) as usize;
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                return fmt::Display::fmt(
                    &Name::scan(&original[off..], original).unwrap(), fmt)
            } else if byte & 0b1100_0000 == 0 {
                if pos != 0 {
                    try!(fmt.write_char('.'));
                }
                let end = pos + byte as usize + 1;
                try!(fmt.write_str(from_utf8(&data[pos+1..end]).unwrap()));
                pos = end;
                continue;
            } else {
                unreachable!();
            }
        }
    }
}
<|endoftext|>


<commit_before>use ::*;
use relm::{Relm, RemoteRelm, Widget};
use gtk::prelude::*;
use gtk::{Window, WindowType, DrawingArea, Button, ScrolledWindow};
use tokio_core::reactor::Interval;
use std::time::Duration;

use map::*;

#[derive(Clone)]
pub struct Model {}

#[derive(Clone)]
pub struct CairoSurface(cairo::Surface);
unsafe impl Send for CairoSurface {}

#[derive(SimpleMsg)]
pub enum Msg {
    Tick,
    Quit,
}

#[derive(Clone)]
pub struct Win {
    hbox: gtk::Box,
    button_box: gtk::ButtonBox,
    pause_button: Button,
    next_button: Button,
    clear_button: Button,
    zoom_in_button: Button,
    zoom_out_button: Button,
    area: DrawingArea,
    scroller: ScrolledWindow,
    window: Window,
}

impl Widget for Win {
    type Root = Window;
    type Model = Model;
    type Msg = Msg;

    fn root(&self) -> &Self::Root {
        &self.window
    }

    fn model() -> Self::Model {
        Model {}
    }

    fn subscriptions(relm: &Relm<Msg>) {
        let stream = Interval::new(Duration::from_millis(50), relm.handle()).unwrap();
        relm.connect_exec_ignore_err(stream, Msg::Tick);
    }

    fn update(&mut self, event: Msg, _model: &mut Self::Model) {
        match event {
            Msg::Tick => {
                use gdk::prelude::ContextExt;
                let cr = cairo::Context::create_from_window(&self.area.get_window().unwrap());
                cr.set_source_rgb(0., 0., 0.);
                cr.paint();
            },
            Msg::Quit => gtk::main_quit(),
            _ => {},
        }
    }

    fn view(relm: RemoteRelm<Msg>, _model: &Self::Model) -> Self {
        let window = Window::new(WindowType::Toplevel);
        let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0);
        let button_box = gtk::ButtonBox::new(gtk::Orientation::Vertical);
        let pause_button = Button::new_with_label("Start");
        let random_button = Button::new_with_label("Randomize");
        let next_button = Button::new_with_label("Next");
        let clear_button = Button::new_with_label("Clear");
        let zoom_in_button = Button::new_with_label("Zoom in");
        let zoom_out_button = Button::new_with_label("Zoom out");
        let area = DrawingArea::new();
        let scroller = ScrolledWindow::new(None, None);
        scroller.set_size_request(600, 600);
        // disable auto-hide scrollbar
        scroller.set_overlay_scrolling(false);
        button_box.set_layout(gtk::ButtonBoxStyle::Start);

        button_box.pack_start(&pause_button, false, false, 0);
        button_box.pack_start(&next_button, false, false, 0);
        button_box.pack_start(&random_button, false, false, 0);
        button_box.pack_start(&clear_button, false, false, 0);
        button_box.pack_start(&zoom_in_button, false, false, 0);
        button_box.pack_start(&zoom_out_button, false, false, 0);
        scroller.add(&area);
        hbox.pack_start(&scroller, false, false, 0);
        hbox.pack_start(&button_box, false, false, 0);
        window.add(&hbox);
        window.set_title("Game of Life");
        window.show_all();

        connect!(relm, window, connect_delete_event(_, _) (Some(Msg::Quit), Inhibit(false)));

        //connect!(relm, area, connect_draw(_, cr) (Some(Msg::Draw(CairoContext(cr.clone()))), Inhibit(true)));
        /*
        {
            let stream = relm.stream().clone();
            area.connect_draw(move |this, cr| {
                let (msg, return_value) = {
                    let cr = CairoContext(cr.clone());
                    (Some(Msg::Draw(cr)), Inhibit(true))
                };
                let msg: Option<_> = msg.into();
                if let Some(msg) = msg {
                    println!("Before Emit");
                    stream.emit(msg);
                    println!("After Emit");
                }
                return_value
            });
        }
        */
        /*
        area.connect_draw(move |_, cr| {
            cr.set_source_surface();
            cr.set_source_rgb(0.5, 0.5, 0.5);
            cr.paint();
            Inhibit(true)
        });
        */
        Win {
            hbox: hbox,
            button_box: button_box,
            pause_button: pause_button,
            next_button: next_button,
            clear_button: clear_button,
            zoom_in_button: zoom_in_button,
            zoom_out_button: zoom_out_button,
            area: area,
            scroller: scroller,
            window: window,
        }
    }
}
<commit_msg>Remove commented code<commit_after>use ::*;
use relm::{Relm, RemoteRelm, Widget};
use gtk::prelude::*;
use gtk::{Window, WindowType, DrawingArea, Button, ScrolledWindow};
use tokio_core::reactor::Interval;
use std::time::Duration;

use map::*;

#[derive(Clone)]
pub struct Model {}

#[derive(Clone)]
pub struct CairoSurface(cairo::Surface);
unsafe impl Send for CairoSurface {}

#[derive(SimpleMsg)]
pub enum Msg {
    Tick,
    Quit,
}

#[derive(Clone)]
pub struct Win {
    hbox: gtk::Box,
    button_box: gtk::ButtonBox,
    pause_button: Button,
    next_button: Button,
    clear_button: Button,
    zoom_in_button: Button,
    zoom_out_button: Button,
    area: DrawingArea,
    scroller: ScrolledWindow,
    window: Window,
}

impl Widget for Win {
    type Root = Window;
    type Model = Model;
    type Msg = Msg;

    fn root(&self) -> &Self::Root {
        &self.window
    }

    fn model() -> Self::Model {
        Model {}
    }

    fn subscriptions(relm: &Relm<Msg>) {
        let stream = Interval::new(Duration::from_millis(50), relm.handle()).unwrap();
        relm.connect_exec_ignore_err(stream, Msg::Tick);
    }

    fn update(&mut self, event: Msg, _model: &mut Self::Model) {
        match event {
            Msg::Tick => {
                use gdk::prelude::ContextExt;
                let cr = cairo::Context::create_from_window(&self.area.get_window().unwrap());
                cr.set_source_rgb(0., 0., 0.);
                cr.paint();
            },
            Msg::Quit => gtk::main_quit(),
            _ => {},
        }
    }

    fn view(relm: RemoteRelm<Msg>, _model: &Self::Model) -> Self {
        let window = Window::new(WindowType::Toplevel);
        let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0);
        let button_box = gtk::ButtonBox::new(gtk::Orientation::Vertical);
        let pause_button = Button::new_with_label("Start");
        let random_button = Button::new_with_label("Randomize");
        let next_button = Button::new_with_label("Next");
        let clear_button = Button::new_with_label("Clear");
        let zoom_in_button = Button::new_with_label("Zoom in");
        let zoom_out_button = Button::new_with_label("Zoom out");
        let area = DrawingArea::new();
        let scroller = ScrolledWindow::new(None, None);
        scroller.set_size_request(600, 600);
        // disable auto-hide scrollbar
        scroller.set_overlay_scrolling(false);
        button_box.set_layout(gtk::ButtonBoxStyle::Start);

        button_box.pack_start(&pause_button, false, false, 0);
        button_box.pack_start(&next_button, false, false, 0);
        button_box.pack_start(&random_button, false, false, 0);
        button_box.pack_start(&clear_button, false, false, 0);
        button_box.pack_start(&zoom_in_button, false, false, 0);
        button_box.pack_start(&zoom_out_button, false, false, 0);
        scroller.add(&area);
        hbox.pack_start(&scroller, false, false, 0);
        hbox.pack_start(&button_box, false, false, 0);
        window.add(&hbox);
        window.set_title("Game of Life");
        window.show_all();

        connect!(relm, window, connect_delete_event(_, _) (Some(Msg::Quit), Inhibit(false)));

        Win {
            hbox: hbox,
            button_box: button_box,
            pause_button: pause_button,
            next_button: next_button,
            clear_button: clear_button,
            zoom_in_button: zoom_in_button,
            zoom_out_button: zoom_out_button,
            area: area,
            scroller: scroller,
            window: window,
        }
    }
}
<|endoftext|>


<commit_before>use crate::{
    error::ParseError,
    stream::buf_reader::{Buffer, Bufferless, CombineBuffer},
};

use std::{
    fmt,
    io::{self, Read},
    pin::Pin,
};

#[derive(Debug)]
pub enum Error<E, P> {
    Parse(E),
    Io { position: P, error: io::Error },
}

impl<'a, P> From<Error<crate::easy::Errors<u8, &'a [u8], P>, P>>
    for crate::easy::Errors<u8, &'a [u8], P>
where
    P: Ord + Clone,
{
    fn from(e: Error<crate::easy::Errors<u8, &'a [u8], P>, P>) -> Self {
        match e {
            Error::Parse(e) => e,
            Error::Io { position, error } => {
                crate::easy::Errors::from_error(position, crate::easy::Error::Other(error.into()))
            }
        }
    }
}

impl<E, P> std::error::Error for Error<E, P>
where
    E: std::error::Error,
    P: fmt::Display + fmt::Debug,
{
}

impl<E: fmt::Display, P: fmt::Display> fmt::Display for Error<E, P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Parse(e) => e.fmt(f),
            Error::Io { position: _, error } => error.fmt(f),
        }
    }
}

#[derive(Default)]
/// Used together with the `decode!` macro
pub struct Decoder<S, P, C = Buffer> {
    position: P,
    state: S,
    buffer: C,
    end_of_input: bool,
}

impl<S, P> Decoder<S, P, Buffer>
where
    P: Default,
    S: Default,
{
    /// Constructs a new `Decoder` with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with `Decoder::buffer`
    pub fn new() -> Self {
        Decoder::default()
    }

    /// Constructs a new `Decoder` with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with `Decoder::buffer`
    pub fn new_buffer() -> Self {
        Decoder::new()
    }
}

impl<S, P> Decoder<S, P, Bufferless>
where
    P: Default,
    S: Default,
{
    /// Constructs a new `Decoder` without an internal buffer. Requires the read instance to be
    /// wrapped with combine's [`BufReader`][] instance to
    ///
    /// [`BufReader`]: stream/buf_reader/index.html
    pub fn new_bufferless() -> Self {
        Decoder::default()
    }
}

impl<S, P> Decoder<S, P> {
    pub fn buffer(&self) -> &[u8] {
        &self.buffer.0
    }
}

impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub fn advance<R>(&mut self, read: &mut R, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance(read, removed)
    }

    #[doc(hidden)]
    pub fn advance_pin<R>(&mut self, read: Pin<&mut R>, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance_pin(read, removed);
    }

    pub fn position(&self) -> &P {
        &self.position
    }

    #[doc(hidden)]
    pub fn __inner(&mut self) -> (&mut S, &mut P, &C, bool) {
        (
            &mut self.state,
            &mut self.position,
            &self.buffer,
            self.end_of_input,
        )
    }
}

impl<S, P, C> Decoder<S, P, C>
where
    C: ,
{
    #[doc(hidden)]
    pub fn __before_parse<R>(&mut self, mut reader: R) -> io::Result<()>
    where
        R: Read,
        C: crate::stream::buf_reader::CombineSyncRead<R>,
    {
        if self.buffer.extend_buf_sync(&mut reader)? == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-02")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_02<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_02_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_02_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_03<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_03_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_03_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "futures-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_async<R>(&mut self, reader: Pin<&mut R>) -> io::Result<()>
    where
        R: futures_io_03::AsyncRead,
        C: crate::stream::buf_reader::CombineAsyncRead<R>,
    {
        let copied = self.buffer.extend_buf(reader).await?;

        if copied == 0 {
            self.end_of_input = true;
        }
        Ok(())
    }
}
<commit_msg>fix decoder links<commit_after>use crate::{
    error::ParseError,
    stream::buf_reader::{Buffer, Bufferless, CombineBuffer},
};

use std::{
    fmt,
    io::{self, Read},
    pin::Pin,
};

#[derive(Debug)]
pub enum Error<E, P> {
    Parse(E),
    Io { position: P, error: io::Error },
}

impl<'a, P> From<Error<crate::easy::Errors<u8, &'a [u8], P>, P>>
    for crate::easy::Errors<u8, &'a [u8], P>
where
    P: Ord + Clone,
{
    fn from(e: Error<crate::easy::Errors<u8, &'a [u8], P>, P>) -> Self {
        match e {
            Error::Parse(e) => e,
            Error::Io { position, error } => {
                crate::easy::Errors::from_error(position, crate::easy::Error::Other(error.into()))
            }
        }
    }
}

impl<E, P> std::error::Error for Error<E, P>
where
    E: std::error::Error,
    P: fmt::Display + fmt::Debug,
{
}

impl<E: fmt::Display, P: fmt::Display> fmt::Display for Error<E, P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::Parse(e) => e.fmt(f),
            Error::Io { position: _, error } => error.fmt(f),
        }
    }
}

#[derive(Default)]
/// Used together with the `decode!` macro
pub struct Decoder<S, P, C = Buffer> {
    position: P,
    state: S,
    buffer: C,
    end_of_input: bool,
}

impl<S, P> Decoder<S, P, Buffer>
where
    P: Default,
    S: Default,
{
    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new() -> Self {
        Decoder::default()
    }

    /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to
    /// be used when decoding but there may be data left in the internal buffer after decoding
    /// (accessible with [`Decoder::buffer`])
    pub fn new_buffer() -> Self {
        Decoder::new()
    }
}

impl<S, P> Decoder<S, P, Bufferless>
where
    P: Default,
    S: Default,
{
    /// Constructs a new `Decoder` without an internal buffer. Requires the read instance to be
    /// wrapped with combine's [`BufReader`] instance to
    ///
    /// [`BufReader`]: super::buf_reader::BufReader
    pub fn new_bufferless() -> Self {
        Decoder::default()
    }
}

impl<S, P> Decoder<S, P> {
    pub fn buffer(&self) -> &[u8] {
        &self.buffer.0
    }
}

impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub fn advance<R>(&mut self, read: &mut R, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance(read, removed)
    }

    #[doc(hidden)]
    pub fn advance_pin<R>(&mut self, read: Pin<&mut R>, removed: usize)
    where
        C: CombineBuffer<R>,
    {
        // Remove the data we have parsed and adjust `removed` to be the amount of data we
        // committed from `self.reader`
        self.buffer.advance_pin(read, removed);
    }

    pub fn position(&self) -> &P {
        &self.position
    }

    #[doc(hidden)]
    pub fn __inner(&mut self) -> (&mut S, &mut P, &C, bool) {
        (
            &mut self.state,
            &mut self.position,
            &self.buffer,
            self.end_of_input,
        )
    }
}

impl<S, P, C> Decoder<S, P, C>
where
    C: ,
{
    #[doc(hidden)]
    pub fn __before_parse<R>(&mut self, mut reader: R) -> io::Result<()>
    where
        R: Read,
        C: crate::stream::buf_reader::CombineSyncRead<R>,
    {
        if self.buffer.extend_buf_sync(&mut reader)? == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-02")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_02<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_02_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_02_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "tokio-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_tokio_03<R>(&mut self, mut reader: Pin<&mut R>) -> io::Result<()>
    where
        R: tokio_03_dep::io::AsyncRead,
        C: crate::stream::buf_reader::CombineRead<R, dyn tokio_03_dep::io::AsyncRead>,
    {
        let copied =
            futures_util_03::future::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut()))
                .await?;
        if copied == 0 {
            self.end_of_input = true;
        }

        Ok(())
    }
}

#[cfg(feature = "futures-03")]
impl<S, P, C> Decoder<S, P, C> {
    #[doc(hidden)]
    pub async fn __before_parse_async<R>(&mut self, reader: Pin<&mut R>) -> io::Result<()>
    where
        R: futures_io_03::AsyncRead,
        C: crate::stream::buf_reader::CombineAsyncRead<R>,
    {
        let copied = self.buffer.extend_buf(reader).await?;

        if copied == 0 {
            self.end_of_input = true;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashSet,HashMap};
use uuid::Uuid;

use graphics::{ Graphics, ImageSize };
use graphics::math::{ Matrix2d };

use input::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
    // Set of sprites that should be removed once animations have finished.
    dead_sprites: HashSet<Uuid>,
}

impl<I: ImageSize> Scene<I> {
    /// Create a new scene
    pub fn new() -> Scene<I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
            dead_sprites: HashSet::new(),
        }
    }

    /// Update animation's state
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(id).unwrap();
                let (status, _) = a.event(e, &mut |args| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *args.state {
                            None => { start_state = args.action.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, args.dt)
                    };
                    *args.state = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if !new_animations.is_empty() {
                self.running.insert(id, new_animations);
            }
        }

        self.prune_dead_sprites();
    }

    fn prune_dead_sprites(&mut self) {
        if !self.dead_sprites.is_empty() {
            let mut to_remove = HashSet::new();

            for sprite_id in self.dead_sprites.iter() {
                let n = self.running_for_child(*sprite_id)
                    .expect("Assert failed: invalid internal state for dead_sprites");

                if n == 0 {
                    to_remove.insert(*sprite_id);
                }
            }

            for sprite_id in to_remove.iter() {
                self.remove_child(*sprite_id);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in &self.children {
            child.draw(t, b);
        }
    }

    /// Render this scene with tint
    pub fn draw_tinted<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B, c: [f32;3]) {
        for child in &self.children {
            child.draw_tinted(t,b,c)
        }
    }

    /// Register animation with sprite
    pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(&sprite_id) {
            for (i, &(ref b, _, _)) in animations.iter().enumerate() {
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            self.running.get_mut(&sprite_id).unwrap().remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in &self.running {
            total += animations.len();
        }
        total
    }

    /// Get the number of running animations for a sprite. If sprite does not
    /// exist, returns None.
    pub fn running_for_child(&self, sprite_id: Uuid) -> Option<usize> {
        if let Some(animations) = self.running.get(&sprite_id) {
            Some(animations.len())
        } else {
            if self.child(sprite_id).is_some() {
                Some(0)
            } else {
                None
            }
        }
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in &mut self.children {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.dead_sprites.remove(&id);
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Remove the child by `id` from the scene's children or grandchild once
    /// all of its animations have finished. If the child current has no
    /// animations, it is removed immediately. Children with paused animations
    /// will not be removed until the animations are resumed and completed.
    pub fn remove_child_when_done(&mut self, id: Uuid) {
        match self.running_for_child(id) {
            Some(n) => {
                if n == 0 {
                    self.remove_child(id);
                } else {
                    self.dead_sprites.insert(id);
                }
            },
            None => {}
        }
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in &self.children {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in &mut self.children {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }
}
<commit_msg>Add an accessor for a scene's children.<commit_after>use std::collections::{HashSet,HashMap};
use uuid::Uuid;

use graphics::{ Graphics, ImageSize };
use graphics::math::{ Matrix2d };

use input::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
    // Set of sprites that should be removed once animations have finished.
    dead_sprites: HashSet<Uuid>,
}

impl<I: ImageSize> Scene<I> {
    /// Create a new scene
    pub fn new() -> Scene<I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
            dead_sprites: HashSet::new(),
        }
    }

    /// Update animation's state
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(id).unwrap();
                let (status, _) = a.event(e, &mut |args| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *args.state {
                            None => { start_state = args.action.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, args.dt)
                    };
                    *args.state = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if !new_animations.is_empty() {
                self.running.insert(id, new_animations);
            }
        }

        self.prune_dead_sprites();
    }

    fn prune_dead_sprites(&mut self) {
        if !self.dead_sprites.is_empty() {
            let mut to_remove = HashSet::new();

            for sprite_id in self.dead_sprites.iter() {
                let n = self.running_for_child(*sprite_id)
                    .expect("Assert failed: invalid internal state for dead_sprites");

                if n == 0 {
                    to_remove.insert(*sprite_id);
                }
            }

            for sprite_id in to_remove.iter() {
                self.remove_child(*sprite_id);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in &self.children {
            child.draw(t, b);
        }
    }

    /// Render this scene with tint
    pub fn draw_tinted<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B, c: [f32;3]) {
        for child in &self.children {
            child.draw_tinted(t,b,c)
        }
    }

    /// Register animation with sprite
    pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(&sprite_id) {
            for (i, &(ref b, _, _)) in animations.iter().enumerate() {
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            self.running.get_mut(&sprite_id).unwrap().remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in &self.running {
            total += animations.len();
        }
        total
    }

    /// Get the number of running animations for a sprite. If sprite does not
    /// exist, returns None.
    pub fn running_for_child(&self, sprite_id: Uuid) -> Option<usize> {
        if let Some(animations) = self.running.get(&sprite_id) {
            Some(animations.len())
        } else {
            if self.child(sprite_id).is_some() {
                Some(0)
            } else {
                None
            }
        }
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in &mut self.children {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.dead_sprites.remove(&id);
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Remove the child by `id` from the scene's children or grandchild once
    /// all of its animations have finished. If the child current has no
    /// animations, it is removed immediately. Children with paused animations
    /// will not be removed until the animations are resumed and completed.
    pub fn remove_child_when_done(&mut self, id: Uuid) {
        match self.running_for_child(id) {
            Some(n) => {
                if n == 0 {
                    self.remove_child(id);
                } else {
                    self.dead_sprites.insert(id);
                }
            },
            None => {}
        }
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in &self.children {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in &mut self.children {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Get the list of top-level (non-child) sprites.
    #[inline(always)]
    pub fn children(&self) -> &Vec<Sprite<I>> {
        &self.children
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::os::unix::io::RawFd;
use std::option::Option;
use libc::{self, c_int, c_void};
use {Errno, Error, Result};
use ::unistd::Pid;

// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags!{
    pub struct CloneFlags: libc::c_int {
        CLONE_VM;
        CLONE_FS;
        CLONE_FILES;
        CLONE_SIGHAND;
        CLONE_PTRACE;
        CLONE_VFORK;
        CLONE_PARENT;
        CLONE_THREAD;
        CLONE_NEWNS;
        CLONE_SYSVSEM;
        CLONE_SETTLS;
        CLONE_PARENT_SETTID;
        CLONE_CHILD_CLEARTID;
        CLONE_DETACHED;
        CLONE_UNTRACED;
        CLONE_CHILD_SETTID;
        CLONE_NEWCGROUP;
        CLONE_NEWUTS;
        CLONE_NEWIPC;
        CLONE_NEWUSER;
        CLONE_NEWPID;
        CLONE_NEWNET;
        CLONE_IO;
    }
}

pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct CpuSet {
    cpu_set: libc::cpu_set_t,
}

impl CpuSet {
    pub fn new() -> CpuSet {
        CpuSet { cpu_set: unsafe { mem::zeroed() } }
    }

    pub fn is_set(&self, field: usize) -> Result<bool> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
        }
    }

    pub fn set(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
        }
    }

    pub fn unset(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
        }
    }
}

mod ffi {
    use libc::{c_void, c_int};

    pub type CloneCb = extern "C" fn(data: *const super::CloneCb) -> c_int;

    // We cannot give a proper #[repr(C)] to super::CloneCb
    #[allow(improper_ctypes)]
    extern "C" {
        // create a child process
        // doc: http://man7.org/linux/man-pages/man2/clone.2.html
        pub fn clone(cb: *const CloneCb,
                     child_stack: *mut c_void,
                     flags: c_int,
                     arg: *mut super::CloneCb,
                     ...)
                     -> c_int;
    }
}

pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
    let res = unsafe {
        libc::sched_setaffinity(pid.into(),
                                mem::size_of::<CpuSet>() as libc::size_t,
                                &cpuset.cpu_set)
    };

    Errno::result(res).map(drop)
}

pub fn clone(mut cb: CloneCb,
             stack: &mut [u8],
             flags: CloneFlags,
             signal: Option<c_int>)
             -> Result<Pid> {
    extern "C" fn callback(data: *mut CloneCb) -> c_int {
        let cb: &mut CloneCb = unsafe { &mut *data };
        (*cb)() as c_int
    }

    let res = unsafe {
        let combined = flags.bits() | signal.unwrap_or(0);
        let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
        let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
        ffi::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
                   ptr_aligned as *mut c_void,
                   combined,
                   &mut cb)
    };

    Errno::result(res).map(Pid::from_raw)
}

pub fn unshare(flags: CloneFlags) -> Result<()> {
    let res = unsafe { libc::unshare(flags.bits()) };

    Errno::result(res).map(drop)
}

pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
    let res = unsafe { libc::setns(fd, nstype.bits()) };

    Errno::result(res).map(drop)
}
<commit_msg>Use libc types for sched FFI<commit_after>use std::mem;
use std::os::unix::io::RawFd;
use std::option::Option;
use libc::{self, c_int, c_void};
use {Errno, Error, Result};
use ::unistd::Pid;

// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags!{
    pub struct CloneFlags: libc::c_int {
        CLONE_VM;
        CLONE_FS;
        CLONE_FILES;
        CLONE_SIGHAND;
        CLONE_PTRACE;
        CLONE_VFORK;
        CLONE_PARENT;
        CLONE_THREAD;
        CLONE_NEWNS;
        CLONE_SYSVSEM;
        CLONE_SETTLS;
        CLONE_PARENT_SETTID;
        CLONE_CHILD_CLEARTID;
        CLONE_DETACHED;
        CLONE_UNTRACED;
        CLONE_CHILD_SETTID;
        CLONE_NEWCGROUP;
        CLONE_NEWUTS;
        CLONE_NEWIPC;
        CLONE_NEWUSER;
        CLONE_NEWPID;
        CLONE_NEWNET;
        CLONE_IO;
    }
}

pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>;

#[repr(C)]
#[derive(Clone, Copy)]
pub struct CpuSet {
    cpu_set: libc::cpu_set_t,
}

impl CpuSet {
    pub fn new() -> CpuSet {
        CpuSet { cpu_set: unsafe { mem::zeroed() } }
    }

    pub fn is_set(&self, field: usize) -> Result<bool> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
        }
    }

    pub fn set(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
        }
    }

    pub fn unset(&mut self, field: usize) -> Result<()> {
        if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
            Err(Error::Sys(Errno::EINVAL))
        } else {
            Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
        }
    }
}

pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
    let res = unsafe {
        libc::sched_setaffinity(pid.into(),
                                mem::size_of::<CpuSet>() as libc::size_t,
                                &cpuset.cpu_set)
    };

    Errno::result(res).map(drop)
}

pub fn clone(mut cb: CloneCb,
             stack: &mut [u8],
             flags: CloneFlags,
             signal: Option<c_int>)
             -> Result<Pid> {
    extern "C" fn callback(data: *mut CloneCb) -> c_int {
        let cb: &mut CloneCb = unsafe { &mut *data };
        (*cb)() as c_int
    }

    let res = unsafe {
        let combined = flags.bits() | signal.unwrap_or(0);
        let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
        let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
        libc::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
                   ptr_aligned as *mut c_void,
                   combined,
                   &mut cb as *mut _ as *mut c_void)
    };

    Errno::result(res).map(Pid::from_raw)
}

pub fn unshare(flags: CloneFlags) -> Result<()> {
    let res = unsafe { libc::unshare(flags.bits()) };

    Errno::result(res).map(drop)
}

pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
    let res = unsafe { libc::setns(fd, nstype.bits()) };

    Errno::result(res).map(drop)
}
<|endoftext|>


<commit_before>use {TryRead, TryWrite};
use io::{self, PipeReader, PipeWriter};
use std::mem;
use std::os::unix::io::{RawFd, AsRawFd};

/*
 *
 * ===== Awakener =====
 *
 */

pub struct Awakener {
    reader: PipeReader,
    writer: PipeWriter,
}

impl Awakener {
    pub fn new() -> io::Result<Awakener> {
        let (rd, wr) = try!(io::pipe());

        Ok(Awakener {
            reader: rd,
            writer: wr
        })
    }

    pub fn as_raw_fd(&self) -> RawFd {
        self.reader.as_raw_fd()
    }

    pub fn wakeup(&self) -> io::Result<()> {
        // A hack, but such is life. PipeWriter is backed by a single FD, which
        // is thread safe.
        unsafe {
            let wr: &mut PipeWriter = mem::transmute(&self.writer);
            wr.write_slice(b"0x01").map(|_| ())
        }
    }

    pub fn cleanup(&self) {
        let mut buf = [0; 128];

        loop {
            // Also a bit hackish. It would be possible to split up the read /
            // write sides of the awakener, but that would be a more
            // significant refactor. A transmute here is safe.
            unsafe {
                let rd: &mut PipeReader = mem::transmute(&self.reader);

                // Consume data until all bytes are purged
                match rd.read_slice(&mut buf) {
                    Ok(Some(i)) if i > 0 => {},
                    _ => return,
                }
            }
        }
    }
}
<commit_msg>Rust nightly fix: remove invalid transmutes<commit_after>use {TryRead, TryWrite};
use io::{self, PipeReader, PipeWriter};
use std::mem;
use std::cell::UnsafeCell;
use std::os::unix::io::{RawFd, AsRawFd};

/*
 *
 * ===== Awakener =====
 *
 */

pub struct Awakener {
    reader: UnsafeCell<PipeReader>,
    writer: UnsafeCell<PipeWriter>,
}

impl Awakener {
    pub fn new() -> io::Result<Awakener> {
        let (rd, wr) = try!(io::pipe());

        Ok(Awakener {
            reader: UnsafeCell::new(rd),
            writer: UnsafeCell::new(wr),
        })
    }

    pub fn as_raw_fd(&self) -> RawFd {
        unsafe {
            let rd: &PipeReader = mem::transmute(self.reader.get());
            rd.as_raw_fd()
        }
    }

    pub fn wakeup(&self) -> io::Result<()> {
        // A hack, but such is life. PipeWriter is backed by a single FD, which
        // is thread safe.
        unsafe {
            let wr: &mut PipeWriter = mem::transmute(self.writer.get());
            wr.write_slice(b"0x01").map(|_| ())
        }
    }

    pub fn cleanup(&self) {
        let mut buf = [0; 128];

        loop {
            // Also a bit hackish. It would be possible to split up the read /
            // write sides of the awakener, but that would be a more
            // significant refactor. A transmute here is safe.
            unsafe {
                let rd: &mut PipeReader = mem::transmute(self.reader.get());

                // Consume data until all bytes are purged
                match rd.read_slice(&mut buf) {
                    Ok(Some(i)) if i > 0 => {},
                    _ => return,
                }
            }
        }
    }
}
<|endoftext|>