From 2747602b5acadbfe1ed438601c7e74461112c7a3 Mon Sep 17 00:00:00 2001 From: Max Oberaigner <58148625+moberer@users.noreply.github.com> Date: Thu, 18 Apr 2024 16:19:25 +0200 Subject: [PATCH] Extension: Refactor code into separate files (#64) Co-authored-by: Max Oberaigner --- rust/godot-plugin/src/lib.rs | 58 +++++++++++++------------------- rust/godot-plugin/src/signals.rs | 37 ++++++++++++++++++++ rust/godot-plugin/src/state.rs | 34 +++++++++++++++++++ 3 files changed, 94 insertions(+), 35 deletions(-) create mode 100644 rust/godot-plugin/src/signals.rs create mode 100644 rust/godot-plugin/src/state.rs diff --git a/rust/godot-plugin/src/lib.rs b/rust/godot-plugin/src/lib.rs index f6e9261..d94e553 100644 --- a/rust/godot-plugin/src/lib.rs +++ b/rust/godot-plugin/src/lib.rs @@ -1,20 +1,24 @@ +// Main entry point from the Godot side. +// +// Registers an Engine Singleton. +// Provides the Top-Level API to GDScript. + use godot::builtin::Array; -use godot::engine::Engine; use godot::prelude::*; -use std::sync::{Mutex, OnceLock}; - use compiler::Ast; use compiler::Compilable; +use godot::engine::Engine; + +use crate::signals::*; +use crate::state::*; + +mod signals; +mod state; // Register this plugin as a Godot Extension struct MyExtension {} -fn ast() -> &'static Mutex { - static AST: OnceLock> = OnceLock::new(); - AST.get_or_init(|| Mutex::new(Ast::default())) -} - #[gdextension] unsafe impl ExtensionLibrary for MyExtension { fn on_level_init(level: InitLevel) { @@ -59,6 +63,17 @@ impl Api { ast.to_godot_ast() } + #[func] + fn get_all_sprites() -> Array { + todo!("not implemented") + } + + #[func] + fn set_current_sprite(id: i64) { + let mut state = editor_state().lock().unwrap(); + state.set_current_sprite(id); + } + #[func] fn compile() -> GString { let ast = ast().lock().unwrap(); @@ -90,30 +105,3 @@ fn to_godot_ast(a: &compiler::ast::Statement) -> i64 { // ----------------------------------------------------------- // -enum GlobalSignals { - ScriptUpdated, -} - -fn global_notify(signal: GlobalSignals) { - let mut global_signals = get_autoload("/root/GlobalSignals"); - - let signal_name = match signal { - GlobalSignals::ScriptUpdated => "script_updated", - } - .into(); - - global_signals.emit_signal(signal_name, &[]); -} - -fn get_autoload(name: &str) -> Gd { - let name: NodePath = StringName::from(name).into(); - - Engine::singleton() - .get_main_loop() - .expect("could not get main loop") - .cast::() - .get_root() - .expect("could not get root of scene") - .get_node(name) - .expect("could not find element in scene") -} diff --git a/rust/godot-plugin/src/signals.rs b/rust/godot-plugin/src/signals.rs new file mode 100644 index 0000000..23abb1b --- /dev/null +++ b/rust/godot-plugin/src/signals.rs @@ -0,0 +1,37 @@ +// This file handles the uncanny mechanics of sending a notification signal +// (as implemented by godot) from this Godot Engine Singleton to +// +// the top-level "GlobalSignals" autoloaded Scene. +// From there the signals can be further dispached in GDScript +// by connecting to this signal. + +use godot::engine::Engine; +use godot::prelude::*; + +pub enum GlobalSignals { + ScriptUpdated, +} + +pub fn global_notify(signal: GlobalSignals) { + let mut global_signals = get_autoload("/root/GlobalSignals"); + + let signal_name = match signal { + GlobalSignals::ScriptUpdated => "script_updated", + } + .into(); + + global_signals.emit_signal(signal_name, &[]); +} + +fn get_autoload(name: &str) -> Gd { + let name: NodePath = StringName::from(name).into(); + + Engine::singleton() + .get_main_loop() + .expect("could not get main loop") + .cast::() + .get_root() + .expect("could not get root of scene") + .get_node(name) + .expect("could not find element in scene") +} diff --git a/rust/godot-plugin/src/state.rs b/rust/godot-plugin/src/state.rs new file mode 100644 index 0000000..38bee48 --- /dev/null +++ b/rust/godot-plugin/src/state.rs @@ -0,0 +1,34 @@ +// "Server-Side" state of the Godot Project. +// +// Keeps a hold of the currently selected project, +// script, etc. +// +// TODO: Rethink wheter this is really the best way to do this, +// or whether we should just send the full selector down with +// every call from the GDScript side. + +use std::sync::{Mutex, OnceLock}; + +use compiler::Ast; + +pub fn ast() -> &'static Mutex { + static AST: OnceLock> = OnceLock::new(); + AST.get_or_init(|| Mutex::new(Ast::default())) +} + +#[derive(Default)] +pub struct EditorState { + current_sprite: Option, +} + +impl EditorState { + pub fn set_current_sprite(&mut self, id: i64) { + // TODO: Validate whether sprite_id is valid! + self.current_sprite = Some(id); + } +} + +pub fn editor_state() -> &'static Mutex { + static EDITOR_STATE: OnceLock> = OnceLock::new(); + EDITOR_STATE.get_or_init(|| Mutex::new(EditorState::default())) +}