tirbofish/dropbear · commit
f18fad43d671e22469d0ac391bcc120913d937d1
packing up for the night
Signature present but could not be verified.
Unverified
@@ -54,13 +54,12 @@ rayon = "1.11" flate2 = "1.1" reqwest = { version = "0.11", features = ["stream"] } tar = "0.4" -async-trait = "0.1" futures-util = "0.3" -boa_engine = "0.20" backtrace = "0.3" gltf = "1" os_info = "3.12" rustc_version_runtime = "0.3" +libloading = "0.8" [workspace.dependencies.image] version = "0.25" @@ -21,8 +21,8 @@ use crate::{ model::{self, Vertex}, }; -pub const NO_TEXTURE: &[u8] = include_bytes!("../../resources/no-texture.png"); -pub const NO_MODEL: &[u8] = include_bytes!("../../resources/error.glb"); +pub const NO_TEXTURE: &[u8] = include_bytes!("../../resources/textures/no-texture.png"); +pub const NO_MODEL: &[u8] = include_bytes!("../../resources/models/error.glb"); pub struct RenderContext<'a> { pub shared: Arc<SharedGraphicsContext>, @@ -526,7 +526,8 @@ impl App { log::info!("dropbear-engine running..."); let ad = app_dirs2::get_app_root(AppDataType::UserData, &config.app_info); if let Ok(path) = ad {log::info!("App data is stored at {}", path.display())}; - log::debug!("Additional nerdy stuff: {:#?}", rustc_version_runtime::version_meta()); + #[cfg(debug_assertions)] + log::debug!("Additional nerdy build stuff: {:?}", rustc_version_runtime::version_meta()); let event_loop = EventLoop::with_user_event().build()?; log::debug!("Created new event loop"); let mut app = Box::new(App::new(config, future_queue)); @@ -323,7 +323,7 @@ impl Light { }; if result.cube_lazy_model.is_none() { let lazy_model = Model::lazy_load( - include_bytes!("../../resources/cube.glb").to_vec(), + include_bytes!("../../resources/models/cube.glb").to_vec(), result.label.as_deref(), ) .await?; @@ -356,7 +356,7 @@ impl Light { let cube_model = Arc::new(Model::load_from_memory( graphics.clone(), - include_bytes!("../../resources/cube.glb").to_vec(), + include_bytes!("../../resources/models/cube.glb").to_vec(), label, ) .await @@ -16,7 +16,7 @@ use std::{mem, ops::Range, path::PathBuf}; use std::hash::{DefaultHasher, Hash, Hasher}; use wgpu::{BufferAddress, VertexAttribute, VertexBufferLayout, util::DeviceExt}; -pub const GREY_TEXTURE_BYTES: &[u8] = include_bytes!("../../resources/grey.png"); +pub const GREY_TEXTURE_BYTES: &[u8] = include_bytes!("../../resources/textures/grey.png"); lazy_static! { pub static ref MODEL_CACHE: Mutex<HashMap<String, Model>> = Mutex::new(HashMap::new()); @@ -23,9 +23,9 @@ parking_lot.workspace = true ron.workspace = true serde.workspace = true winit.workspace = true -# zip.workspace = true tokio.workspace = true rayon.workspace = true +libloading.workspace = true [features] editor = [] @@ -6,3 +6,4 @@ pub mod scripting; pub mod states; pub mod utils; pub mod spawn; +mod swift; @@ -3,10 +3,11 @@ use crate::states::{EntityNode, PROJECT, SOURCE, ScriptComponent, Value}; use dropbear_engine::entity::{AdoptedEntity, Transform}; use hecs::{Entity, World}; use std::path::PathBuf; -use std::str::FromStr; use std::{collections::HashMap, fs}; +use std::env::current_exe; +use libloading::{library_filename, Library}; -pub const TEMPLATE_SCRIPT: &str = include_str!("../../resources/template.ts"); +pub const TEMPLATE_SCRIPT: &str = include_str!("../../resources/scripting/swift/sample.swift"); #[derive(Clone)] pub struct DropbearScriptingAPIContext { @@ -81,14 +82,20 @@ impl DropbearScriptingAPIContext { pub struct ScriptManager { script_context: DropbearScriptingAPIContext, + library: Library, } impl ScriptManager { pub fn new() -> anyhow::Result<Self> { + let lib_path: PathBuf = Self::look_for_potential_library()?; + let library = unsafe { Library::new(lib_path.clone())? }; + let result = Self { + library, script_context: DropbearScriptingAPIContext::new(), }; + log::info!("Loaded {} from {}", library_filename("dropbear").display(), lib_path.display()); log::debug!("Initialised ScriptManager"); Ok(result) } @@ -99,7 +106,7 @@ impl ScriptManager { script_content: String, ) -> anyhow::Result<String> { - log::debug!("Loaded script [{}]", script_name); + log::debug!("Loaded library [{}]", script_name); Ok(script_name.clone()) } @@ -127,6 +134,40 @@ impl ScriptManager { Ok(()) } + + fn look_for_potential_library() -> anyhow::Result<PathBuf> { + // look for project path if editor feature is available + let root_path = { + #[cfg(feature = "editor")] + { + let _guard = PROJECT.read(); + _guard.project_path.clone() + } + + #[cfg(not(feature = "editor"))] + { + std::env::current_exe()?.parent().unwrap().to_path_buf() + } + }; + + let lib_file_name = library_filename("dropbear"); + + let potential_paths = vec![ + root_path.join(lib_file_name.clone()), // when packaged for shipping + // cant think of any other spots + // root_path.parent().unwrap().parent().unwrap().join("").join(lib_file_name.clone()), // during production of editor/engine + current_exe()?.parent().unwrap().parent().unwrap().parent().unwrap().to_path_buf().join(".build").join("debug").join(lib_file_name.clone()), + + ]; + + for path in potential_paths { + if path.exists() { + return Ok(path); + } + } + + anyhow::bail!("Unable to locate path for the dropbear dynamic library"); + } } pub fn move_script_to_src(script_path: &PathBuf) -> anyhow::Result<PathBuf> { @@ -0,0 +1,2 @@ +//! A module for dealing with the FFI between Swift dropbear-engine scripting API and +//! the game engine in Rust. @@ -0,0 +1 @@ +pub mod ffi; @@ -1,7 +1,7 @@ use crate::states::Node; -pub const PROTO_TEXTURE: &[u8] = include_bytes!("../../resources/proto.png"); +pub const PROTO_TEXTURE: &[u8] = include_bytes!("../../resources/textures/proto.png"); pub fn search_nodes_recursively<'a, F>(nodes: &'a [Node], matcher: &F, results: &mut Vec<&'a Node>) where @@ -36,9 +36,6 @@ walkdir.workspace = true zip.workspace = true tokio.workspace = true reqwest.workspace = true -flate2.workspace = true -tar.workspace = true -futures-util.workspace = true [target.'cfg(not(target_os = "android"))'.dependencies] rfd.workspace = true @@ -1,7 +1,21 @@ use std::fs::{self, File}; use std::io::Cursor; +use std::process::Command; fn main() -> anyhow::Result<()> { + let output = Command::new("git") + .args(["rev-parse", "--short=6", "HEAD"]) + .output() + .expect("Failed to execute git"); + + let git_hash = String::from_utf8(output.stdout).expect("Invalid UTF-8 in git output"); + let git_hash = git_hash.trim(); + + println!("cargo:rustc-env=GIT_HASH={}", git_hash); + + println!("cargo:rerun-if-changed=.git/HEAD"); + println!("cargo:rerun-if-changed=.git/refs/heads"); + // 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) @@ -602,15 +602,6 @@ impl InspectableComponent for ScriptComponent { .unwrap_or_default() .to_string_lossy() .to_string(); - let lib_path = &script_file.clone().parent().unwrap().join("dropbear.ts"); - if std::fs::read(lib_path).is_err() { - log::warn!("dropbear.ts library does not exist in project source directory, copying..."); - if let Err(e) = std::fs::write(lib_path, include_str!("../../../resources/dropbear.ts")) { - log::error!("Non-fatal error: Creating library file failed: {}", e); - } else { - log::info!("Wrote dropbear.ts library file!"); - } - }; *signal = Signal::ScriptAction(ScriptAction::AttachScript { script_path: script_file, script_name, @@ -623,17 +614,6 @@ impl InspectableComponent for ScriptComponent { .set_file_name(format!("{}_script.ts", label)) .save_file() { - // check if dropbear module exists - // todo: change this to an %APPDATA% file instead of to memory. - let lib_path = &script_path.clone().parent().unwrap().join("dropbear.ts"); - if std::fs::read(lib_path).is_err() { - log::warn!("dropbear.ts library does not exist in project source directory, copying..."); - if let Err(e) = std::fs::write(lib_path, include_str!("../../../resources/dropbear.ts")) { - log::error!("Non-fatal error: Creating library file failed: {}", e); - } else { - log::info!("Wrote dropbear.ts library file!"); - } - }; match std::fs::write(&script_path, TEMPLATE_SCRIPT) { Ok(_) => { let script_name = script_path @@ -104,7 +104,7 @@ pub struct Editor { } impl Editor { - pub fn new() -> Self { + pub fn new() -> anyhow::Result<Self> { let tabs = vec![EditorTab::Viewport]; let mut dock_state = DockState::new(tabs); @@ -139,7 +139,7 @@ impl Editor { } }); - Self { + Ok(Self { scene_command: SceneCommand::None, dock_state, texture_id: None, @@ -159,7 +159,7 @@ impl Editor { viewport_mode: ViewportMode::None, signal: Signal::None, undo_stack: Vec::new(), - script_manager: ScriptManager::new().unwrap(), + script_manager: ScriptManager::new()?, editor_state: EditorState::Editing, gizmo_mode: EnumSet::empty(), play_mode_backup: None, @@ -174,7 +174,7 @@ impl Editor { alt_pending_spawn_queue: vec![], world_receiver: None, dock_state_shared: None, - } + }) } fn double_key_pressed(&mut self, key: KeyCode) -> bool { @@ -11,6 +11,7 @@ mod signal; use clap::{Arg, Command}; use dropbear_engine::{scene, WindowConfiguration}; use std::{fs, path::PathBuf, rc::Rc}; +use std::panic::catch_unwind; use std::sync::Arc; use parking_lot::RwLock; use dropbear_engine::future::FutureQueue; @@ -28,6 +29,8 @@ async fn main() -> anyhow::Result<()> { to use the Eucalyptus editor on Android, please don't. Instead, use the `data-only` feature\ to use with dependencies or create your own game on Desktop. Sorry :(" ); + + dropbear_engine::panic::set_hook(); let matches = Command::new("eucalyptus-editor") .about("A visual game editor") .version(env!("CARGO_PKG_VERSION")) @@ -137,7 +140,7 @@ async fn main() -> anyhow::Result<()> { } None => { let config = WindowConfiguration { - title: "Eucalyptus, built with dropbear".into(), + title: format!("Eucalyptus, built with dropbear | Version {} on commit {}", env!("CARGO_PKG_VERSION"), env!("GIT_HASH")), windowed_mode: dropbear_engine::WindowedModes::Maximised, max_fps: dropbear_engine::App::NO_FPS_CAP, app_info: APP_INFO, @@ -146,7 +149,7 @@ async fn main() -> anyhow::Result<()> { let future_queue = Arc::new(FutureQueue::new()); let main_menu = Rc::new(RwLock::new(menu::MainMenu::new())); - let editor = Rc::new(RwLock::new(editor::Editor::new())); + let editor = Rc::new(RwLock::new(editor::Editor::new().unwrap_or_else(|e| panic!("Unable to initialise Eucalyptus Editor: {}", e)))); dropbear_engine::run_app!(config, Some(future_queue), |mut scene_manager, mut input_manager| { scene::add_scene_with_input( @@ -117,7 +117,7 @@ impl MainMenu { Ok(()) } "swift" => { - let package_template = include_str!("../../resources/Build.swift"); + let package_template = include_str!("../../resources/scripting/swift/Build.swift"); let package_template = package_template.replace("skibidi_toilet_goon_maxx", &project_name); // do not ask my why i chose skibidi_toilet_goon_maxx, it was just the first word i came up with. std::fs::write(path.join("Package.swift"), package_template)?; @@ -586,7 +586,7 @@ impl SignalController for Editor { egui_extras::install_image_loaders(ui.ctx()); ui.add(Image::from_bytes( "bytes://theres_nothing.jpg", - include_bytes!("../../resources/theres_nothing.jpg"), + include_bytes!("../../resources/textures/theres_nothing.jpg"), )); ui.label("Theres nothing..."); // scripting could be planned??? @@ -757,7 +757,7 @@ impl SignalController for Editor { } PendingSpawn2::Cube => { let pending = PendingSpawn { - asset_path: ResourceReference::from_bytes(include_bytes!("../../resources/cube.glb")), + asset_path: ResourceReference::from_bytes(include_bytes!("../../resources/models/cube.glb")), asset_name: "Default Cube".to_string(), transform: Default::default(), properties: Default::default(), @@ -1,30 +0,0 @@ -// swift-tools-version: 6.2 - -// Build system file for the dropbear-engine scripting API - -import PackageDescription - -let package = Package( - name: "skibidi_toilet_goon_maxx", - products: [ - .library( - name: "skibidi_toilet_goon_maxx", - type: .dynamic, // required as it will be linked to the final executable - targets: ["skibidi_toilet_goon_maxx"] - ), - ], - dependencies: [ - // add your own dependencies here! - // .package(url: "https://github.com/4tkbytes/dropbear", from: "0.0.0") - ], - targets: [ - .target( - name: "skibidi_toilet_goon_maxx", - path: "src", - exclude: [ - // exclude other items here - "source.eucc" - ] - ), - ] -) Binary files a/resources/cube.glb and /dev/null differ Binary files a/resources/cube_thumbnail.png and /dev/null differ Binary files a/resources/error.glb and /dev/null differ Binary files a/resources/grey.png and /dev/null differ Binary files /dev/null and b/resources/models/cube.glb differ Binary files /dev/null and b/resources/models/error.glb differ Binary files a/resources/no-texture.png and /dev/null differ Binary files a/resources/proto.png and /dev/null differ @@ -0,0 +1,30 @@ +// swift-tools-version: 6.2 + +// Build system file for the dropbear-engine scripting API + +import PackageDescription + +let package = Package( + name: "skibidi_toilet_goon_maxx", + products: [ + .library( + name: "skibidi_toilet_goon_maxx", + type: .dynamic, // required as it will be linked to the final executable + targets: ["skibidi_toilet_goon_maxx"] + ), + ], + dependencies: [ + // add your own dependencies here! + // .package(url: "https://github.com/4tkbytes/dropbear", from: "0.0.0") + ], + targets: [ + .target( + name: "skibidi_toilet_goon_maxx", + path: "src", + exclude: [ + // exclude other items here + "source.eucc" + ] + ), + ] +) @@ -0,0 +1,14 @@ +// dropbear engine script example, make the necessary changes + +import dropbear + +@ScriptEntry +class ChangeMyName: BaseScript { + override func onLoad() { + print("It's alive! It's alive! It's alive, it's alive, IT'S ALIVE!") + } + + override func onUpdate(dt: Float) { + print("And it's running at: \(1/dt) FPS?") + } +} Binary files /dev/null and b/resources/textures/cube_thumbnail.png differ Binary files /dev/null and b/resources/textures/grey.png differ Binary files /dev/null and b/resources/textures/no-texture.png differ Binary files /dev/null and b/resources/textures/proto.png differ Binary files /dev/null and b/resources/textures/theres_nothing.jpg differ Binary files a/resources/theres_nothing.jpg and /dev/null differ