1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use bitmap_font::BitmapFont;
use line_renderer::LineRenderer;
use text_renderer::TextRenderer;

use gfx;
use gfx::traits::*;
use gfx_texture;
use image;

#[derive(Debug)]
pub enum DebugRendererError {
    ShaderProgramError(gfx::ProgramError),
    BitmapFontTextureError,
}

impl From<gfx::ProgramError> for DebugRendererError {
    fn from(err: gfx::ProgramError) -> DebugRendererError {
        DebugRendererError::ShaderProgramError(err)
    }
}

pub struct DebugRenderer<R: gfx::Resources> {
    line_renderer: LineRenderer<R>,
    text_renderer: TextRenderer<R>,
}

impl<R: gfx::Resources> DebugRenderer<R> {

    pub fn from_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        canvas: &mut gfx::Canvas<O, D, F>,
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::handle::Texture<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {
        let (w, h) = canvas.output.get_size();
        DebugRenderer::new(&mut canvas.factory,
                           [w as u32, h as u32], initial_buffer_size,
                           bitmap_font, bitmap_font_texture)
    }

    pub fn new<
        F: Factory<R>,
    > (
        factory: &mut F,
        frame_size: [u32; 2],
        initial_buffer_size: usize,
        bitmap_font: Option<BitmapFont>,
        bitmap_font_texture: Option<gfx::handle::Texture<R>>,
    ) -> Result<DebugRenderer<R>, DebugRendererError> {
        let bitmap_font = match bitmap_font {
            Some(f) => f,
            None => BitmapFont::from_string(include_str!("../assets/notosans.fnt")).unwrap()
        };

        let bitmap_font_texture = match bitmap_font_texture {
            Some(t) => t,
            None => {
                if let image::DynamicImage::ImageRgba8(rgba_image) = image::load_from_memory_with_format(include_bytes!("../assets/notosans.png"), image::ImageFormat::PNG).unwrap() {
                    gfx_texture::Texture::from_image(factory, &rgba_image, false, false, false).handle()
                } else {
                    return Err(DebugRendererError::BitmapFontTextureError)
                }
            }
        };

        let line_renderer = try!(LineRenderer::new(factory, initial_buffer_size));
        let text_renderer = try!(TextRenderer::new(factory, frame_size, initial_buffer_size, bitmap_font, bitmap_font_texture));

        Ok(DebugRenderer {
            line_renderer: line_renderer,
            text_renderer: text_renderer,
        })
    }

    pub fn draw_line(&mut self, start: [f32; 3], end: [f32; 3], color: [f32; 4]) {
        self.line_renderer.draw_line(start, end, color);
    }

    pub fn draw_text_on_screen (
        &mut self,
        text: &str,
        screen_position: [i32; 2],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_on_screen(text, screen_position, color);
    }

    pub fn draw_text_at_position (
        &mut self,
        text: &str,
        world_position: [f32; 3],
        color: [f32; 4],
    ) {
        self.text_renderer.draw_text_at_position(text, world_position, color);
    }

    pub fn render_canvas<
        C: gfx::CommandBuffer<R>,
        F: Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    > (
        &mut self,
        canvas: &mut gfx::Canvas<O, D, F>,
        projection: [[f32; 4]; 4],
    ) {
        let mut stream = (&mut canvas.renderer, &canvas.output);
        self.render(&mut stream, &mut canvas.factory, projection);
    }

    pub fn render<
        S: gfx::Stream<R>,
        F: Factory<R>,
    > (
        &mut self,
        stream: &mut S,
        factory: &mut F,
        projection: [[f32; 4]; 4],
    ) {
        self.line_renderer.render(stream, factory, projection);
        self.text_renderer.render(stream, factory, projection);
    }
}