Import Oxide engine (Stages 0–10) under MIT license
Full project snapshot migrated to new Gitea remote without history: engine, editor, physics, script, examples, tests, docs, and assets. Relicensed from GPLv3 to MIT and updated repo URLs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
//! The [`ScriptAsset`] — a loaded script's source — and its [`ScriptLoader`].
|
||||
//!
|
||||
//! A script lives on disk as a `.rhai` file under the project's `assets/scripts/`
|
||||
//! folder. Loading one yields a [`ScriptAsset`], which is just the source text
|
||||
//! plus its origin path; turning that text into something executable (a compiled
|
||||
//! `rhai` AST) is the job of the [`ScriptEngine`](crate::ScriptEngine), done at
|
||||
//! run time so a live edit can recompile without touching the asset plumbing.
|
||||
//!
|
||||
//! Keeping the asset as plain source (rather than a pre-compiled AST) is what
|
||||
//! makes hot-reload cheap: the file watcher swaps in fresh source on change and
|
||||
//! the host recompiles, with no engine-specific data baked into the asset cache.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use oxide_engine::asset::{AssetError, AssetLoader};
|
||||
|
||||
/// A loaded script: its source text and the path it came from.
|
||||
///
|
||||
/// This is the *asset* a [`Script`](crate::Script) component points at via an
|
||||
/// [`AssetRef<ScriptAsset>`](oxide_engine::asset::AssetRef). It is deliberately
|
||||
/// inert — holding source, not behaviour — so the same file can be recompiled on
|
||||
/// every live reload.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ScriptAsset {
|
||||
/// The script's source code.
|
||||
pub source: String,
|
||||
/// A human-readable name for diagnostics (the file stem, when loaded from
|
||||
/// disk), used in error messages and the script console.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl ScriptAsset {
|
||||
/// Builds an asset from in-memory source with the given diagnostic `name`.
|
||||
pub fn from_source(name: impl Into<String>, source: impl Into<String>) -> Self {
|
||||
Self {
|
||||
source: source.into(),
|
||||
name: name.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`AssetServer`](oxide_engine::asset::AssetServer) loader for `.rhai`
|
||||
/// scripts.
|
||||
///
|
||||
/// Registered by the [`ScriptModule`](crate::ScriptModule) (handles `.rhai`), so
|
||||
/// `assets.load::<ScriptAsset>("scripts/spin.rhai")` works once the module is
|
||||
/// added. It reads the file as UTF-8 and records the file stem as the asset's
|
||||
/// diagnostic name.
|
||||
pub struct ScriptLoader;
|
||||
|
||||
impl AssetLoader for ScriptLoader {
|
||||
type Asset = ScriptAsset;
|
||||
|
||||
fn extensions(&self) -> &'static [&'static str] {
|
||||
&["rhai"]
|
||||
}
|
||||
|
||||
fn load(&self, path: &Path) -> Result<ScriptAsset, AssetError> {
|
||||
let source = std::fs::read_to_string(path).map_err(|err| AssetError::Load {
|
||||
path: path.to_path_buf(),
|
||||
message: err.to_string(),
|
||||
})?;
|
||||
let name = path
|
||||
.file_stem()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("script")
|
||||
.to_string();
|
||||
Ok(ScriptAsset { source, name })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_source_keeps_name_and_text() {
|
||||
let a = ScriptAsset::from_source("spin", "let x = 1;");
|
||||
assert_eq!(a.name, "spin");
|
||||
assert_eq!(a.source, "let x = 1;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loader_reads_a_file_and_uses_the_stem_as_name() {
|
||||
let dir = std::env::temp_dir().join("oxide-script-loader-test");
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join("hello.rhai");
|
||||
std::fs::write(&path, "print(\"hi\");").unwrap();
|
||||
|
||||
let asset = ScriptLoader.load(&path).unwrap();
|
||||
assert_eq!(asset.name, "hello");
|
||||
assert!(asset.source.contains("print"));
|
||||
|
||||
std::fs::remove_file(&path).ok();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loader_claims_the_rhai_extension() {
|
||||
assert_eq!(ScriptLoader.extensions(), &["rhai"]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user