Split the Renderer

Created a Canvas + TextureCreator
This commit is contained in:
Andres
2017-05-02 07:30:18 +02:00
committed by Cobrand
parent d4f133c374
commit 19c5d12602
18 changed files with 844 additions and 596 deletions
+7 -6
View File
@@ -14,17 +14,18 @@ fn main() {
let window = video_subsystem.window("SDL2", 640, 480)
.position_centered().build().unwrap();
let mut renderer = window.renderer()
let mut canvas = window.into_canvas()
.accelerated().build().unwrap();
let texture_creator = canvas.texture_creator();
renderer.set_draw_color(sdl2::pixels::Color::RGBA(0,0,0,255));
canvas.set_draw_color(sdl2::pixels::Color::RGBA(0,0,0,255));
let mut timer = sdl_context.timer().unwrap();
let mut event_pump = sdl_context.event_pump().unwrap();
let temp_surface = sdl2::surface::Surface::load_bmp(Path::new("assets/animate.bmp")).unwrap();
let texture = renderer.create_texture_from_surface(&temp_surface).unwrap();
let texture = texture_creator.create_texture_from_surface(&temp_surface).unwrap();
let center = Point::new(320,240);
let mut source_rect = Rect::new(0, 0, 128, 82);
@@ -45,9 +46,9 @@ fn main() {
let ticks = timer.ticks();
source_rect.set_x((128 * ((ticks / 100) % 6) ) as i32);
renderer.clear();
renderer.copy_ex(&texture, Some(source_rect), Some(dest_rect), 10.0, None, true, false).unwrap();
renderer.present();
canvas.clear();
canvas.copy_ex(&texture, Some(source_rect), Some(dest_rect), 10.0, None, true, false).unwrap();
canvas.present();
std::thread::sleep(Duration::from_millis(100));
}
+4 -4
View File
@@ -14,11 +14,11 @@ pub fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
renderer.set_draw_color(Color::RGB(255, 0, 0));
renderer.clear();
renderer.present();
canvas.set_draw_color(Color::RGB(255, 0, 0));
canvas.clear();
canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
+8 -9
View File
@@ -17,7 +17,6 @@ macro_rules! rect(
);
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsys = sdl_context.video().unwrap();
let window = video_subsys.window("rust-sdl2_gfx: draw line & FPSManager", SCREEN_WIDTH, SCREEN_HEIGHT)
@@ -26,11 +25,11 @@ fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
renderer.set_draw_color(pixels::Color::RGB(0, 0, 0));
renderer.clear();
renderer.present();
canvas.set_draw_color(pixels::Color::RGB(0, 0, 0));
canvas.clear();
canvas.present();
let mut lastx = 0;
let mut lasty = 0;
@@ -50,20 +49,20 @@ fn main() {
} else if keycode == Keycode::Space {
println!("space down");
for i in 0..400 {
renderer.pixel(i as i16, i as i16, 0xFF000FFu32).unwrap();
canvas.pixel(i as i16, i as i16, 0xFF000FFu32).unwrap();
}
renderer.present();
canvas.present();
}
}
Event::MouseButtonDown {x, y, ..} => {
let color = pixels::Color::RGB(x as u8, y as u8, 255);
let _ = renderer.line(lastx, lasty, x as i16, y as i16, color);
let _ = canvas.line(lastx, lasty, x as i16, y as i16, color);
lastx = x as i16;
lasty = y as i16;
println!("mouse btn down at ({},{})", x, y);
renderer.present();
canvas.present();
}
_ => {}
+5 -4
View File
@@ -16,11 +16,12 @@ pub fn run(png: &Path) {
.build()
.unwrap();
let mut renderer = window.renderer().software().build().unwrap();
let texture = renderer.load_texture(png).unwrap();
let mut canvas = window.into_canvas().software().build().unwrap();
let texture_creator = canvas.texture_creator();
let texture = texture_creator.load_texture(png).unwrap();
renderer.copy(&texture, None, None).expect("Render failed");
renderer.present();
canvas.copy(&texture, None, None).expect("Render failed");
canvas.present();
'mainloop: loop {
for event in sdl_context.event_pump().unwrap().poll_iter() {
+5 -5
View File
@@ -15,11 +15,11 @@ pub fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
renderer.set_draw_color(Color::RGB(255, 0, 0));
renderer.clear();
renderer.present();
canvas.set_draw_color(Color::RGB(255, 0, 0));
canvas.clear();
canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
@@ -30,7 +30,7 @@ pub fn main() {
show_simple_message_box(MESSAGEBOX_ERROR,
"Some title",
"Some information inside the window",
renderer.window());
canvas.window());
match res {
Ok(_) => {}
Err(ShowMessageError::SdlError(string)) => {
+53
View File
@@ -0,0 +1,53 @@
extern crate sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Point, Rect};
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem
.window("rust-sdl2 resource-manager demo", 800, 600)
.position_centered()
.build()
.unwrap();
let mut canvas = window.into_canvas().software().build().unwrap();
let creator = canvas.texture_creator();
let mut texture = creator
.create_texture_target(PixelFormatEnum::RGBA8888, 400, 300)
.unwrap();
let mut angle = 0.0;
'mainloop: loop {
for event in sdl_context.event_pump().unwrap().poll_iter() {
match event {
Event::Quit { .. } => break 'mainloop,
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
_ => {}
}
}
angle = (angle + 0.5) % 360.;
{
let mut target = canvas.with_target(&mut texture).unwrap();
target.clear();
target.set_draw_color(Color::RGBA(255, 0, 0, 255));
target.fill_rect(Rect::new(0, 0, 400, 300)).unwrap();
} // <- drops the `target` so that the `canvas` can be used again
canvas.set_draw_color(Color::RGBA(0, 0, 0, 255));
let dst = Some(Rect::new(0, 0, 400, 300));
canvas.clear();
canvas
.copy_ex(&texture,
None,
dst,
angle,
Some(Point::new(400, 300)),
false,
false)
.unwrap();
canvas.present();
}
}
+7 -6
View File
@@ -15,9 +15,10 @@ pub fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
let texture_creator = canvas.texture_creator();
let mut texture = renderer.create_texture_streaming(
let mut texture = texture_creator.create_texture_streaming(
PixelFormatEnum::RGB24, 256, 256).unwrap();
// Create a red-green gradient
texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
@@ -31,11 +32,11 @@ pub fn main() {
}
}).unwrap();
renderer.clear();
renderer.copy(&texture, None, Some(Rect::new(100, 100, 256, 256))).unwrap();
renderer.copy_ex(&texture, None,
canvas.clear();
canvas.copy(&texture, None, Some(Rect::new(100, 100, 256, 256))).unwrap();
canvas.copy_ex(&texture, None,
Some(Rect::new(450, 100, 256, 256)), 30.0, None, false, false).unwrap();
renderer.present();
canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap();
+6 -5
View File
@@ -15,9 +15,10 @@ pub fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
let texture_creator = canvas.texture_creator();
let mut texture = renderer.create_texture_streaming(
let mut texture = texture_creator.create_texture_streaming(
PixelFormatEnum::IYUV, 256, 256).unwrap();
// Create a U-V gradient
texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
@@ -48,9 +49,9 @@ pub fn main() {
}
}).unwrap();
renderer.clear();
renderer.copy(&texture, None, Some(Rect::new(100, 100, 256, 256))).unwrap();
renderer.present();
canvas.clear();
canvas.copy(&texture, None, Some(Rect::new(100, 100, 256, 256))).unwrap();
canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap();
+153
View File
@@ -0,0 +1,153 @@
extern crate sdl2;
use sdl2::event::Event;
use sdl2::image::{LoadTexture, INIT_PNG, INIT_JPG};
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::render::{TextureCreator, Texture};
use sdl2::ttf::{Font, Sdl2TtfContext};
use std::env;
use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::rc::Rc;
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() < 3 {
println!("Usage: cargo run /path/to/image.(png|jpg) /path/to/font.(ttf|ttc|fon)")
} else {
let image_path = &args[1];
let font_path = &args[2];
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let font_context = sdl2::ttf::init().unwrap();
let _image_context = sdl2::image::init(INIT_PNG | INIT_JPG).unwrap();
let window = video_subsystem
.window("rust-sdl2 resource-manager demo", 800, 600)
.position_centered()
.build()
.unwrap();
let mut canvas = window.into_canvas().software().build().unwrap();
let texture_creator = canvas.texture_creator();
let mut texture_manager = TextureManager::new(&texture_creator);
let mut font_manager = FontManager::new(&font_context);
let details = FontDetails {
path: font_path.clone(),
size: 32,
};
'mainloop: loop {
for event in sdl_context.event_pump().unwrap().poll_iter() {
match event {
Event::Quit { .. } => break 'mainloop,
Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'mainloop,
_ => {}
}
}
// will load the image texture + font only once
let texture = texture_manager.load(image_path).unwrap();
let font = font_manager.load(&details).unwrap();
// not recommended to create a texture from the font each iteration
// but it is the simplest thing to do for this example
let surface = font.render("Hello Rust!")
.blended(Color::RGBA(255, 0, 0, 255))
.unwrap();
let font_texture = texture_creator
.create_texture_from_surface(&surface)
.unwrap();
//draw all
canvas.clear();
canvas.copy(&texture, None, None).unwrap();
canvas.copy(&font_texture, None, None).unwrap();
canvas.present();
}
}
}
type TextureManager<'l, T> = ResourceManager<'l, String, Texture<'l>, TextureCreator<T>>;
type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, Sdl2TtfContext>;
// Generic struct to cache any resource loaded by a ResourceLoader
pub struct ResourceManager<'l, K, R, L>
where K: Hash + Eq,
L: 'l + ResourceLoader<'l, R>
{
loader: &'l L,
cache: HashMap<K, Rc<R>>,
}
impl<'l, K, R, L> ResourceManager<'l, K, R, L>
where K: Hash + Eq,
L: ResourceLoader<'l, R>
{
pub fn new(loader: &'l L) -> Self {
ResourceManager {
cache: HashMap::new(),
loader: loader,
}
}
// Generics magic to allow a HashMap to use String as a key
// while allowing it to use &str for gets
pub fn load<D>(&mut self, details: &D) -> Result<Rc<R>, String>
where L: ResourceLoader<'l, R, Args = D>,
D: Eq + Hash + ?Sized,
K: Borrow<D> + for<'a> From<&'a D>
{
self.cache
.get(details)
.cloned()
.map_or_else(|| {
let resource = Rc::new(self.loader.load(details)?);
self.cache.insert(details.into(), resource.clone());
Ok(resource)
},
Ok)
}
}
// TextureCreator knows how to load Textures
impl<'l, T> ResourceLoader<'l, Texture<'l>> for TextureCreator<T> {
type Args = str;
fn load(&'l self, path: &str) -> Result<Texture, String> {
println!("LOADED A TEXTURE");
self.load_texture(path)
}
}
// Font Context knows how to load Fonts
impl<'l> ResourceLoader<'l, Font<'l, 'static>> for Sdl2TtfContext {
type Args = FontDetails;
fn load(&'l self, details: &FontDetails) -> Result<Font<'l, 'static>, String> {
println!("LOADED A FONT");
self.load_font(&details.path, details.size)
}
}
// Generic trait to Load any Resource Kind
pub trait ResourceLoader<'l, R> {
type Args: ?Sized;
fn load(&'l self, data: &Self::Args) -> Result<R, String>;
}
// Information needed to load a Font
#[derive(PartialEq, Eq, Hash)]
pub struct FontDetails {
pub path: String,
pub size: u16,
}
impl<'a> From<&'a FontDetails> for FontDetails {
fn from(details: &'a FontDetails) -> FontDetails {
FontDetails {
path: details.path.clone(),
size: details.size,
}
}
}
+8 -7
View File
@@ -54,19 +54,20 @@ fn run(font_path: &Path) {
.build()
.unwrap();
let mut renderer = window.renderer().build().unwrap();
let mut canvas = window.into_canvas().build().unwrap();
let texture_creator = canvas.texture_creator();
// Load a font
let mut font = ttf_context.load_font(font_path, 128).unwrap();
font.set_style(sdl2::ttf::STYLE_BOLD);
// render a surface, and convert it to a texture bound to the renderer
// render a surface, and convert it to a texture bound to the canvas
let surface = font.render("Hello Rust!")
.blended(Color::RGBA(255, 0, 0, 255)).unwrap();
let mut texture = renderer.create_texture_from_surface(&surface).unwrap();
let mut texture = texture_creator.create_texture_from_surface(&surface).unwrap();
renderer.set_draw_color(Color::RGBA(195, 217, 255, 255));
renderer.clear();
canvas.set_draw_color(Color::RGBA(195, 217, 255, 255));
canvas.clear();
let TextureQuery { width, height, .. } = texture.query();
@@ -74,8 +75,8 @@ fn run(font_path: &Path) {
let padding = 64;
let target = get_centered_rect(width, height, SCREEN_WIDTH - padding, SCREEN_HEIGHT - padding);
renderer.copy(&mut texture, None, Some(target)).unwrap();
renderer.present();
canvas.copy(&mut texture, None, Some(target)).unwrap();
canvas.present();
'mainloop: loop {
for event in sdl_context.event_pump().unwrap().poll_iter() {
+5 -5
View File
@@ -14,7 +14,7 @@ pub fn main() {
.build()
.unwrap();
let mut renderer = window.renderer().present_vsync().build().unwrap();
let mut canvas = window.into_canvas().present_vsync().build().unwrap();
let mut tick = 0;
@@ -31,7 +31,7 @@ pub fn main() {
{
// Update the window title.
let mut window = renderer.window_mut().unwrap();
let mut window = canvas.window_mut();
let position = window.position();
let size = window.size();
@@ -46,8 +46,8 @@ pub fn main() {
tick += 1;
}
renderer.set_draw_color(Color::RGB(0, 0, 0));
renderer.clear();
renderer.present();
canvas.set_draw_color(Color::RGB(0, 0, 0));
canvas.clear();
canvas.present();
}
}