Skip to content

Commit

Permalink
Godot rust script now supports enums and custom types (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
TitanNano authored Aug 23, 2024
1 parent 7bb429d commit cac3707
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 79 deletions.
5 changes: 3 additions & 2 deletions native/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ rand = "0.8.5"
pomsky-macro = "0.11.0"
regex = "1.10.5"

godot-rust-script = { git = "https://github.com/titannano/godot-rust-script", rev = "91c51296bc47a99db4c632f8b50780bed3d512b2" }
godot-rust-script = { git = "https://github.com/titannano/godot-rust-script", rev = "c7ced77799330804c17f79663f234a69fe272f7e" }
13 changes: 5 additions & 8 deletions native/src/editor.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
mod building_imports;

use godot::{
builtin::Callable,
engine::{notify::NodeNotification, EditorPlugin, IEditorPlugin},
obj::{Base, Gd, WithBaseField},
register::{godot_api, GodotClass},
};
use godot::builtin::Callable;
use godot::engine::notify::NodeNotification;
use godot::engine::{EditorPlugin, IEditorPlugin};
use godot::obj::{Base, Gd, WithBaseField};
use godot::register::{godot_api, GodotClass};

use crate::util::logger;
use building_imports::SetupBuildingImports;

#[derive(GodotClass)]
Expand Down Expand Up @@ -37,7 +35,6 @@ impl IEditorPlugin for EditorExtension {

fn on_notification(&mut self, what: NodeNotification) {
if what == NodeNotification::PREDELETE {
logger::debug!("godots destructor was called for EditorExtension...");
self.setup_building_imports.clone().free();
}
}
Expand Down
2 changes: 1 addition & 1 deletion native/src/scripts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ mod world;

pub use spawner::*;

godot_rust_script::setup_library!();
godot_rust_script::define_script_root!();
49 changes: 42 additions & 7 deletions native/src/scripts/objects/building.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use godot::{
builtin::{math::ApproxEq, Array, Transform3D, Vector3},
engine::{MeshInstance3D, Node, Node3D, PackedScene, Time},
meta::ToGodot,
global::PropertyHint,
meta::{FromGodot, GodotConvert, ToGodot},
obj::{Gd, Inherits},
prelude::ConvertError,
tools::load,
};
use godot_rust_script::{godot_script_impl, CastToScript, GodotScript, RsRef};
use godot_rust_script::{godot_script_impl, CastToScript, GodotScript, GodotScriptExport, RsRef};
use rand::Rng;
use std::{any::Any, fmt::Debug};

Expand All @@ -21,6 +23,7 @@ trait BuildingFeature<N: Inherits<Node>>: Debug {
fn dispatch_notification(&mut self, _notification: BuildingNotification) {}
}

#[derive(Debug, Default)]
struct BuildingEventFlags(u8);

impl BuildingEventFlags {
Expand All @@ -29,6 +32,40 @@ impl BuildingEventFlags {
}
}

impl GodotConvert for BuildingEventFlags {
type Via = u8;
}

impl FromGodot for BuildingEventFlags {
fn try_from_godot(via: Self::Via) -> Result<Self, ConvertError> {
Ok(Self(via))
}
}

impl ToGodot for BuildingEventFlags {
fn to_godot(&self) -> Self::Via {
self.0
}
}

impl GodotScriptExport for BuildingEventFlags {
fn hint_string(_custom_hint: Option<PropertyHint>, custom_string: Option<String>) -> String {
if let Some(custom_string) = custom_string {
return custom_string;
}

String::from("Fire:1")
}

fn hint(custom: Option<PropertyHint>) -> PropertyHint {
if let Some(custom) = custom {
return custom;
}

PropertyHint::FLAGS
}
}

#[derive(Debug)]
struct Features<F: Debug + ?Sized>(Vec<Box<F>>);

Expand Down Expand Up @@ -200,8 +237,8 @@ impl<N: Inherits<Node>> BuildingFeature<N> for FireFeature {
#[derive(GodotScript, Debug)]
#[script(base = Node)]
struct Building {
#[export(flags = ["Fire:1"])]
pub events: u8,
#[export]
pub events: BuildingEventFlags,

#[export]
pub mesh: Option<Gd<MeshInstance3D>>,
Expand All @@ -218,14 +255,12 @@ struct Building {
#[godot_script_impl]
impl Building {
pub fn _ready(&mut self) {
let events = BuildingEventFlags(self.events);

self.tile_coords = (
self.tile_coords_array.get(0).unwrap_or(0),
self.tile_coords_array.get(1).unwrap_or(0),
);

if events.fire() {
if self.events.fire() {
if let Some(ref mesh) = self.mesh {
self.features
.push(Box::new(FireFeature::new(self.tile_coords, mesh)));
Expand Down
73 changes: 13 additions & 60 deletions native/src/scripts/objects/canon_upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,19 @@ use godot::{
engine::{GpuParticles3D, Node3D},
obj::Gd,
};
use godot_rust_script::{godot_script_impl, GodotScript};
use godot_rust_script::{godot_script_impl, GodotScript, GodotScriptEnum};

use crate::util::logger;

#[derive(Debug, Default)]
enum CanonMode {
#[derive(Debug, Default, GodotScriptEnum, Clone, Copy)]
#[script_enum(export)]
pub enum CanonMode {
#[default]
Inactive,
Water,
Teargas,
}

impl TryFrom<u8> for CanonMode {
type Error = anyhow::Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
let result = match value {
0 => Self::Inactive,
1 => Self::Water,
2 => Self::Teargas,
_ => {
bail!("Failed to parse cannon mode {}, invalid variant!", value);
}
};

Ok(result)
}
}

impl From<CanonMode> for u8 {
fn from(value: CanonMode) -> Self {
match value {
CanonMode::Inactive => 0,
CanonMode::Water => 1,
CanonMode::Teargas => 2,
}
}
}

#[derive(Debug)]
enum CanonAction {
FirePrimary,
Expand All @@ -66,9 +40,9 @@ impl TryFrom<StringName> for CanonAction {
#[derive(GodotScript, Debug)]
#[script(base = Node3D)]
struct CanonUpgrade {
#[export(enum_options = ["Inactive", "Water", "Teargas"])]
#[export]
#[prop(set = Self::set_mode)]
pub mode: u8,
pub mode: CanonMode,

#[export]
pub water_jet: Option<Gd<GpuParticles3D>>,
Expand All @@ -82,28 +56,21 @@ impl CanonUpgrade {
self.set_mode(self.mode);
}

pub fn set_mode(&mut self, value: u8) {
pub fn set_mode(&mut self, value: CanonMode) {
self.mode = value;

if !self.base.is_node_ready() {
return;
}

let variant = CanonMode::try_from(value)
.context("Failed to parse mode!")
.unwrap_or_else(|err| {
logger::error!("{:?}", err);
CanonMode::default()
});

let Some(water_jet) = self.water_jet.as_mut() else {
logger::error!("Water jet node is not available!");
return;
};

water_jet.set_emitting(false);

match variant {
match value {
CanonMode::Inactive => (),
CanonMode::Water => water_jet.set_emitting(true),
CanonMode::Teargas => (),
Expand All @@ -119,22 +86,15 @@ impl CanonUpgrade {
}
};

let current_mode: CanonMode = match self.mode.try_into().context("Current mode is invalid")
{
Ok(mode) => mode,
Err(err) => {
logger::error!("{:?}", err);
return;
}
};
let current_mode = self.mode;

match (action, current_mode) {
(CanonAction::FirePrimary, CanonMode::Inactive) => {
self.set_mode(CanonMode::Water.into());
self.set_mode(CanonMode::Water);
}

(CanonAction::FireSecondary, CanonMode::Inactive) => {
self.set_mode(CanonMode::Teargas.into());
self.set_mode(CanonMode::Teargas);
}

_ => (),
Expand All @@ -150,19 +110,12 @@ impl CanonUpgrade {
}
};

let current_mode: CanonMode = match self.mode.try_into().context("Current mode is invalid")
{
Ok(mode) => mode,
Err(err) => {
logger::error!("{:?}", err);
return;
}
};
let current_mode: CanonMode = self.mode;

match (action, current_mode) {
(CanonAction::FireSecondary, CanonMode::Teargas)
| (CanonAction::FirePrimary, CanonMode::Water) => {
self.set_mode(CanonMode::Inactive.into());
self.set_mode(CanonMode::Inactive);
}

_ => (),
Expand Down

0 comments on commit cac3707

Please sign in to comment.