Skip to content

Commit f56713a

Browse files
authored
Merge branch 'godot-rust:master' into update-macos-image-runner
2 parents 3c01208 + a5f1404 commit f56713a

File tree

5 files changed

+67
-47
lines changed

5 files changed

+67
-47
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ jobs:
114114

115115
- name: linux
116116
os: ubuntu-22.04
117-
rust-toolchain: "1.85"
117+
rust-toolchain: "1.87"
118118
rust-special: -msrv
119119

120120
steps:

dodge-the-creeps/godot/Main.tscn

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,4 @@ stream = ExtResource("5")
4848
[node name="DeathSound" type="AudioStreamPlayer" parent="."]
4949
stream = ExtResource("6")
5050

51-
[connection signal="timeout" from="MobTimer" to="." method="on_mob_timer_timeout"]
52-
[connection signal="timeout" from="ScoreTimer" to="." method="on_score_timer_timeout"]
5351
[connection signal="timeout" from="StartTimer" to="." method="on_start_timer_timeout"]

dodge-the-creeps/rust/src/main_scene.rs

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{hud, mob, player};
22

3-
use godot::classes::{Marker2D, PathFollow2D, RigidBody2D, Timer};
3+
use godot::classes::{AudioStreamPlayer, Marker2D, PathFollow2D, RigidBody2D, Timer};
44
use godot::prelude::*;
55

66
use rand::Rng as _;
@@ -46,25 +46,42 @@ impl INode for Main {
4646
self.player
4747
.signals()
4848
.hit()
49-
.connect_obj(&main, Self::game_over);
49+
.connect_other(&main, Self::game_over);
5050

5151
// Connect Hud::start_game -> Main::new_game.
5252
self.hud
5353
.signals()
5454
.start_game()
55-
.connect_obj(&main, Self::new_game);
55+
.connect_other(&main, Self::new_game);
56+
57+
// Connect Main.ScoreTimer::timeout -> Main::on_score_timer_timeout.
58+
self.score_timer()
59+
.signals()
60+
.timeout()
61+
.connect_other(&main, Self::on_score_timer_timeout);
62+
63+
// Connect Main.MobTimer::timeout -> Main::on_mob_timer_timeout.
64+
self.mob_timer()
65+
.signals()
66+
.timeout()
67+
.connect_other(&main, Self::on_mob_timer_timeout);
68+
69+
// Main.StartTimer::timeout -> Main::on_start_timer_timeout is set up in the Editor's Inspector UI, but could be done here as well,
70+
// as follows. Note that signal handlers connected via Rust do not need a #[func] annotation, they can remain entirely visible to Godot.
71+
//
72+
// self.start_timer()
73+
// .signals()
74+
// .timeout()
75+
// .connect_other(&main, Self::on_start_timer_timeout);
5676
}
5777
}
5878

5979
#[godot_api]
6080
impl Main {
6181
// No #[func] here, this method is directly called from Rust (via type-safe signals).
6282
fn game_over(&mut self) {
63-
let mut score_timer = self.base().get_node_as::<Timer>("ScoreTimer");
64-
let mut mob_timer = self.base().get_node_as::<Timer>("MobTimer");
65-
66-
score_timer.stop();
67-
mob_timer.stop();
83+
self.score_timer().stop();
84+
self.mob_timer().stop();
6885

6986
self.hud.bind_mut().show_game_over();
7087

@@ -75,12 +92,11 @@ impl Main {
7592
// No #[func].
7693
pub fn new_game(&mut self) {
7794
let start_position = self.base().get_node_as::<Marker2D>("StartPosition");
78-
let mut start_timer = self.base().get_node_as::<Timer>("StartTimer");
7995

8096
self.score = 0;
8197

8298
self.player.bind_mut().start(start_position.get_position());
83-
start_timer.start();
99+
self.start_timer().start();
84100

85101
let hud = self.hud.bind_mut();
86102
hud.update_score(self.score);
@@ -89,22 +105,20 @@ impl Main {
89105
self.music.play();
90106
}
91107

92-
#[func]
93-
fn on_start_timer_timeout(&self) {
94-
let mut mob_timer = self.base().get_node_as::<Timer>("MobTimer");
95-
let mut score_timer = self.base().get_node_as::<Timer>("ScoreTimer");
96-
mob_timer.start();
97-
score_timer.start();
108+
#[func] // needed because connected in Editor UI (see ready).
109+
fn on_start_timer_timeout(&mut self) {
110+
self.mob_timer().start();
111+
self.score_timer().start();
98112
}
99113

100-
#[func]
114+
// No #[func], connected in pure Rust.
101115
fn on_score_timer_timeout(&mut self) {
102116
self.score += 1;
103117

104118
self.hud.bind_mut().update_score(self.score);
105119
}
106120

107-
#[func]
121+
// No #[func], connected in pure Rust.
108122
fn on_mob_timer_timeout(&mut self) {
109123
let mut mob_spawn_location = self
110124
.base()
@@ -134,4 +148,17 @@ impl Main {
134148

135149
mob.set_linear_velocity(Vector2::new(range, 0.0).rotated(real::from_f32(direction)));
136150
}
151+
152+
// These timers could also be stored as OnReady fields, but are now fetched via function for demonstration purposes.
153+
fn start_timer(&self) -> Gd<Timer> {
154+
self.base().get_node_as::<Timer>("StartTimer")
155+
}
156+
157+
fn score_timer(&self) -> Gd<Timer> {
158+
self.base().get_node_as::<Timer>("ScoreTimer")
159+
}
160+
161+
fn mob_timer(&self) -> Gd<Timer> {
162+
self.base().get_node_as::<Timer>("MobTimer")
163+
}
137164
}

dodge-the-creeps/rust/src/player.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, PhysicsBody2D};
1+
use godot::classes::{AnimatedSprite2D, Area2D, CollisionShape2D, IArea2D, Input};
22
use godot::prelude::*;
33

44
#[derive(GodotClass)]
@@ -17,7 +17,7 @@ impl Player {
1717
pub fn hit();
1818

1919
#[func]
20-
fn on_player_body_entered(&mut self, _body: Gd<PhysicsBody2D>) {
20+
fn on_player_body_entered(&mut self, _body: Gd<Node2D>) {
2121
self.base_mut().hide();
2222
self.signals().hit().emit();
2323

@@ -55,9 +55,15 @@ impl IArea2D for Player {
5555
let viewport = self.base().get_viewport_rect();
5656
self.screen_size = viewport.size;
5757
self.base_mut().hide();
58+
59+
// Signal setup
60+
self.signals()
61+
.body_entered()
62+
.connect_self(Self::on_player_body_entered);
5863
}
5964

60-
fn process(&mut self, delta: f64) {
65+
// `delta` can be f32 or f64; #[godot_api] macro converts transparently.
66+
fn process(&mut self, delta: f32) {
6167
let mut animated_sprite = self
6268
.base()
6369
.get_node_as::<AnimatedSprite2D>("AnimatedSprite2D");
@@ -100,7 +106,7 @@ impl IArea2D for Player {
100106
animated_sprite.stop();
101107
}
102108

103-
let change = velocity * real::from_f64(delta);
109+
let change = velocity * delta;
104110
let position = self.base().get_global_position() + change;
105111
let position = Vector2::new(
106112
position.x.clamp(0.0, self.screen_size.x),

hot-reload/rust/src/lib.rs

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,31 @@ struct HotReload;
1111

1212
#[gdextension]
1313
unsafe impl ExtensionLibrary for HotReload {
14-
fn on_level_init(_level: InitLevel) {
15-
println!("[Rust] Init level {:?}", _level);
14+
fn on_level_init(level: InitLevel) {
15+
println!("[Rust] Init level {level:?}");
1616
}
1717

18-
fn on_level_deinit(_level: InitLevel) {
19-
println!("[Rust] Deinit level {:?}", _level);
18+
fn on_level_deinit(level: InitLevel) {
19+
println!("[Rust] Deinit level {level:?}");
2020
}
2121
}
2222

2323
// ----------------------------------------------------------------------------------------------------------------------------------------------
2424

2525
/// A RustDoc comment appearing under the editor help docs.
2626
#[derive(GodotClass)]
27-
#[class(base=Node)]
27+
#[class(init, base=Node)]
2828
struct Reloadable {
2929
/// A planet!
3030
#[export]
31+
#[init(val = Planet::Earth)]
3132
favorite_planet: Planet,
3233
//
3334
// HOT-RELOAD: uncomment this to add a new exported field (also update init() below).
3435
// #[export]
3536
// some_string: GString,
3637
}
3738

38-
#[godot_api]
39-
impl INode for Reloadable {
40-
fn init(_base: Base<Self::Base>) -> Self {
41-
// HOT-RELOAD: change values to initialize with different defaults.
42-
Self {
43-
favorite_planet: Planet::Earth,
44-
//some_string: "Hello, world!".into(),
45-
}
46-
}
47-
}
48-
4939
#[godot_api]
5040
impl Reloadable {
5141
/// A function to return a number.
@@ -55,19 +45,18 @@ impl Reloadable {
5545
100
5646
}
5747

58-
/// Constructor from a string.
48+
// HOT-RELOAD: uncomment to make new function accessible.
49+
5950
#[func]
60-
fn from_string(s: GString) -> Gd<Self> {
61-
Gd::from_object(Reloadable {
62-
favorite_planet: Planet::from_godot(s),
63-
})
51+
fn get_planet(&self) -> Planet {
52+
self.favorite_planet
6453
}
6554
}
6655

6756
// ----------------------------------------------------------------------------------------------------------------------------------------------
6857

6958
/// A planet enum.
70-
#[derive(GodotConvert, Var, Export)]
59+
#[derive(GodotConvert, Var, Export, Copy, Clone, Debug)]
7160
#[godot(via = GString)]
7261
enum Planet {
7362
Earth,

0 commit comments

Comments
 (0)