tirbofish/dropbear · diff
significant progress, such as more work gradle and have generated a java native interface. still trying to get an idea of what might be best. for now, im merging back onto main and removing swift entirely.
Signature present but could not be verified.
Unverified
@@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="build" type="GradleRunConfiguration" factoryName="Gradle"> + <ExternalSystemSettings> + <option name="executionName" /> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="externalSystemIdString" value="GRADLE" /> + <option name="scriptParameters" value="" /> + <option name="taskDescriptions"> + <list /> + </option> + <option name="taskNames"> + <list> + <option value="build" /> + </list> + </option> + <option name="vmOptions" /> + </ExternalSystemSettings> + <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> + <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> + <DebugAllEnabled>false</DebugAllEnabled> + <RunAsTest>false</RunAsTest> + <method v="2" /> + </configuration> +</component> @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="generateJniHeaders" type="GradleRunConfiguration" factoryName="Gradle"> + <ExternalSystemSettings> + <option name="executionName" /> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="externalSystemIdString" value="GRADLE" /> + <option name="scriptParameters" value="" /> + <option name="taskDescriptions"> + <list /> + </option> + <option name="taskNames"> + <list> + <option value="generateJniHeaders" /> + </list> + </option> + <option name="vmOptions" /> + </ExternalSystemSettings> + <ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess> + <ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess> + <DebugAllEnabled>false</DebugAllEnabled> + <RunAsTest>false</RunAsTest> + <method v="2" /> + </configuration> +</component> @@ -60,7 +60,7 @@ backtrace = "0.3" gltf = "1" os_info = "3.12" rustc_version_runtime = "0.3" -libloading = "0.8" +jni = { version = "0.21", features = ["invocation"] } [workspace.dependencies.image] version = "0.25" @@ -11,6 +11,7 @@ repositories { dependencies { testImplementation(kotlin("test")) + implementation(kotlin("test")) } tasks.test { @@ -18,4 +19,26 @@ tasks.test { } kotlin { jvmToolchain(21) -} +} + +sourceSets { + main { + java.srcDirs("src/main/kotlin", "src/main/java") + } +} + +tasks.register<JavaCompile>("generateJniHeaders") { + val outputDir = layout.buildDirectory.dir("generated/jni-headers") + options.headerOutputDirectory.set(outputDir.get().asFile) + + classpath = files( + tasks.named("compileKotlin"), + tasks.named("compileJava") + ) + + source = fileTree("src/main/java") { + include("**/*.java") + } + + dependsOn("compileJava", "compileKotlin") +} @@ -25,8 +25,8 @@ serde.workspace = true winit.workspace = true tokio.workspace = true rayon.workspace = true -libloading.workspace = true -crossbeam-channel.workspace = true +jni.workspace = true +lazy_static = "1.5.0" [features] editor = [] @@ -2,7 +2,6 @@ use std::{ collections::{HashMap, HashSet}, time::{Duration, Instant}, }; -use serde::{Deserialize, Serialize}; use winit::{event::MouseButton, keyboard::KeyCode}; #[derive(Clone)] @@ -1,15 +1,12 @@ +mod java; + use crate::input::InputState; use crate::states::{EntityNode, PROJECT, SOURCE, ScriptComponent, Value}; use dropbear_engine::entity::{AdoptedEntity, Transform}; use hecs::{Entity, World}; use std::path::PathBuf; use std::{collections::HashMap, fs}; -use std::env::current_exe; -use glam::{Quat, Vec3}; -use libloading::{library_filename, Library}; -use once_cell::sync::Lazy; -use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; +use crate::scripting::java::JavaContext; pub const TEMPLATE_SCRIPT: &str = include_str!("../../resources/scripting/swift/sample.swift"); @@ -86,7 +83,7 @@ impl DropbearScriptingAPIContext { pub struct ScriptManager { script_context: DropbearScriptingAPIContext, - // library: Library, + java: JavaContext, } impl ScriptManager { @@ -95,11 +92,10 @@ impl ScriptManager { // let library = unsafe { Library::new(lib_path.clone())? }; let result = Self { - // library, + java: JavaContext::new()?, script_context: DropbearScriptingAPIContext::new(), }; - // log::info!("Loaded {} from {}", library_filename("dropbear").display(), lib_path.display()); log::debug!("Initialised ScriptManager"); Ok(result) } @@ -0,0 +1,20 @@ +use jni::{InitArgsBuilder, JNIVersion, JavaVM}; + +/// A dropbear wrapper for Java Virtual Machine (JVM) based functions +pub(crate) struct JavaContext { + jvm: JavaVM, +} + +impl JavaContext { + pub fn new() -> anyhow::Result<Self> { + let jvm_args = InitArgsBuilder::new() + .version(JNIVersion::V8) + .build()?; + + let jvm = JavaVM::new(jvm_args)?; + log::info!("Initialised JVM"); + Ok(Self { + jvm + }) + } +} @@ -11,7 +11,6 @@ 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; @@ -0,0 +1,28 @@ +package com.dropbear + +import com.dropbear.ffi.NativeEngine + +class DropbearEngine { + var nativeEngine: NativeEngine? = null + + // figure out how to create a new class + /** + * Fetches the currently active entity the script is attached to. + * + * If there is no entity this script is attached to, it will return + * a `null` in the form of a [Result] + */ + fun getActiveEntity(): Result<EntityRef> { + return Result.failure(Exception("Function not implemented")) + } + + /** + * Fetches an entity based on its label in the editor. + * + * If there is no entity under that label, it will return a + * `null` in the form of a [Result] + */ + fun getEntity(label: String): EntityRef? { + return null + } +} @@ -0,0 +1,27 @@ +package com.dropbear + +import com.dropbear.math.Vector3D + +/** + * A class to hold a reference to an entity. + * + * The dropbear engine interface is made in Rust, which uses a + * borrow checker paradigm, which heavily utilises immutability + * unless explicitly provided with the `mut` keyword. + * + * Because of this, the primary source of the World (place to store + * entities) is stored in Rust, and passing an EntityRef (which contains + * an ID) follows Rust's ideologies of passing references instead of the entire entity, + * which provides immutability. + * + * To edit any values part of the entity, take a look at the functions provided + * by [EntityRef], which will require a reference to [DropbearEngine] to push the commands. + */ +class EntityRef { + var label: String = "" + + /** + * Sets the position of the entity by a Vector + */ + fun setPosition(position: Vector3D, engine: DropbearEngine) {} +} @@ -0,0 +1,12 @@ +package com.dropbear + +class Example(override var engine: DropbearEngine) : RunnableScript { + override fun load() { + val entity = engine.getActiveEntity() + + } + + override fun update() { + TODO("Not yet implemented") + } +} @@ -1,5 +0,0 @@ -package com.dropbear - -fun main() { - println("Hello World!") -} @@ -0,0 +1,21 @@ +package com.dropbear + +/** + * The basic interface that all classes implement for the class to be run. + */ +interface RunnableScript { + var engine: DropbearEngine + /** + * A function that is run once during the lifetime of the entity. + * + * It can be used to set initial properties such as health and more. + * + * ALl classes that implement RunnableScript need to implement the load function. + */ + fun load() + + /** + * A function that is run every frame during the lifetime of the entity. + */ + fun update() +} @@ -0,0 +1,17 @@ +package com.dropbear.ffi; + +import com.dropbear.math.Transform; + +/** + * A class for dealing with native functions that is required by the Kotlin scripting + * and the Rust game engine. + */ +public class NativeEngine { + /** + * Fetches the transform of the entity by its label in the editor + * @param label The label of the entity + * @return The {@link Transform} component if the entity exists, null if not. + */ + public native Transform getTransformOfEntity(String label); + public native String getLabelOfAttachedEntity(); +} @@ -0,0 +1,11 @@ +package com.dropbear.math + +typealias QuaternionD = Quaternion<Double> + +class Quaternion<T: Number>(var x: T, var y: T, var z: T, var w: T) { + companion object { + fun identity(): Quaternion<Double> { + return Quaternion(0.0, 0.0, 0.0, 1.0) + } + } +} @@ -0,0 +1,9 @@ +package com.dropbear.math + +/** + * A class that keeps all the values of a Transform, which consists of a + * position ([Vector3D]), rotation([QuaternionD]) and a scale([Vector3D]). + */ +class Transform(var position: Vector3D, var rotation: QuaternionD, var scale: Vector3D) { + +} @@ -0,0 +1,29 @@ +package com.dropbear.math + +/** + * A class for holding a vector of `3` values of the same type. + */ +class Vector3<T: Number>(var x: T, var y: T, var z: T) { + companion object { + /** + * Creates a new [com.dropbear.math.Vector3] of type `T` with one value. + */ + fun <T: Number> uniform(value: T): Vector3<T> { + return Vector3(value, value, value) + } + + /** + * Creates a [com.dropbear.math.Vector3] of type [Double] filled with only zeroes + */ + fun zero(): Vector3<Double> { + return Vector3(0.0, 0.0, 0.0) + } + } + + fun asDoubleVector(): Vector3<Double> { + return Vector3(this.x.toDouble(), this.y.toDouble(), this.z.toDouble()) + } + +} + +typealias Vector3D = Vector3<Double>