kitgit

tirbofish/dropbear · commit

1adac6af0a0e7980d2d540fbb1305fbb36cf6aae

still broken, soon to be fixed :( note: fuck its a mess

Unverified

tk <4tkbytes@pm.me> · 2025-08-31 15:05

view full diff

diff --git a/Cargo.toml b/Cargo.toml
index 6255a1b..200086b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,7 +6,7 @@ package.repository = "https://github.com/4tkbytes/dropbear-engine"
 package.readme = "README.md"
 
 resolver = "3"
-members = ["dropbear-engine", "eucalyptus", "gleek", "redback-runtime"]
+members = ["dropbear-engine", "eucalyptus", "redback-runtime"]
 
 [workspace.dependencies]
 anyhow = { version = "1.0", features = ["backtrace"] }
@@ -43,11 +43,13 @@ rfd = "0.15.4"
 rhai = "1.22"
 ron = "0.10.1"
 russimp-ng = { version = "3.2.4", features = ["static-link"] }
+rustyscript = { version = "0.12" }
 serde = { version = "1.0.219", features = ["derive"] }
 spin_sleep = "1.3"
+specta = { version = "=2.0.0-rc.22", features = ["glam", "derive", "export"] }
+specta-typescript = "0.0.9"
 tokio = { version = "1", features = ["full"] }
 transform-gizmo-egui = { git = "https://github.com/4tkbytes/transform-gizmo"}
-ts-rs = "10.1"
 wgpu = "26"
 winit = { version = "0.30", features = [] }
 zip = "4.3"
diff --git a/dropbear-engine/Cargo.toml b/dropbear-engine/Cargo.toml
index 061ded4..860d7ed 100644
--- a/dropbear-engine/Cargo.toml
+++ b/dropbear-engine/Cargo.toml
@@ -34,7 +34,7 @@ hecs.workspace = true
 once_cell.workspace = true
 parking_lot.workspace = true
 lazy_static.workspace = true
-ts-rs.workspace = true
+specta.workspace = true
 
 [target.'cfg(not(target_os = "android"))'.dependencies]
 rfd.workspace = true
diff --git a/eucalyptus/Cargo.toml b/eucalyptus/Cargo.toml
index 13ccfcc..54ed5b5 100644
--- a/eucalyptus/Cargo.toml
+++ b/eucalyptus/Cargo.toml
@@ -42,7 +42,10 @@ clap = { workspace = true, optional = true }
 walkdir = { workspace = true, optional = true }
 zip = { workspace = true, optional = true }
 bytemuck = "1.23.2"
-ts-rs.workspace = true
+
+rustyscript.workspace = true
+specta.workspace = true
+specta-typescript.workspace = true
 
 [target.'cfg(not(target_os = "android"))'.dependencies]
 rfd = { workspace = true, optional = true }
@@ -108,4 +111,4 @@ data-only = [
 anyhow = "1.0"
 app_dirs2 = "2.5"
 reqwest = { version = "0.12", features = ["blocking"] }
-zip = "4.3"
\ No newline at end of file
+zip = "4.3"
diff --git a/eucalyptus/build.rs b/eucalyptus/build.rs
index 3078c4f..fd9e83f 100644
--- a/eucalyptus/build.rs
+++ b/eucalyptus/build.rs
@@ -2,6 +2,7 @@ use std::fs::{self, File};
 use std::io::Cursor;
 
 fn main() -> anyhow::Result<()> {
+    // todo: move this into the "setup" process
     let repo_zip_url = "https://github.com/4tkbytes/dropbear/archive/refs/heads/main.zip";
     let response = reqwest::blocking::get(repo_zip_url)
         .map_err(|e| anyhow::anyhow!("Failed to download repo zip: {}", e))?
diff --git a/eucalyptus/src/scripting/math.rs b/eucalyptus/src/scripting/math.rs
index d185836..b600ccf 100644
--- a/eucalyptus/src/scripting/math.rs
+++ b/eucalyptus/src/scripting/math.rs
@@ -1,61 +1,8 @@
-use rhai::*;
-use rhai::plugin::*;
+use rustyscript::{Module, Runtime};
 
-#[rhai::export_module]
-pub mod math_functions {
-    // Basic math
-    pub fn abs(x: f64) -> f64 { x.abs() }
-    pub fn sqrt(x: f64) -> f64 { x.sqrt() }
-    pub fn pow(x: f64, y: f64) -> f64 { x.powf(y) }
-    pub fn min(x: f64, y: f64) -> f64 { x.min(y) }
-    pub fn max(x: f64, y: f64) -> f64 { x.max(y) }
-    pub fn clamp(x: f64, min: f64, max: f64) -> f64 { x.clamp(min, max) }
-
-    // Trig functions
-    pub fn sin(x: f64) -> f64 { x.sin() }
-    pub fn cos(x: f64) -> f64 { x.cos() }
-    pub fn tan(x: f64) -> f64 { x.tan() }
-    pub fn asin(x: f64) -> f64 { x.asin() }
-    pub fn acos(x: f64) -> f64 { x.acos() }
-    pub fn atan(x: f64) -> f64 { x.atan() }
-    pub fn atan2(y: f64, x: f64) -> f64 { y.atan2(x) }
-
-    // Hyperbolic functions
-    pub fn sinh(x: f64) -> f64 { x.sinh() }
-    pub fn cosh(x: f64) -> f64 { x.cosh() }
-    pub fn tanh(x: f64) -> f64 { x.tanh() }
-
-    // Logarithmic and exponential
-    pub fn exp(x: f64) -> f64 { x.exp() }
-    pub fn ln(x: f64) -> f64 { x.ln() }
-    pub fn log10(x: f64) -> f64 { x.log10() }
-    pub fn log2(x: f64) -> f64 { x.log2() }
-
-    // Rounding functions
-    pub fn floor(x: f64) -> f64 { x.floor() }
-    pub fn ceil(x: f64) -> f64 { x.ceil() }
-    pub fn round(x: f64) -> f64 { x.round() }
-    pub fn trunc(x: f64) -> f64 { x.trunc() }
-    pub fn fract(x: f64) -> f64 { x.fract() }
-
-    // Conversion
-    pub fn to_radians(degrees: f64) -> f64 { degrees.to_radians() }
-    pub fn to_degrees(radians: f64) -> f64 { radians.to_degrees() }
-
-    // Utility functions
-    pub fn lerp(a: f64, b: f64, t: f64) -> f64 { a + (b - a) * t }
-    pub fn smoothstep(edge0: f64, edge1: f64, x: f64) -> f64 {
-        let t = ((x - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
-        t * t * (3.0 - 2.0 * t)
-    }
-
-    // Consts
-    pub const PI: f64 = std::f64::consts::PI;
-    pub const E: f64 = std::f64::consts::E;
-    pub const TAU: f64 = std::f64::consts::TAU;
-}
-
-pub fn register_math_functions(engine: &mut Engine) {
-    engine.register_static_module("math", exported_module!(math_functions).into());
+pub fn register_math_functions(runtime: &mut Runtime) -> anyhow::Result<()> {
+    // runtime.load_module_async(module)
+    let module = Module::load_dir("typescript")?;
+    runtime.load_modules(module, side_modules)
     log::info!("[Script] Initialised math module");
 }
\ No newline at end of file
diff --git a/eucalyptus/src/scripting/mod.rs b/eucalyptus/src/scripting/mod.rs
index 15cae7e..61c51ad 100644
--- a/eucalyptus/src/scripting/mod.rs
+++ b/eucalyptus/src/scripting/mod.rs
@@ -2,16 +2,19 @@ pub mod entity;
 pub mod math;
 pub mod input;
 
+use chrono::DateTime;
 use dropbear_engine::entity::{AdoptedEntity, Transform};
 use glam::{DQuat, DVec3};
 use hecs::World;
-use rhai::*;
+use rustyscript::{Runtime, RuntimeOptions};
+use specta::{Type, TypeCollection};
+use specta_typescript::Typescript;
 use std::path::PathBuf;
 use std::{collections::HashMap, fs};
 
 use crate::states::{EntityNode, ModelProperties, ScriptComponent, PROJECT, SOURCE};
 
-pub const TEMPLATE_SCRIPT: &'static str = include_str!("../template.rhai");
+pub const TEMPLATE_SCRIPT: &'static str = include_str!("../template.ts");
 
 pub enum ScriptAction {
     AttachScript {
@@ -156,79 +159,117 @@ pub fn attach_script_to_entity(
     Ok(())
 }
 
+// #[cfg(feature = "editor")]
+// pub fn generate_ts() -> anyhow::Result<()> {
+//     let mut types = TypeCollection::default();
+//     types.register::<Transform>();
+
+//     let utc: DateTime<Utc> = Utc::now();
+//     let header = format!("
+// // @generated by dropbear-engine on {} UTC time
+// // Hello there! This is the generated stubs for the Eucalyptus Editor scripting component. 
+// // This file purely exists for the LSP and for TypeScripts type safety. Running this library 
+// // most likely won't do anything, but go ahead and be my guest. 
+// // EDIT THIS LIBRARY AT YOUR OWN WILL. IT IS RECOMMENDED TO NOT TOUCH THIS FILE
+//     ", utc);
+    
+//     if let Ok(project) = PROJECT.read() {
+//         Typescript::new().header(header).export_to(project.project_path.clone().join("src/dropbear-engine.d.ts"), types)?;
+//     } else {
+//         anyhow::bail!("Unable to retain Project Config lock, could not generate typescript bindings");
+//     }
+//     Ok(())
+// }
+
 pub struct ScriptManager {
-    pub engine: rhai::Engine,
+    pub runtime: Runtime,
     compiled_scripts: HashMap<String, AST>,
     script_scopes: HashMap<hecs::Entity, Scope<'static>>,
 }
 
 impl ScriptManager {
-    pub fn new() -> Self {
-        let mut engine = rhai::Engine::new();
-
-        // REGISTER FUNCTIONS HERE
-        math::register_math_functions(&mut engine);
-        input::InputState::register_input_modules(&mut engine);
-        entity::register_model_props_module(&mut engine);
+    pub fn new() -> anyhow::Result<Self> {
+        let mut runtime = Runtime::new(RuntimeOptions::default())?;
         
-        engine.register_type_with_name::<Transform>("Transform");
-        engine.register_type_with_name::<DQuat>("Quaternion");
-
-        // transform
-        engine.register_fn("new_transform", Transform::new);
-        engine.register_get_set(
-            "position",
-            |t: &mut Transform| t.position,
-            |t: &mut Transform, pos: DVec3| t.position = pos,
-        );
-        engine.register_get_set(
-            "rotation",
-            |t: &mut Transform| t.rotation,
-            |t: &mut Transform, rot: DQuat| t.rotation = rot,
-        );
-        engine.register_get_set(
-            "scale",
-            |t: &mut Transform| t.scale,
-            |t: &mut Transform, scale: DVec3| t.scale = scale,
-        );
 
-        // vector methods
-        engine.register_type_with_name::<DVec3>("Vector3");
-        engine.register_fn("vec3", |x: f64, y: f64, z: f64| DVec3::new(x, y, z));
-        engine.register_get_set("x", |v: &mut DVec3| v.x, |v: &mut DVec3, x: f64| v.x = x);
-        engine.register_get_set("y", |v: &mut DVec3| v.y, |v: &mut DVec3, y: f64| v.y = y);
-        engine.register_get_set("z", |v: &mut DVec3| v.z, |v: &mut DVec3, z: f64| v.z = z);
-
-        // utils
-        engine.register_fn("log", |msg: &str| {
-            println!("[Script] {}", msg);
-        });
-        engine.register_fn("time", || {
-            std::time::SystemTime::now()
-                .duration_since(std::time::UNIX_EPOCH)
-                .unwrap()
-                .as_secs_f64()
-        });
-
-        // operators
-        engine.register_fn("<", |a: f64, b: f32| a < b as f64);
-        engine.register_fn("<=", |a: f64, b: f32| a <= b as f64);
-        engine.register_fn(">", |a: f64, b: f32| a > b as f64);
-        engine.register_fn(">=", |a: f64, b: f32| a >= b as f64);
-        engine.register_fn("==", |a: f64, b: f32| a == b as f64);
-        engine.register_fn("!=", |a: f64, b: f32| a != b as f64);
-
-        engine.register_fn("<", |a: f32, b: f64| (a as f64) < b);
-        engine.register_fn("<=", |a: f32, b: f64| (a as f64) <= b);
-        engine.register_fn(">", |a: f32, b: f64| (a as f64) > b);
-        engine.register_fn(">=", |a: f32, b: f64| (a as f64) >= b);
-        engine.register_fn("==", |a: f32, b: f64| (a as f64) == b);
-        engine.register_fn("!=", |a: f32, b: f64| (a as f64) != b);
-
-        // input
+        // // REGISTER FUNCTIONS HERE
+        // math::register_math_functions(&mut runtime);
+        // input::InputState::register_input_modules(&mut runtime);
+        // entity::register_model_props_module(&mut runtime);
+
+        // // register types used by scripts
+        // runtime.register_type_with_name::<Transform>("Transform");
+        // runtime.register_type_with_name::<DQuat>("Quaternion");
+        // runtime.register_type_with_name::<DVec3>("Vector3");
+
+        // runtime.mod
+
+        // // constructors / helpers (alias names to match helper.ts)
+        // runtime.register_function("createTransform", Transform::new);
+        // runtime.register_function("createVec3", |x: f64, y: f64, z: f64| DVec3::new(x, y, z));
+        // // keep the original alias if you used "vec3" elsewhere
+        // runtime.register_function("vec3", |x: f64, y: f64, z: f64| DVec3::new(x, y, z));
+
+        // runtime.register_function("createQuatIdentity", || DQuat::IDENTITY);
+        // // from-euler: adapt to your exact DQuat API if different
+        // runtime.register_function("createQuatFromEuler", |x: f64, y: f64, z: f64| {
+        //     // uses EulerRot::XYZ — adjust if your glam API differs
+        //     DQuat::from_euler(glam::EulerRot::XYZ, x, y, z)
+        // });
+
+        // // transform helpers: simple implementations that return an updated Transform
+        // runtime.register_function(
+        //     "transformTranslate",
+        //     |mut t: Transform, v: DVec3| {
+        //         t.position += v;
+        //         t
+        //     },
+        // );
+        // runtime.register_function(
+        //     "transformScale",
+        //     |mut t: Transform, s: DVec3| {
+        //         t.scale *= s;
+        //         t
+        //     },
+        // );
+        // runtime.register_function(
+        //     "transformMatrix",
+        //     |t: Transform| {
+        //         // return whatever representation your scripts expect (e.g. a 4x4 matrix type)
+        //         t.matrix() // replace with actual method if different
+        //     },
+        // );
+
+        // // axis rotations — simple wrappers that multiply quaternions
+        // runtime.register_function("transformRotateX", |mut t: Transform, a: f64| {
+        //     let r = DQuat::from_rotation_x(a);
+        //     t.rotation = r * t.rotation;
+        //     t
+        // });
+        // runtime.register_function("transformRotateY", |mut t: Transform, a: f64| {
+        //     let r = DQuat::from_rotation_y(a);
+        //     t.rotation = r * t.rotation;
+        //     t
+        // });
+        // runtime.register_function("transformRotateZ", |mut t: Transform, a: f64| {
+        //     let r = DQuat::from_rotation_z(a);
+        //     t.rotation = r * t.rotation;
+        //     t
+        // });
+
+        // // utils already in your file — log and time
+        // runtime.register_function("log", |msg: String| {
+        //     println!("[Script] {}", msg);
+        // });
+        // runtime.register_function("time", || {
+        //     std::time::SystemTime::now()
+        //         .duration_since(std::time::UNIX_EPOCH)
+        //         .unwrap()
+        //         .as_secs_f64()
+        // });
 
         Self {
-            engine,
+            runtime,
             compiled_scripts: HashMap::new(),
             script_scopes: HashMap::new(),
         }
diff --git a/eucalyptus/src/template.rhai b/eucalyptus/src/template.rhai
deleted file mode 100644
index 3b9acee..0000000
--- a/eucalyptus/src/template.rhai
+++ /dev/null
@@ -1,20 +0,0 @@
-// Docs:
-// https://github.com/4tkbytes/dropbear/blob/main/docs/README.md
-
-fn init() {
-    print("Script initialised!");
-    // Access the entity's transform
-    // transform.position.x = 0.0;
-}
-
-fn update(dt) {
-    // Example: rotate the entity
-    // let rotation_speed = 1.0;
-    // transform.position.x = sin(time()) * 2.0;
-    // transform.position.y = cos(time()) * 2.0;
-    
-    // Example: log every second
-    // if (time() % 1.0 < dt) {
-    //     print("Entity position: " + transform.position.x + ", " + transform.position.y + ", " + transform.position.z);
-    // }
-}
\ No newline at end of file
diff --git a/eucalyptus/src/template.ts b/eucalyptus/src/template.ts
new file mode 100644
index 0000000..8826b52
--- /dev/null
+++ b/eucalyptus/src/template.ts
@@ -0,0 +1 @@
+// todo
\ No newline at end of file
diff --git a/eucalyptus/src/typescript/helper.ts b/eucalyptus/src/typescript/helper.ts
new file mode 100644
index 0000000..a49aca5
--- /dev/null
+++ b/eucalyptus/src/typescript/helper.ts
@@ -0,0 +1,46 @@
+// Modules for the dropbear-engine scripting component
+
+type TransformT = any;
+type Vec3T = any;
+type QuatT = any;
+
+function hostFn(name: string) {
+    const fn = (globalThis as any)[name];
+    if (typeof fn !== "function") {
+        throw new Error(`Host function ${name}() is not available. Make sure the runtime exposes it.`);
+    }
+    return fn;
+}
+
+const Transform = {
+    create: (): TransformT => hostFn("createTransform")(),
+    translate: (transform: TransformT, translation: [number, number, number] | number[]): TransformT =>
+        hostFn("transformTranslate")(transform, translation),
+    rotateX: (transform: TransformT, angle: number): TransformT =>
+        hostFn("transformRotateX")(transform, angle),
+    rotateY: (transform: TransformT, angle: number): TransformT =>
+        hostFn("transformRotateY")(transform, angle),
+    rotateZ: (transform: TransformT, angle: number): TransformT =>
+        hostFn("transformRotateZ")(transform, angle),
+    scale: (transform: TransformT, scale: number | [number, number, number]): TransformT =>
+        hostFn("transformScale")(transform, scale),
+    matrix: (transform: TransformT): TransformT => hostFn("transformMatrix")(transform),
+};
+
+const Vec3 = {
+    create: (x = 0, y = 0, z = 0): Vec3T => hostFn("createVec3")(x, y, z),
+    zero: (): Vec3T => hostFn("createVec3")(0, 0, 0),
+    one: (): Vec3T => hostFn("createVec3")(1, 1, 1),
+};
+
+const Quaternion = {
+    identity: (): QuatT => hostFn("createQuatIdentity")(),
+    fromEuler: (x: number, y: number, z: number): QuatT => hostFn("createQuatFromEuler")(x, y, z),
+};
+
+// make global
+export { Transform, Vec3, Quaternion };
+
+globalThis.Transform = Transform;
+globalThis.Vec3 = Vec3;
+globalThis.Quaternion = Quaternion;
\ No newline at end of file