mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Split the Renderer
Created a Canvas + TextureCreator
This commit is contained in:
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)) => {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user