How to use Windowdescriptor in Bevy? - rust

use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(WindowDescriptor{
width: 140.0,
height:140.0,
title: "Game of Life".to_string(),
..Default::default()
})
.run();
}
I don't know why this isn't working and its showing the following compile-error
error[E0277]: the trait bound `bevy::prelude::WindowDescriptor: Resource` is not satisfied
--> src\main.rs:7:26
|
7 | .insert_resource(WindowDescriptor{
| __________---------------_^
| | |
| | required by a bound introduced by this call
8 | | width: 140.0,
9 | | height:140.0,
10 | | title: "Game of Life".to_string(),
11 | | ..Default::default()
12 | | })
| |_________^ the trait `Resource` is not implemented for `bevy::prelude::WindowDescriptor`
I was following this video and it works just fine in the video
I am learning how to use bevy game engine but when i pass windowdesciptor as an argument to the add_resource function and it shows me error

Since bevy 0.9
The WindowDescriptor settings have been moved from a resource to WindowPlugin::window
So your code should be:
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
window: WindowDescriptor {
width: 140.0,
height:140.0,
title: "Game of Life".to_string(),
..default()
},
..default()
}))
.run();
}

Related

Rust gloo_events : Nested eventlisteners

So, few months ago, i went on the journey of Rust and WASM.
The goal is to build a new generation free software WASM CMS to build websites implementing crypto and decentralized networking.
(See Fermyon Bartholomew, Locutus (rust version of Freenet), Holochain).
I want to build a business around that, so i will never drop this project. For those who are interested, help is welcome.
Anyway, i'm stuck on this problems since weeks, and i'm literally going crazy about it. Here is the problem:
For now i'm trying to make a rectangle selection tool, to simply draw empty rectangles on my canvas.
The mechanic is as follow, just three nested event listeners:
The first one is the onmousedown, registering the x/y position of the mouse click, and then adding the 2nd eventlistener
The second one is the onmousemove, adding the 3rd eventlistener if not already added, and then drawing/redrawing the rectangle
The third one is the oumouseup, setting the Point to None, and then removing itself and the onmousemove listeners
You can get the project at https://github.com/MojoMotion/canvas_rectangle_drawing_example (push requests are welcome).
Here is the main.rs:
use wasm_bindgen::JsCast;
use wasm_bindgen::UnwrapThrowExt;
//use gloo_console::log;
use gloo::events::EventListener;
use gloo_utils::document;
use web_sys::CanvasRenderingContext2d;
use web_sys::MouseEvent;
use std::cell::RefCell;
use std::rc::Rc;
struct Point {
x: f32,
y: f32,
}
fn main() {
let canvas = Rc::new(RefCell::new(document()
.get_element_by_id("canvas")
.unwrap()
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|_| ())
.unwrap()));
let context: CanvasRenderingContext2d = canvas
.borrow()
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<CanvasRenderingContext2d>()
.unwrap();
let p1 = Rc::new(RefCell::new(None));
let p2 = Rc::new(RefCell::new(None));
let mouse_down = EventListener::new(&*canvas.borrow_mut(), "mousedown", |event| {
let event = event.dyn_ref::<MouseEvent>().unwrap_throw();
*p1.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
let mouse_move = EventListener::new(&*canvas.borrow_mut(), "mousemove", |event| {
let event = event.dyn_ref::<MouseEvent>().unwrap_throw();
*p2.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
let mouse_up = EventListener::new(&*canvas.borrow_mut(), "mouseup", |_event| {
*p1.borrow_mut() = None;
*p2.borrow_mut() = None;
//context.begin_path();
//context.move_to(125., 125.);
//context.line_to(125., 45.);
//context.line_to(45., 125.);
//context.close_path();
//context.stroke();
});
mouse_up.forget();
});
mouse_move.forget();
});
mouse_down.forget();
}
Here is the errors :
error[E0597]: `p1` does not live long enough
--> src/main.rs:40:10
|
38 | let mouse_down = EventListener::new(&*canvas.borrow_mut(), "mousedown", |event| {
| ------- value captured here
39 | let event = event.dyn_ref::<MouseEvent>().unwrap_throw();
40 | *p1.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
| ^^ borrowed value does not live long enough
...
46 | let mouse_up = EventListener::new(&*canvas.borrow_mut(), "mouseup", |_event| {
| ____________________________-
47 | | *p1.borrow_mut() = None;
48 | | *p2.borrow_mut() = None;
49 | |
... |
56 | |
57 | | });
| |______________- argument requires that `p1` is borrowed for `'static`
...
64 | }
| - `p1` dropped here while still borrowed
error[E0597]: `canvas` does not live long enough
--> src/main.rs:42:47
|
38 | let mouse_down = EventListener::new(&*canvas.borrow_mut(), "mousedown", |event| {
| ------- value captured here
...
42 | let mouse_move = EventListener::new(&*canvas.borrow_mut(), "mousemove", |event| {
| - ^^^^^^ borrowed value does not live long enough
| __________________________|
| |
43 | | let event = event.dyn_ref::<MouseEvent>().unwrap_throw();
44 | | *p2.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
45 | |
... |
58 | | mouse_up.forget();
59 | | });
| |__________- argument requires that `canvas` is borrowed for `'static`
...
64 | }
| - `canvas` dropped here while still borrowed
error[E0597]: `p2` does not live long enough
--> src/main.rs:44:14
|
38 | let mouse_down = EventListener::new(&*canvas.borrow_mut(), "mousedown", |event| {
| ------- value captured here
...
44 | *p2.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
| ^^ borrowed value does not live long enough
45 |
46 | let mouse_up = EventListener::new(&*canvas.borrow_mut(), "mouseup", |_event| {
| ____________________________-
47 | | *p1.borrow_mut() = None;
48 | | *p2.borrow_mut() = None;
49 | |
... |
56 | |
57 | | });
| |______________- argument requires that `p2` is borrowed for `'static`
...
64 | }
| - `p2` dropped here while still borrowed
I guess the problem comes from the eventlistener.forget() method call that throws the borrowed variables out of scope (i guess by using Futures stuff).
I tried to get around the problem by understanding lifetimes and use the 'static lifetime, Rc and RefCell, which apparently does not lives long enough for eventlisteners.
My guess is that i should use eventlistener.callback() with Futures stuff (futures::stream::Stream, futures::channel::mpsc, std::pin::Pin, std::task::{Context, Poll}) following the official doc at https://docs.rs/gloo-events/latest/gloo_events/struct.EventListener.html, but because i'm not very experienced with javascript, i'm really lost trying connecting rust and javascript...
Right now i'm trying to make the code bit in javascript to have better understanding of js behavior and callback stuff... I will never surrender but in the meantime i would love to have some help... Also i think this is a really cool project so i if we can share the solution for free i think that's nice. Help me out!
You're passing around references to reference counted values, if this sentence seems a bit redundant it's because it is.
Or in other words Rc<T> is already a reference to T.
Just .clone() the Rc<T> if you need multiple and pass the cloned values.
let p1: Rc<RefCell<Option<Point>>> = Rc::new(RefCell::new(None));
let mouse_down = {
let p1 = p1.clone();
EventListener::new(canvas.borrow(), "mousedown", move |event| {
let event = event.dyn_ref::<MouseEvent>().unwrap_throw();
*p1.borrow_mut() = Some(Point { x: event.x() as f32, y: event.y() as f32 });
// ...
})
};
// further uses of p1

use an object inside a closure which is passed to a method of that object

i have a struct Screen with its implementation
pub struct Screen {
stdin: Stdin,
// types are irrelevant
stdout: MouseStdout,
}
impl Screen {
// ...
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
&self,
mut handler: F,
) {
let stdin = stdin();
for e in stdin.events() {
let e = e.unwrap();
match e {
Event::Key(Key::Ctrl('c')) => break,
_ => {
handler(&e);
},
}
}
}
}
and usage (which is wrong and know it)
let mut screen = Screen::new();
screen.init_screen();
screen.handle_keys_loop(|event| {
match event {
Event::Key(Key::Char('a')) => {
screen.println("hello there",15, 1, true);
},
_ => {}
}
});
screen.end_screen();
the error is
error[E0502]: cannot borrow `screen` as mutable because it is also borrowed as immutable
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ mutable borrow occurs here
| | |
| _____| immutable borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | println!("{} {} {} {}", "do something with a", 15, 1, true);
78 | | // tried to borrow as mutable
79 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
82 | | }
83 | | });
| |______- immutable borrow occurs here
and if i make self mut inside handle_keys_loop to get rid of cannot borrow screen as mutable because it is also borrowed as immutable
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
+ &mut self,
- &self
....
i get this error
error[E0499]: cannot borrow `screen` as mutable more than once at a time
--> src/bin/terminal.rs:74:29
|
74 | screen.handle_keys_loop(|event| {
| - ---------------- ^^^^^^^ second mutable borrow occurs here
| | |
| _____| first borrow later used by call
| |
75 | | match event {
76 | | Event::Key(Key::Char('a')) => {
77 | | screen.println("hello there",15, 1, true);
| | ------ second borrow occurs due to use of `screen` in closure
... |
80 | | }
81 | | });
| |______- first mutable borrow occurs here
what im trying to do: use the method handle_keys_loop of screen and pass screen inside the closure, which is passed to handle_keys_loop. basically, to use screen inside of screen.
how do i achieve that ?
some people told me to use RefCell, but that didnt work out very well, i got BorrowError.
i will use any workaround to just use screen inside the closure which is passed to screen's method.
thanks in advance.
One pattern I use to handle such a situation is to pass self: &mut Self back into the closure from handle and use that inside the closure. A simplified version of your code:
struct Screen {}
struct Event {}
impl Screen {
fn handle<F: FnMut(&mut Screen, Event)>(&mut self, mut handler: F) {
handler(self, Event {})
}
fn print(&mut self) {}
}
fn main() {
let mut screen = Screen {};
screen.handle(|screen, _event| screen.print());
screen.handle(|screen, _event| screen.print());
}
You can't do what you're trying to do because it violates Rust's rule that you can't mutate a value while something else has access to it.
However, your handle_keys_loop method doesn't even use self which means the &self parameter is redundant. There's no reason to give a function an argument it's not going to use (except when implementing a trait that requires it).
Just remove the argument:
pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
mut handler: F,
) {
And call it as Screen::handle_keys_loop(|event| { ... }).
Alternatively, make it a free function, external to Screen entirely, since it doesn't depend on Screen in any way.

How can I let one struct contains another struct and a value produced by that struct in Rust?

Actually the lexer's get_next_token will return a Token which has no relation to the lexer.
But the get_next_token method would borrow "mut self", so the compiler kept yelling "cannot return value referencing function parameter lexer".
How can I deal with it???????
// in impl lexer
fn get_next_token(&mut self) -> Token {
let mut result = None;
while self.current_char != None {
match self.current_char {
// editing result
}
}
if let Some(token) = result {
token
} else {
Token::new(EOF, Nil)
}
}
struct Intepreter<'a> {
lexer: Lexer<'a>,
current_token: Token<'a>
}
impl<'a> Intepreter<'a> {
fn new(mut lexer: Lexer<'a>) -> Intepreter {
let current_token = lexer.get_next_token();
Intepreter {
lexer: lexer,
current_token // error!
}
}
}
error[E0515]: cannot return value referencing function parameter `lexer`
--> src\main.rs:134:9
|
133 | let current_token = lexer.get_next_token();
| ---------------------- `lexer` is borrowed here
134 | / Intepreter {
135 | | lexer: lexer,
136 | | current_token
137 | | }
| |_________^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `lexer` because it is borrowed
--> src\main.rs:135:20
|
131 | impl<'a> Intepreter<'a> {
| -- lifetime `'a` defined here
132 | fn new(mut lexer: Lexer<'a>) -> Intepreter {
133 | let current_token = lexer.get_next_token();
| ---------------------- borrow of `lexer` occurs here
134 | / Intepreter {
135 | | lexer: lexer,
| | ^^^^^ move out of `lexer` occurs here
136 | | current_token
137 | | }
| |_________- returning this value requires that `lexer` is borrowed for `'a`

.pack_start() not working with gtk-rs Box

In the following code using gtk-rs I continuously get the error "method cannot be called on gtk4::Box due to unsatisfied trait bounds" for "hbox.pack_start". I have seen this method working in other gtk-rs applications and in the documentation, so I'm not sure what I am doing wrong.
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow, Button, Label};
fn main() {
let app = Application::builder()
.application_id("org.kresslein.rkcounter")
.build();
app.connect_activate(build_ui);
app.run();
}
fn build_ui(app: &Application) {
let hbox: gtk::Box = gtk::Box::new(gtk::Orientation::Horizontal, 10);
hbox.set_homogeneous(false);
let app_title = Label::new(Some("Counter"));
// Problematic line:
hbox.pack_start(&app_title, true, true, 0);
let window = ApplicationWindow::builder()
.application(app)
.title("Counter")
.child(&hbox)
.build();
// Present window
window.present();
}
Here is the full error message:
error[E0599]: the method `pack_start` exists for struct `gtk4::Box`, but its trait bounds were not satisfied
--> src/main.rs:47:10
|
47 | hbox.pack_start(&app_title);
| ^^^^^^^^^^ method cannot be called on `gtk4::Box` due to unsatisfied trait bounds
|
::: /home/ricky/.cargo/registry/src/github.com-1ecc6299db9ec823/gtk4-0.3.1/src/auto/box_.rs:27:1
|
27 | / glib::wrapper! {
28 | | #[doc(alias = "GtkBox")]
29 | | pub struct Box(Object<ffi::GtkBox, ffi::GtkBoxClass>) #extends Widget, #implements Accessible, Buildable, ConstraintTarget, Orientable;
30 | |
... |
33 | | }
34 | | }
| | -
| | |
| |_doesn't satisfy `gtk4::Box: IsA<CellLayout>`
| doesn't satisfy `gtk4::Box: gtk4::prelude::CellLayoutExt`
|
= note: the following trait bounds were not satisfied:
`gtk4::Box: IsA<CellLayout>`
which is required by `gtk4::Box: gtk4::prelude::CellLayoutExt`
For more information about this error, try `rustc --explain E0599`.

How to map or transform a vector of structs into another vector of structs?

Minimal Reproducible Example
pub struct User {
pub id: i32,
pub name: String,
pub match_id: i32,
}
pub struct Match {
pub id: i32,
pub name: String,
}
pub struct MatchWithUsers {
pub id: i32,
pub name: String,
pub users: Vec<User>,
}
fn main() {
let query_result: Vec<(Match, Option<User>)> = vec![
(
Match {
id: 1,
name: String::from("1st match"),
},
Some(User {
id: 1,
name: String::from("Jack"),
match_id: 1,
}),
),
(
Match {
id: 2,
name: String::from("2nd match"),
},
Some(User {
id: 2,
name: String::from("John"),
match_id: 2,
}),
),
(
Match {
id: 3,
name: String::from("3rd match"),
},
None,
),
];
let mut response: Vec<MatchWithUsers> = Vec::new();
for (m, u) in &query_result {
let existing_match = &response
.into_iter()
.find(|match_with_user| match_with_user.id == m.id);
match existing_match {
Some(found_match) => {
println!("Inser user into match: {}", found_match.name);
match u {
Some(mut user) => {
found_match.users.push(user);
}
None => println!("No users."),
}
}
None => {
println!("No existing match. Add to response.");
let user = u.as_ref().unwrap();
response.push(MatchWithUsers {
id: m.id,
name: m.name.clone(),
users: vec![],
});
}
}
}
println!("Response with: {}", response.len());
}
warning: unused variable: `user`
--> src/main.rs:69:21
|
69 | let user = u.as_ref().unwrap();
| ^^^^ help: consider prefixing with an underscore: `_user`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable does not need to be mutable
--> src/main.rs:61:26
|
61 | Some(mut user) => {
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0382]: use of moved value: `response`
--> src/main.rs:53:31
|
50 | let mut response: Vec<MatchWithUsers> = Vec::new();
| ------------ move occurs because `response` has type `std::vec::Vec<MatchWithUsers>`, which does not implement the `Copy` trait
...
53 | let existing_match = &response
| ^^^^^^^^ value moved here, in previous iteration of loop
error[E0507]: cannot move out of `u.0` which is behind a shared reference
--> src/main.rs:60:23
|
60 | match u {
| ^
61 | Some(mut user) => {
| --------
| |
| data moved here
| move occurs because `user` has type `User`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `found_match.users` as mutable, as it is behind a `&` reference
--> src/main.rs:62:25
|
62 | found_match.users.push(user);
| ^^^^^^^^^^^^^^^^^ `found_match` is a `&` reference, so the data it refers to cannot be borrowed as mutable
Playground
My problem
I have an API test project using Rocket and Diesel.
The following method does a Diesel query and should map the result to a JSON response. This is a response of all matches in the database with thier users. The users should be nested in each Match node.
My solution attempt
I create a vector.
Iterate in the query result;
Check if the match already exists in my vector, if it does, add the user info (coming from the query result) and add it to the users attribute in the current MatchWithUser, otherwise just add a struct (MatchWithUsers) to the vector.
pub fn show_all_matches2() -> Vec<MatchWithUsers> {
use schema::*;
let connection = establish_connection();
let query_result: Vec<(Match, Option<User>)> = matches::table
.left_join(users::table.on(users::match_id.eq(matches::id)))
.load(&connection)
.expect("Error loading matches");
let mut response: Vec<MatchWithUsers> = Vec::new();
for (m, u) in &query_result {
let existing_match = &response
.into_iter()
.find(|match_with_user| match_with_user.id == m.id);
match existing_match {
Some(mut found_match) => {
println!("Inser user into match: {}", found_match.name);
found_match.users.push(u.unwrap());
}
None => {
println!("No existing match. Add to response.");
let user = u.as_ref().unwrap();
response.push(MatchWithUsers {
id: m.id,
name: m.name.clone(),
players_count: m.players_count,
users: vec![User {
id: user.id,
name: user.name.clone(),
match_id: user.match_id,
}],
});
}
}
}
response
}
Structs
use crate::schema::{matches, users};
use serde::{Deserialize, Serialize};
#[derive(Queryable, Identifiable, Associations, Serialize, Deserialize)]
#[belongs_to(Match)]
#[table_name = "users"]
pub struct User {
pub id: i32,
pub name: String,
pub match_id: i32,
}
#[derive(Queryable, Identifiable, Serialize, Deserialize)]
#[table_name = "matches"]
pub struct Match {
pub id: i32,
pub name: String,
pub players_count: i32,
}
#[derive(Serialize, Deserialize)]
pub struct MatchWithUsers {
pub id: i32,
pub name: String,
pub players_count: i32,
pub users: Vec<User>,
}
Errors
$ cargo run
Compiling got_board_api_v3 v0.1.0 (/Users/tauil/Projects/got/got-board-api-v3)
error[E0382]: use of moved value: `response`
--> src/lib.rs:54:31
|
51 | let mut response: Vec<MatchWithUsers> = Vec::new();
| ------------ move occurs because `response` has type `std::vec::Vec<models::MatchWithUsers>`, which does not implement the `Copy` trait
...
54 | let existing_match = &response
| ^^^^^^^^ value moved here, in previous iteration of loop
error[E0507]: cannot move out of `existing_match.0` which is behind a shared reference
--> src/lib.rs:58:15
|
58 | match existing_match {
| ^^^^^^^^^^^^^^
59 | Some(mut found_match) => {
| ---------------
| |
| data moved here
| move occurs because `found_match` has type `models::MatchWithUsers`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `*u` which is behind a shared reference
--> src/lib.rs:61:40
|
61 | found_match.users.push(u.unwrap());
| ^
| |
| move occurs because `*u` has type `std::option::Option<models::User>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `u.as_ref()`
Query result in the Postgres client:
select * from matches left join users on matches.id = users.match_id;
id | name | players_count | id | name | match_id
----+---------------------+---------------+----+-----------+----------
1 | My first match | 3 | 1 | Rafael | 1
1 | My first match | 3 | 2 | Leandro | 1
1 | My first match | 3 | 3 | Vagner | 1
2 | Just a second match | 4 | 4 | Vagner | 2
2 | Just a second match | 4 | 5 | Leandro | 2
2 | Just a second match | 4 | 6 | Rafael | 2
2 | Just a second match | 4 | 7 | Wanderson | 2
3 | Amazing match | 6 | | |
(8 rows)
You can get a list of matches with the users associated with each match very easily if you use group_by from the itertools crate and if you ensure that your query results are sorted by match ID:
use itertools::Itertools; // 0.9.0
let response: Vec<_> = query_result
.into_iter()
// Note that this assumes that `query_result` is sorted
// by match id since `group_by` only considers
// consecutive matches.
.group_by(|(m, _)| m.id)
.into_iter()
.map(|(id, mut g)| {
// Now `g` is an iterator of `(Match, Option<User>)`
// where all the matches are the same. We take the
// first item to get the match information. Note
// that it is safe to unwrap here because `group_by`
// would never call us with an empty `g`.
let (m, u) = g.next().unwrap();
MatchWithUsers {
id: id,
name: m.name,
// We got the first user along with the match
// information, now we append the other users
// from the remaining items in `g`.
users: u
.into_iter()
.chain(g.flat_map(|(_, u)| u.into_iter()))
.collect(),
}
})
.collect();
Playground

Resources