-
Notifications
You must be signed in to change notification settings - Fork 20
Description
First of all, thanks for all the videos, examples and making fltk-rs!
I've been trying to learn Rust and write an application that uses FLTK and Speedy2D. Currently on the Speedy2D page the instructions for managing GL oneself is this:
let mut renderer = unsafe {
GLRenderer::new_for_gl_context((640, 480), |fn_name| {
window_context.get_proc_address(fn_name) as *const _
})
which is a bit different than what is in the fltk/Speedy2D demo. But I've managed to make a program run with this in Cargo.toml:
edition = "2024"
[dependencies]
fltk = { version = "^1.5", features = ["enable-glwindow"] }
speedy2d = { version = "2.1.0", default-features = false }
The problem is writing the glutwindow draw() function if it needs to move in data from a struct owned by self. A custom draw_on_glut(&mut self) function, which invokes Speedy2D, somewhat works but it's not always called when needed. I am unsure if packing the variables in std::rc, extending the glutwindow widget somehow or using a different layout is the way to go.
This example shows the structure I am currently at:
use fltk::{app::{self, event_key, Receiver, Sender}, enums::{Event, Key}, prelude::*, window::{self, Window}};
use speedy2d::dimen::Vector2;
fn main() {
let args: Vec<_> = std::env::args().collect();
let mut app = MyApp::build(args);
app.launch();
}
pub enum Message {
Up,
Down,
Left,
Right,
Reset,
GlutResized,
}
pub struct MyApp {
app: app::App,
tx: Sender<Message>,
rx: Receiver<Message>,
display: MyDisplay,
}
impl MyApp {
pub fn build(args: Vec<String>) -> Self {
let (tx, rx) = app::channel::<Message>();
let app = app::App::default();
let mut main_win = Window::default().with_size(800, 600);
main_win.make_resizable(true);
let glut_win = fltk::window::GlutWindow::default_fill();
glut_win.end();
main_win.end();
main_win.show();
let mut display: MyDisplay = MyDisplay::build(glut_win, tx);
display.draw_on_glut();
Self {
app,
tx,
rx,
display,
}
}
pub fn launch(&mut self) {
while self.app.wait() {
use Message::*;
if let Some(msg) = self.rx.recv() {
match msg {
Up => self.display.up(),
Down => self.display.down(),
Left => self.display.left(),
Right => self.display.right(),
Reset => self.display.reset(),
GlutResized => self.display.resize_glut(),
}
}
}
}
}
pub struct MyDisplay {
glut_win: window::GlutWindow,
renderer: speedy2d::GLRenderer,
xpos: f32, //example of field in struct used to draw circle
ypos: f32,
}
impl MyDisplay {
pub fn build(mut glut_win: fltk::window::GlutWindow, tx: app::Sender<Message>) -> Self {
let w = glut_win.width();
let h = glut_win.height();
let renderer = unsafe {
speedy2d::GLRenderer::new_for_gl_context((w as u32, h as u32), |fn_name| {
glut_win.get_proc_address(fn_name) as *const _
})}.expect("cannot connect glcontext");
glut_win.resize_callback(move|_sel, _xpos, _ypos, _wid, _hei| {
tx.send(Message::GlutResized);
});
glut_win.draw(|_| {
//make this work somehow
//have speedy2d renderer, graphics, draw_circle in here?
});
glut_win.handle(move |widget, event| {
match event {
Event::Focus => {
true
},
Event::KeyDown => {
match event_key() {
Key::Up => {
tx.send(Message::Up);
true
},
Key::Down => {
tx.send(Message::Down);
true
},
Key::Left => {
tx.send(Message::Left);
true
},
Key::Right => {
tx.send(Message::Right);
true
},
Key::Enter => {
tx.send(Message::Reset);
true
},
_ => false,
}
},
_ => false,
}
});
Self {
glut_win,
renderer,
xpos: 200.,
ypos: 100.,
}
}
pub fn resize_glut(&mut self) {
self.draw_on_glut();
}
pub fn draw_on_glut(&mut self) {
self.renderer.set_viewport_size_pixels(Vector2::new(self.glut_win.width() as u32, self.glut_win.height() as u32));
self.renderer.draw_frame(|graphics| {
graphics.clear_screen(speedy2d::color::Color::DARK_GRAY);
graphics.draw_circle((self.xpos, self.ypos), 50., speedy2d::color::Color::RED);
});
self.glut_win.flush(); //seems to need damage or flush to draw...
//self.glut_win.set_damage(true);
}
pub fn reset(&mut self) {
self.xpos = 300.;
self.ypos = 60.;
self.draw_on_glut();
}
pub fn up(&mut self) {
self.ypos -= 1.;
self.draw_on_glut();
}
pub fn down(&mut self) {
self.ypos += 1.;
self.draw_on_glut();
}
pub fn left(&mut self) {
self.xpos -= 1.;
self.draw_on_glut();
}
pub fn right(&mut self) {
self.xpos += 1.;
self.draw_on_glut();
}
}