kitgit

tirbofish/dropbear · commit

9a88505ee88bc8e5b33702f180dccec4c18dbe4a

refactor + wip: changed to a more "abstract" component querying system, allowing for other developers to create their own components. also shuffled the code, and now got the commonMain working (to a documentable stage). todo: - implement jvmMain functions, implement JNI rust code and test to see if physics is working - if physics is working: - implement nativeLibMain and native rust code - if physics is NOT working: - fix up PhysicsState in rust and kotlin and see what the issue is, then resolve. - fix up magna-carta to support new system will i hit my deadline (basic physics working by new years)??? hopefully so...

Unverified

Thribhu K <4tkbytes@pm.me> · 2025-12-29 12:56

view full diff

diff --git a/build.gradle.kts b/build.gradle.kts
index 5f5eac2..91cb7c9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -32,18 +32,12 @@ val libPathProvider = provider {
         layout.projectDirectory.file("libs/$libName").asFile
     )
 
-    val foundFile = candidates.firstOrNull { it.exists() }
-    if (foundFile != null) {
-        foundFile.absolutePath
-    } else {
-        println("No Rust library exists")
-        ""
-    }
+    candidates.firstOrNull { it.exists() }?.absolutePath ?: ""
 }
 
 kotlin {
     jvm {
-        withJava()
+
     }
 
     val nativeTarget = when {
@@ -81,19 +75,16 @@ kotlin {
             binaries {
                 sharedLib {
                     baseName = "dropbear"
-
                     if (isLinux || isMacOs) {
                         linkerOpts("-L$nativeLibDir", "-l$nativeLibNameForLinking", "-Wl,-rpath,\\\$ORIGIN")
                     } else if (isMingwX64) {
-                        val importLibName = "$nativeLibNameForLinking.dll.lib"
-                        val importLibPath = file("$nativeLibDir/$importLibName").absolutePath
-                        linkerOpts(importLibPath)
+                        linkerOpts(file("$nativeLibDir/$nativeLibNameForLinking.dll.lib").absolutePath)
                     }
                 }
             }
         }
     } else {
-        println("Skipping native target configuration due to missing library path.")
+        println("WARNING: Rust library not found. Native compilation will skip linking against eucalyptus_core.")
         nativeTarget.apply {
             compilations.getByName("main") {
                 cinterops {
@@ -120,8 +111,9 @@ kotlin {
 
         jvmMain {
             kotlin.srcDirs("src/jvmMain/kotlin", "build/magna-carta")
-            dependencies {
 
+            dependencies {
+                implementation(kotlin("stdlib"))
             }
         }
     }
@@ -137,21 +129,41 @@ kotlin {
     }
 }
 
-tasks.register<JavaCompile>("generateJniHeaders") {
-    val outputDir = layout.buildDirectory.dir("generated/jni-headers")
-    options.headerOutputDirectory.set(outputDir.get().asFile)
+val extractJavaSources by tasks.registering(Copy::class) {
+    group = "jni"
+    description = "Copies .java files from jvmMain/kotlin to a temp directory for header generation"
+
+    from("src/jvmMain/kotlin")
+    include("**/*.java")
+    into(layout.buildDirectory.dir("tmp/java-jni-sources"))
+}
+
+val generateJniHeaders by tasks.registering(JavaCompile::class) {
+    group = "jni"
+    description = "Generates JNI headers from extracted Java files"
 
-    destinationDirectory.set(layout.buildDirectory.dir("classes/java/jni"))
+    dependsOn(extractJavaSources, "compileKotlinJvm")
+
+    source(extractJavaSources.map { it.destinationDir })
 
     classpath = files(
-        tasks.named("compileKotlinJvm"),
+        tasks.named("compileKotlinJvm").map { it.outputs.files },
+        configurations.named("jvmCompileClasspath")
     )
 
-    source = fileTree("src/jvmMain/java") {
-        include("**/*.java")
+    destinationDirectory.set(layout.buildDirectory.dir("tmp/jni-dummy-classes"))
+
+    val headerOutputDir = layout.buildDirectory.dir("generated/jni-headers")
+    options.headerOutputDirectory.set(headerOutputDir)
+
+    doLast {
+        println("Generated JNI Headers at: ${headerOutputDir.get().asFile.absolutePath}")
     }
+}
 
-    dependsOn("compileKotlinJvm")
+
+tasks.named("jvmMainClasses") {
+    dependsOn(generateJniHeaders)
 }
 
 publishing {
@@ -165,7 +177,7 @@ publishing {
     publications.withType<MavenPublication> {
         pom {
             name.set("dropbear")
-            description.set("The dropbear scripting part of the engine... uhh yeah!")
+            description.set("The dropbear scripting part of the engine")
             url.set("https://github.com/tirbofish/dropbear")
 
             licenses {
@@ -179,7 +191,7 @@ publishing {
                 developer {
                     id.set("tirbofish")
                     name.set("tk")
-                    email.set("tirbofish@pm.me")
+                    email.set("4tkbytes@pm.me")
                 }
             }
 
@@ -198,13 +210,11 @@ tasks.register<Jar>("fatJar") {
 
     from(kotlin.jvm().compilations["main"].output)
 
-    configurations.named("jvmRuntimeClasspath").get().forEach { file ->
-        if (file.name.endsWith(".jar")) {
-            from(zipTree(file))
-        } else {
-            from(file)
-        }
-    }
+    from(configurations.named("jvmRuntimeClasspath").map {
+        it.map { file -> if (file.isDirectory) file else zipTree(file) }
+    })
 
-    manifest {}
+    manifest {
+        attributes["Implementation-Version"] = project.version
+    }
 }
\ No newline at end of file
diff --git a/eucalyptus-core/src/lib.rs b/eucalyptus-core/src/lib.rs
index 6d0b3cb..a2a4236 100644
--- a/eucalyptus-core/src/lib.rs
+++ b/eucalyptus-core/src/lib.rs
@@ -53,6 +53,8 @@ pub fn register_components(
     component_registry.register_with_default::<Script>();
     component_registry.register_with_default::<SerializedMeshRenderer>();
     component_registry.register_with_default::<Camera3D>();
+    component_registry.register_with_default::<RigidBody>();
+    component_registry.register_with_default::<ColliderGroup>();
 
     component_registry.register_converter::<MeshRenderer, SerializedMeshRenderer, _>(
         |_, _, renderer| {
@@ -77,9 +79,6 @@ pub fn register_components(
         },
     );
 
-    component_registry.register_with_default::<RigidBody>();
-    component_registry.register_with_default::<ColliderGroup>();
-
     // // register plugin defined structs
     // if let Err(e) = plugin_registry.load_plugins() {
     //     fatal!("Failed to load plugins: {}", e);
diff --git a/eucalyptus-editor/src/editor/dock.rs b/eucalyptus-editor/src/editor/dock.rs
index 22f3856..d7a9cc1 100644
--- a/eucalyptus-editor/src/editor/dock.rs
+++ b/eucalyptus-editor/src/editor/dock.rs
@@ -478,9 +478,9 @@ impl<'a> TabViewer for EditorTabViewer<'a> {
                                         log_once::debug_once!("Available components: ");
                                         for (id, name) in registry.iter_available_components() {
                                             log_once::debug_once!("id: {}, name: {}", id, name);
-                                            if name.contains("EntityTransform") {
-                                                continue;
-                                            }
+                                            // if name.contains("EntityTransform") {
+                                            //     continue;
+                                            // }
                                             let short_name =
                                                 name.split("::").last().unwrap_or(name);
                                             let display_name =
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 3eb05ee..5c470be 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
 [versions]
-kotlin = "2.1.0"
+kotlin = "2.3.0"
 kotlinxSerialization = "1.8.0"
 
 [libraries]
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5a41f17..50632e7 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -9,11 +9,11 @@ pluginManagement {
 plugins {
     id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
 }
-include("magna-carta-plugin")
+//include("magna-carta-plugin")
 
 buildCache {
     local {
         isEnabled = true
     }
 }
-include("dropbear-gradle-plugin")
\ No newline at end of file
+//include("dropbear-gradle-plugin")
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/Camera.kt b/src/commonMain/kotlin/com/dropbear/Camera.kt
index db5ab00..3016200 100644
--- a/src/commonMain/kotlin/com/dropbear/Camera.kt
+++ b/src/commonMain/kotlin/com/dropbear/Camera.kt
@@ -1,5 +1,7 @@
 package com.dropbear
 
+import com.dropbear.ecs.Component
+import com.dropbear.ecs.ComponentType
 import com.dropbear.math.Vector3D
 
 /**
@@ -7,44 +9,42 @@ import com.dropbear.math.Vector3D
  */
 class Camera(
     internal val entity: EntityId,
-) {
+): Component(entity, "Camera3D") {
     var eye: Vector3D
-        get() = native.getCameraEye(this)
-        set(value) = native.setCameraEye(this, value)
+        get() = getCameraEye(entity)
+        set(value) = setCameraEye(entity, value)
     var target: Vector3D
-        get() = native.getCameraTarget(this)
-        set(value) = native.setCameraTarget(this, value)
+        get() = getCameraTarget(entity)
+        set(value) = setCameraTarget(entity, value)
     var up: Vector3D
-        get() = native.getCameraUp(this)
-        set(value) = native.setCameraUp(this, value)
+        get() = getCameraUp(entity)
+        set(value) = setCameraUp(entity, value)
     val aspect: Double
-        get() = native.getCameraAspect(this)
+        get() = getCameraAspect(entity)
     var fov_y: Double
-        get() = native.getCameraFovY(this)
-        set(value) = native.setCameraFovY(this, value)
+        get() = getCameraFovY(entity)
+        set(value) = setCameraFovY(entity, value)
     var znear: Double
-        get() = native.getCameraZNear(this)
-        set(value) = native.setCameraZNear(this, value)
+        get() = getCameraZNear(entity)
+        set(value) = setCameraZNear(entity, value)
     var zfar: Double
-        get() = native.getCameraZFar(this)
-        set(value) = native.setCameraZFar(this)
+        get() = getCameraZFar(entity)
+        set(value) = setCameraZFar(entity, value)
     var yaw: Double
-        get() = native.getCameraYaw(this)
-        set(value) = native.setCameraYaw(this, value)
+        get() = getCameraYaw(entity)
+        set(value) = setCameraYaw(entity, value)
     var pitch: Double
-        get() = native.getCameraPitch(this)
-        set(value) = native.setCameraPitch(this, value)
+        get() = getCameraPitch(entity)
+        set(value) = setCameraPitch(entity, value)
     var speed: Double
-        get() = native.getCameraSpeed(this)
-        set(value) = native.setCameraSpeed(this, value)
+        get() = getCameraSpeed(entity)
+        set(value) = setCameraSpeed(entity, value)
     var sensitivity: Double
-        get() = native.getCameraSensitivity(this)
-        set(value) = native.setCameraSensitivity(this, value)
-
-    internal lateinit var engine: DropbearEngine
+        get() = getCameraSensitivity(entity)
+        set(value) = setCameraSensitivity(entity, value)
 
     override fun toString(): String {
-        return "Camera '${label}' of id $id \n" +
+        return "Camera component of entity $entity \n" +
                 "eye: $eye\n" +
                 "target: $target\n" +
                 "up: $up\n " +
@@ -57,4 +57,34 @@ class Camera(
                 "speed: $speed" +
                 "sensitivity: $sensitivity"
     }
-}
\ No newline at end of file
+
+    companion object : ComponentType<Camera> {
+        override fun get(entityId: EntityId): Camera? {
+            return if (cameraExistsForEntity(entityId)) Camera(entityId) else null
+        }
+    }
+}
+
+expect fun Camera.getCameraEye(entity: EntityId): Vector3D
+expect fun Camera.setCameraEye(entity: EntityId, value: Vector3D)
+expect fun Camera.getCameraTarget(entity: EntityId): Vector3D
+expect fun Camera.setCameraTarget(entity: EntityId, value: Vector3D)
+expect fun Camera.getCameraUp(entity: EntityId): Vector3D
+expect fun Camera.setCameraUp(entity: EntityId, value: Vector3D)
+expect fun Camera.getCameraAspect(entity: EntityId): Double
+expect fun Camera.getCameraFovY(entity: EntityId): Double
+expect fun Camera.setCameraFovY(entity: EntityId, value: Double)
+expect fun Camera.getCameraZNear(entity: EntityId): Double
+expect fun Camera.setCameraZNear(entity: EntityId, value: Double)
+expect fun Camera.getCameraZFar(entity: EntityId): Double
+expect fun Camera.setCameraZFar(entity: EntityId, value: Double)
+expect fun Camera.getCameraYaw(entity: EntityId): Double
+expect fun Camera.setCameraYaw(entity: EntityId, value: Double)
+expect fun Camera.getCameraPitch(entity: EntityId): Double
+expect fun Camera.setCameraPitch(entity: EntityId, value: Double)
+expect fun Camera.getCameraSpeed(entity: EntityId): Double
+expect fun Camera.setCameraSpeed(entity: EntityId, value: Double)
+expect fun Camera.getCameraSensitivity(entity: EntityId): Double
+expect fun Camera.setCameraSensitivity(entity: EntityId, value: Double)
+
+expect fun cameraExistsForEntity(entity: EntityId): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/CustomProperties.kt b/src/commonMain/kotlin/com/dropbear/CustomProperties.kt
new file mode 100644
index 0000000..49f3003
--- /dev/null
+++ b/src/commonMain/kotlin/com/dropbear/CustomProperties.kt
@@ -0,0 +1,93 @@
+package com.dropbear
+
+import com.dropbear.ecs.Component
+import com.dropbear.ecs.ComponentType
+import com.dropbear.math.Vector3
+
+class CustomProperties(val id: EntityId): Component(id, "CustomProperties") {
+    /**
+     * Fetches the property of the ModelProperty component on the entity.
+     */
+    inline fun <reified T> getProperty(key: String): T? {
+        return when (T::class) {
+            String::class -> getStringProperty(id.id, key) as T?
+            Long::class -> getLongProperty(id.id, key) as T?
+            Int::class -> getIntProperty(id.id, key) as T?
+            Double::class -> getDoubleProperty(id.id, key) as T?
+
+            Float::class -> getFloatProperty(id.id, key) as T?
+            Boolean::class -> getBoolProperty(id.id, key) as T?
+            FloatArray::class -> getVec3Property(id.id, key) as T?
+            else -> throw IllegalArgumentException("Unsupported property type: ${T::class}")
+        }
+    }
+
+    /**
+     * Sets a property of the ModelProperty component on the entity.
+     *
+     * # Supported types
+     * - [kotlin.String]
+     * - [kotlin.Long]
+     * - [kotlin.Int]
+     * - [kotlin.Double]
+     * - [kotlin.Float]
+     * - [kotlin.Boolean]
+     * - [com.dropbear.math.Vector3]
+     */
+    /**
+     * Sets a property of the ModelProperty component on the entity.
+     *
+     * # Supported types
+     * - [kotlin.String]
+     * - [kotlin.Long]
+     * - [kotlin.Int]
+     * - [kotlin.Double]
+     * - [kotlin.Float]
+     * - [kotlin.Boolean]
+     * - [com.dropbear.math.Vector3]
+     */
+    fun setProperty(key: String, value: Any) {
+        when (value) {
+            is String -> setStringProperty(id.id, key, value)
+            is Long -> setLongProperty(id.id, key, value)
+            is Int -> setIntProperty(id.id, key, value)
+            is Double -> setFloatProperty(id.id, key, value)
+            is Float -> setFloatProperty(id.id, key, value.toDouble())
+            is Boolean -> setBoolProperty(id.id, key, value)
+            is Vector3<*> -> {
+                val vec = value.asDoubleVector()
+                setVec3Property(id.id, key, floatArrayOf(vec.x.toFloat(), vec.y.toFloat(),
+                    vec.z.toFloat()
+                ))
+            }
+            is FloatArray -> {
+                require(value.size == 3) { "Vec3 property must have exactly 3 elements" }
+                setVec3Property(id.id, key, value)
+            }
+            else -> throw IllegalArgumentException("Unsupported property type: ${value::class}")
+        }
+    }
+
+    companion object : ComponentType<CustomProperties> {
+        override fun get(entityId: EntityId): CustomProperties? {
+            return if (customPropertiesExistsForEntity(entityId)) CustomProperties(entityId) else null
+        }
+    }
+}
+
+expect fun CustomProperties.getStringProperty(entityHandle: Long, label: String): String?
+expect fun CustomProperties.getIntProperty(entityHandle: Long, label: String): Int?
+expect fun CustomProperties.getLongProperty(entityHandle: Long, label: String): Long?
+expect fun CustomProperties.getDoubleProperty(entityHandle: Long, label: String): Double?
+expect fun CustomProperties.getFloatProperty(entityHandle: Long, label: String): Float?
+expect fun CustomProperties.getBoolProperty(entityHandle: Long, label: String): Boolean?
+expect fun CustomProperties.getVec3Property(entityHandle: Long, label: String): FloatArray?
+
+expect fun CustomProperties.setStringProperty(entityHandle: Long, label: String, value: String)
+expect fun CustomProperties.setIntProperty(entityHandle: Long, label: String, value: Int)
+expect fun CustomProperties.setLongProperty(entityHandle: Long, label: String, value: Long)
+expect fun CustomProperties.setFloatProperty(entityHandle: Long, label: String, value: Double)
+expect fun CustomProperties.setBoolProperty(entityHandle: Long, label: String, value: Boolean)
+expect fun CustomProperties.setVec3Property(entityHandle: Long, label: String, value: FloatArray)
+
+expect fun customPropertiesExistsForEntity(entityId: EntityId): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/DropbearEngine.kt b/src/commonMain/kotlin/com/dropbear/DropbearEngine.kt
index 4fb0a44..4666259 100644
--- a/src/commonMain/kotlin/com/dropbear/DropbearEngine.kt
+++ b/src/commonMain/kotlin/com/dropbear/DropbearEngine.kt
@@ -5,7 +5,6 @@ import com.dropbear.ffi.NativeEngine
 import com.dropbear.input.InputState
 import com.dropbear.logging.Logger
 import com.dropbear.scene.SceneManager
-import com.dropbear.ui.UIManager
 
 internal var exceptionOnError: Boolean = false
 var lastErrorMessage: String? = null
@@ -18,8 +17,21 @@ var lastErrorMessage: String? = null
  */
 class DropbearEngine(val native: NativeEngine) {
     private var inputState: InputState? = null
+        get() {
+            if (field == null) {
+                Logger.trace("InputState not initialised, creating new one")
+                field = InputState()
+            }
+            return field
+        }
     private var sceneManager: SceneManager? = null
-    private var uiManager: UIManager? = null
+        get() {
+            if (field == null) {
+                Logger.trace("SceneManager not initialised, creating new one")
+                field = SceneManager()
+            }
+            return field
+        }
 
     init {
         Companion.native = native
@@ -46,57 +58,12 @@ class DropbearEngine(val native: NativeEngine) {
      * Fetches an [EntityRef] with the given label.
      */
     fun getEntity(label: String): EntityRef? {
-        val entityId = native.getEntity(label)
+        val entityId = com.dropbear.getEntity(label)
         val entityRef = if (entityId != null) EntityRef(EntityId(entityId)) else null
-        entityRef?.engine = this
         return entityRef
     }
 
     /**
-     * Fetches the information of the camera with the given label.
-     */
-    fun getCamera(label: String): Camera? {
-        val result = native.getCamera(label)
-        if (result != null) {
-            result.engine = this
-        }
-        return result
-    }
-
-    /**
-     * Gets the current [InputState] for that frame.
-     */
-    fun getInputState(): InputState {
-        if (this.inputState == null) {
-            Logger.trace("InputState not initialised, creating new one")
-            this.inputState = InputState(native)
-        }
-        return this.inputState!!
-    }
-
-    /**
-     * Gets the current [SceneManager] for that frame.
-     */
-    fun getSceneManager(): SceneManager {
-        if (this.sceneManager == null) {
-            Logger.trace("SceneManager not initialised, creating new one")
-            this.sceneManager = SceneManager(native)
-        }
-        return this.sceneManager!!
-    }
-
-    /**
-     * Gets the current [UIManager] for that frame.
-     */
-    fun getUIManager(): UIManager {
-        if (this.uiManager == null) {
-            Logger.trace("UiManager not initialised, creating new one")
-            this.uiManager = UIManager(native)
-        }
-        return this.uiManager!!
-    }
-
-    /**
      * Fetches the asset information from the internal AssetRegistry (located in
      * `dropbear_engine::asset::AssetRegistry`).
      *
@@ -104,7 +71,7 @@ class DropbearEngine(val native: NativeEngine) {
      * The eucalyptus asset URI (or `euca://`) is case-sensitive.
      */
     fun getAsset(eucaURI: String): AssetHandle? {
-        val id = native.getAsset(eucaURI)
+        val id = com.dropbear.getAsset(eucaURI)
         return if (id != null) AssetHandle(id) else null
     }
 
@@ -116,7 +83,7 @@ class DropbearEngine(val native: NativeEngine) {
     fun callExceptionOnError(toggle: Boolean) = DropbearEngine.callExceptionOnError(toggle)
 
     /**
-     * Quits the currently running app or game.
+     * Quits the currently running app or game elegantly.
      * 
      * This function can have different behaviours depending on where it is ran. 
      * - eucalyptus-editor - When called, this exits your Play Mode session and returns you back to
@@ -125,6 +92,11 @@ class DropbearEngine(val native: NativeEngine) {
      *                     also drop any pointers and do any additional cleanup.
      */
     fun quit() {
-        native.quit()
+        com.dropbear.quit()
     }
-}
\ No newline at end of file
+}
+
+expect fun getEntity(label: String): Long?
+expect fun getCamera(label: String): Camera?
+expect fun getAsset(eucaURI: String): Long?
+expect fun quit()
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/EntityRef.kt b/src/commonMain/kotlin/com/dropbear/EntityRef.kt
index af2fde8..ee67dfa 100644
--- a/src/commonMain/kotlin/com/dropbear/EntityRef.kt
+++ b/src/commonMain/kotlin/com/dropbear/EntityRef.kt
@@ -1,12 +1,7 @@
 package com.dropbear
 
-import com.dropbear.asset.ModelHandle
-import com.dropbear.asset.TextureHandle
-import com.dropbear.math.Transform
-import com.dropbear.math.Vector3
-import com.dropbear.math.Vector3D
-import com.dropbear.physics.Collider
-import com.dropbear.physics.RigidBody
+import com.dropbear.ecs.Component
+import com.dropbear.ecs.ComponentType
 
 /**
  * A reference to an ECS Entity stored inside the dropbear engine.
@@ -21,172 +16,21 @@ import com.dropbear.physics.RigidBody
  *              playthroughs, so it is recommended not to store this value.
  */
 class EntityRef(val id: EntityId = EntityId(0L)) {
-    lateinit var engine: DropbearEngine
-
-    override fun toString(): String {
-        return "EntityRef(id=$id)"
-    }
-
-    /**
-     * Fetches the [EntityTransform] component for the entity.
-     */
-    fun getTransform(): EntityTransform? {
-        return engine.native.getTransform(id)
-    }
-
-    /**
-     * Walks up the world hierarchy to find the transform of the parent, then multiply 
-     * to create a propagated [Transform].
-     * 
-     * This will update the entity's world transform based on its parent's world transform.
-     */
-    fun propagate(): Transform? {
-        return engine.native.propagateTransform(id)
-    }
-
-    /**
-     * Sets and replaces the [EntityTransform] component for the entity.
-     */
-    fun setTransform(transform: EntityTransform?) {
-        if (transform == null) return
-        return engine.native.setTransform(id, transform)
-    }
-
-    /**
-     * Fetches the property of the ModelProperty component on the entity.
-     */
-    inline fun <reified T> getProperty(key: String): T? {
-        return when (T::class) {
-            String::class -> engine.native.getStringProperty(id.id, key) as T?
-            Long::class -> engine.native.getLongProperty(id.id, key) as T?
-            Int::class -> engine.native.getIntProperty(id.id, key) as T?
-            Double::class -> engine.native.getDoubleProperty(id.id, key) as T?
-
-            Float::class -> engine.native.getFloatProperty(id.id, key) as T?
-            Boolean::class -> engine.native.getBoolProperty(id.id, key) as T?
-            FloatArray::class -> engine.native.getVec3Property(id.id, key) as T?
-            else -> throw IllegalArgumentException("Unsupported property type: ${T::class}")
-        }
-    }
-
     /**
-     * Sets a property of the ModelProperty component on the entity.
+     * The `Label` component (the entity name).
      *
-     * # Supported types
-     * - [kotlin.String]
-     * - [kotlin.Long]
-     * - [kotlin.Int]
-     * - [kotlin.Double]
-     * - [kotlin.Float]
-     * - [kotlin.Boolean]
-     * - [com.dropbear.math.Vector3]
-     */
-    /**
-     * Sets a property of the ModelProperty component on the entity.
-     *
-     * # Supported types
-     * - [kotlin.String]
-     * - [kotlin.Long]
-     * - [kotlin.Int]
-     * - [kotlin.Double]
-     * - [kotlin.Float]
-     * - [kotlin.Boolean]
-     * - [com.dropbear.math.Vector3]
-     */
-    fun setProperty(key: String, value: Any) {
-        when (value) {
-            is String -> engine.native.setStringProperty(id.id, key, value)
-            is Long -> engine.native.setLongProperty(id.id, key, value)
-            is Int -> engine.native.setIntProperty(id.id, key, value)
-            is Double -> engine.native.setFloatProperty(id.id, key, value)
-            is Float -> engine.native.setFloatProperty(id.id, key, value.toDouble())
-            is Boolean -> engine.native.setBoolProperty(id.id, key, value)
-            is Vector3<*> -> {
-                val vec = value.asDoubleVector()
-                engine.native.setVec3Property(id.id, key, floatArrayOf(vec.x.toFloat(), vec.y.toFloat(),
-                    vec.z.toFloat()
-                ))
-            }
-            is FloatArray -> {
-                require(value.size == 3) { "Vec3 property must have exactly 3 elements" }
-                engine.native.setVec3Property(id.id, key, value)
-            }
-            else -> throw IllegalArgumentException("Unsupported property type: ${value::class}")
-        }
-    }
-
-    /**
-     * Fetches the attached camera for the entity.
-     *
-     * Returns null if no camera is attached as a component according to the editor.
-     */
-    fun getAttachedCamera(): Camera? {
-        val result = engine.native.getAttachedCamera(id)
-        if (result != null) {
-            result.engine = this.engine
-        }
-        return result
-    }
-
-    /**
-     * Fetches the texture for the given material name in the model.
-     */
-    fun getTexture(materialName: String): TextureHandle? {
-        val result = engine.native.getTexture(id.id, materialName)
-        return if (result == null) {
-            null
-        } else {
-            TextureHandle(result)
-        }
-    }
-
-    /**
-     * Returns an array containing the texture identifiers applied to this entity's model.
-     */
-    fun getAllTextures(): Array<String> {
-        return engine.native.getAllTextures(id.id)
-    }
-
-    /**
-     * Checks if the current model being rendered by this entity contains the texture with the given [TextureHandle]
-     */
-    fun hasTexture(textureHandle: TextureHandle): Boolean {
-        return engine.native.isUsingTexture(id.id, textureHandle.raw())
-    }
-
-    /**
-     * Fetches the active model that is currently being used
-     */
-    fun getModel(): ModelHandle? {
-        val result = engine.native.getModel(id.id)
-        return if (result == null) {
-            null
-        } else {
-            ModelHandle(result)
-        }
-    }
-
-    /**
-     * Sets the active model for the entity from a ModelHandle
+     * All entities have a `Label` component. If one does not, it is considered a bug in the engine or *you* did something
+     * to break this. Anyhow, it will throw an [Exception].
      */
-    fun setModel(modelHandle: ModelHandle) {
-        engine.native.setModel(id.id, modelHandle.raw())
-    }
+    val label: String
+        get() = getEntityLabel(id) ?: throw Exception("Entity has no label, expected to contain")
 
-    /**
-     * Checks if the entity is currently using the given model handle.
-     *
-     * Returns false if not using, true if is.
-     */
-    fun usingModel(modelHandle: ModelHandle): Boolean {
-        return engine.native.isUsingModel(id.id, modelHandle.raw())
+    override fun toString(): String {
+        return "EntityRef(id=$id)"
     }
 
-    /**
-     * Sets a texture override for the given material on the active model.
-     */
-    fun setTextureOverride(materialName: String, textureHandle: TextureHandle) {
-        engine.native.setTextureOverride(id.id, materialName, textureHandle)
+    fun <T : Component> get(type: ComponentType<T>): T? {
+        return type.get(id)
     }
 
     /**
@@ -204,7 +48,7 @@ class EntityRef(val id: EntityId = EntityId(0L)) {
      * By running [getChildren] on `cat`, it will return `[ wizard_hat ]`, not `pom_pom`.
      */
     fun getChildren(): Array<EntityRef>? {
-        return engine.native.getChildren(id)
+        return getChildren(id)
     }
 
     /**
@@ -213,7 +57,7 @@ class EntityRef(val id: EntityId = EntityId(0L)) {
      * Returns `null` if an error occurred or no child exists, otherwise the entity.
      */
     fun getChildByLabel(label: String): EntityRef? {
-        return engine.native.getChildByLabel(id, label)
+        return getChildByLabel(id, label)
     }
 
     /**
@@ -232,60 +76,11 @@ class EntityRef(val id: EntityId = EntityId(0L)) {
      * Calling [getParent] on `cat` will return `null`, as the Scene is not an entity.
      */
     fun getParent(): EntityRef? {
-        return engine.native.getParent(id)
-    }
-
-    /**
-     * Fetches the `Label` component (the entity name).
-     *
-     * All entities have a `Label` component. If one does not, it is considered a bug in the engine or *you* did something
-     * to break this. Anyhow, it will throw an [Exception].
-     */
-    fun getLabel(): String {
-        return engine.native.getEntityLabel(id.id) ?: throw Exception("Entity has no label, expected to contain. Likely engine bug")
-    }
-
-    // physics stuff
-
-    /**
-     * Sets physics enabled.
-     *
-     * If physics is enabled, the entity will be under the influence of gravity. Using position based movement will
-     * not be possible, and will have to be done with physics based movement.
-     *
-     * If physics is disabled, the entity will **not** be under the influence of gravity and will stand still.
-     * Other physic-based entities (such as walls and floors) will not affect the player, and collision based
-     * functions will not work.
-     */
-    fun setPhysicsEnabled(enabled: Boolean) {
-        return engine.native.setPhysicsEnabled(id.id, enabled)
-    }
-
-    /**
-     * Checks if physics is applied to the entity.
-     *
-     * If physics is enabled, it will return true. If not, it will return false.
-     */
-    fun isPhysicsEnabled(): Boolean {
-        return engine.native.isPhysicsEnabled(id.id)
+        return getParent(id)
     }
+}
 
-    /**
-     * Fetches the [`RigidBody`] component.
-     *
-     * Can return `null` if no component exists within the entity.
-     */
-    fun getRigidBody(): RigidBody? {
-        return engine.native.getRigidBody(id.id)
-    }
-
-    /**
-     * Fetches all available colliders under the `ColliderGroup` component of the entity.
-     *
-     * Can return an [emptyArray] if no Collider's exist within the group, or `null` if no
-     * such component (`ColliderGroup`) is available on the entity.
-     */
-    fun getAllColliders(): List<Collider>? {
-        return engine.native.getAllColliders(id.id)
-    }
-}
\ No newline at end of file
+expect fun EntityRef.getEntityLabel(entity: EntityId): String?
+expect fun EntityRef.getChildren(entityId: EntityId): Array<EntityRef>?
+expect fun EntityRef.getChildByLabel(entityId: EntityId, label: String): EntityRef?
+expect fun EntityRef.getParent(entityId: EntityId): EntityRef?
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/EntityTransform.kt b/src/commonMain/kotlin/com/dropbear/EntityTransform.kt
index d60d059..42768d4 100644
--- a/src/commonMain/kotlin/com/dropbear/EntityTransform.kt
+++ b/src/commonMain/kotlin/com/dropbear/EntityTransform.kt
@@ -1,12 +1,59 @@
 package com.dropbear
 
+import com.dropbear.ecs.Component
+import com.dropbear.ecs.ComponentType
 import com.dropbear.math.Transform
 
 /**
  * A component that contains the local and world [Transform] of an entity.
  */
-class EntityTransform(var local: Transform, var world: Transform) {
+class EntityTransform(val id: EntityId): Component(id, "EntityTransform") {
+    var local: Transform
+        get() = getLocalTransform(id)
+        set(value) = setLocalTransform(id, value)
+    var world: Transform
+        get() = getWorldTransform(id)
+        set(value) = setWorldTransform(id, value)
+
     override fun toString(): String {
-        return "EntityTransform(local=$local, world=$world)"
+        return "EntityTransform(id: $id, local=$local, world=$world)"
+    }
+
+    /**
+     * Walks up the world hierarchy to find the transform of the parent, then multiply/add
+     * to create a propagated [Transform].
+     */
+    fun propagate(): Transform {
+        return propagateTransform(id)
+    }
+
+    /**
+     * Merges the local and world transforms and return the merged [Transform]
+     */
+    fun sync(): Transform {
+        val scaledPos = local.position * world.scale
+        val rotatedPos = world.rotation * scaledPos
+        val finalPos = world.position + rotatedPos
+        val finalRot = world.rotation * local.rotation
+        val finalScale = world.scale * local.scale
+        return Transform(finalPos, finalRot, finalScale)
     }
-}
\ No newline at end of file
+
+    companion object : ComponentType<EntityTransform> {
+        override fun get(entityId: EntityId): EntityTransform? {
+            return if (entityTransformExistsForEntity(entityId)) {
+                EntityTransform(entityId)
+            } else {
+                null
+            }
+        }
+    }
+}
+
+expect fun EntityTransform.getLocalTransform(entityId: EntityId): Transform
+expect fun EntityTransform.setLocalTransform(entityId: EntityId, transform: Transform)
+expect fun EntityTransform.getWorldTransform(entityId: EntityId): Transform
+expect fun EntityTransform.setWorldTransform(entityId: EntityId, transform: Transform)
+expect fun EntityTransform.propagateTransform(entityId: EntityId): Transform
+
+expect fun entityTransformExistsForEntity(entityId: EntityId): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/MeshRenderer.kt b/src/commonMain/kotlin/com/dropbear/MeshRenderer.kt
new file mode 100644
index 0000000..c16c9d3
--- /dev/null
+++ b/src/commonMain/kotlin/com/dropbear/MeshRenderer.kt
@@ -0,0 +1,72 @@
+package com.dropbear
+
+import com.dropbear.asset.ModelHandle
+import com.dropbear.asset.TextureHandle
+import com.dropbear.ecs.Component
+import com.dropbear.ecs.ComponentType
+
+class MeshRenderer(val id: EntityId) : Component(id, "MeshRenderer") {
+
+    /**
+     * The active model currently assigned to this entity.
+     * Setting this to null removes the model.
+     *
+     * Usage:
+     * ```
+     * val handle = renderer.model
+     * renderer.model = newHandle
+     * ```
+     */
+    var model: ModelHandle?
+        get() {
+            return getModel(id)
+        }
+        set(value) {
+            setModel(id, value)
+        }
+
+    /**
+     * A list of all active Texture handles currently applied to the model.
+     */
+    val textures: List<TextureHandle>?
+        get() = getAllTextureIds(id)
+
+    /**
+     * Returns a list of material names available on the current model.
+     * Useful for knowing what keys to use in [getTexture] or [setTextureOverride].
+     */
+    val materialNames: List<String>
+        get() = getMaterialNames(id)
+
+    /**
+     * Fetches the texture assigned to a specific material slot.
+     * Returns null if the material doesn't exist or has no texture.
+     */
+    fun getTexture(materialName: String): TextureHandle? {
+        val rawId = getTexture(id, materialName)
+        return if (rawId == 0L) null else TextureHandle(rawId)
+    }
+
+    /**
+     * Overrides the texture for a specific material on the active model.
+     */
+    fun setTextureOverride(materialName: String, textureHandle: TextureHandle) {
+        setTextureOverride(id, materialName, textureHandle.raw())
+    }
+
+    companion object : ComponentType<MeshRenderer> {
+        override fun get(entityId: EntityId): MeshRenderer? {
+            return if (meshRendererExistsForEntity(entityId)) MeshRenderer(entityId) else null
+        }
+    }
+}
+
+expect fun MeshRenderer.getModel(id: EntityId): ModelHandle?
+expect fun MeshRenderer.setModel(id: EntityId, model: ModelHandle?)
+expect fun MeshRenderer.getAllTextureIds(id: EntityId): List<TextureHandle>?
+expect fun MeshRenderer.getMaterialNames(id: EntityId): List<String>
+expect fun MeshRenderer.setMaterialNames(id: EntityId, names: Array<String>)
+expect fun MeshRenderer.getTexture(id: EntityId, materialName: String): Long
+expect fun MeshRenderer.setTextureOverride(id: EntityId, materialName: String, textureHandle: Long)
+
+expect fun meshRendererExistsForEntity(entityId: EntityId): Boolean
diff --git a/src/commonMain/kotlin/com/dropbear/Runnable.kt b/src/commonMain/kotlin/com/dropbear/Runnable.kt
index ac126c0..3183324 100644
--- a/src/commonMain/kotlin/com/dropbear/Runnable.kt
+++ b/src/commonMain/kotlin/com/dropbear/Runnable.kt
@@ -7,7 +7,10 @@ package com.dropbear
  * the `magna-carta` manifest generator tool. 
  * 
  * The tags correspond to the tags provided to the entity
- * with the Script. 
+ * with the Script.
+ *
+ * # Note
+ * This annotation only works on classes that implement [com.dropbear.ecs.System], **not** [com.dropbear.ecs.Component]
  */
 @Target(AnnotationTarget.CLASS)
 @Retention(AnnotationRetention.SOURCE)
diff --git a/src/commonMain/kotlin/com/dropbear/ScriptRegistration.kt b/src/commonMain/kotlin/com/dropbear/ScriptRegistration.kt
index 63b8e57..8b50f43 100644
--- a/src/commonMain/kotlin/com/dropbear/ScriptRegistration.kt
+++ b/src/commonMain/kotlin/com/dropbear/ScriptRegistration.kt
@@ -1,5 +1,10 @@
 package com.dropbear
 
+import com.dropbear.ecs.System
+
+/**
+ * Internal data class to register scripts with tags.
+ */
 data class ScriptRegistration(
     val tags: List<String>,
     val script: System
diff --git a/src/commonMain/kotlin/com/dropbear/System.kt b/src/commonMain/kotlin/com/dropbear/System.kt
deleted file mode 100644
index a1a62b6..0000000
--- a/src/commonMain/kotlin/com/dropbear/System.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.dropbear
-
-/**
- * A class that contains the basic information of a system. 
- * 
- * The dropbear engine follows an ECS paradigm, with logic being
- * provided as Systems.
- */
-open class System {
-    /**
-     * The current entity that is being run in the system. Most often than not, it
-     * will have an [EntityRef] attached (because all Script components must be part
-     * of an entity).
-     */
-    var currentEntity: EntityRef? = null
-        private set
-
-    private var engineRef: DropbearEngine? = null
-
-    /**
-     * This function is called when the script module is initialised.
-     *
-     * It is only called once during scene execution. If you re-switch back
-     * to this scene after running the class, it will be run again.
-     */
-    open fun load(engine: DropbearEngine) {}
-
-    /**
-     * This function is called for each update.
-     *
-     * It is run once for each frame, and for every frame. Since this is synced to the frame rate, using
-     * the [deltaTime] variable can aid you in creating uniform player speeds (or something like that).
-     *
-     * @param deltaTime - This specifies the time elapsed since the last update.
-     */
-    open fun update(engine: DropbearEngine, deltaTime: Float) {}
-
-    /**
-     * This function is called for each update that is related to physics.
-     *
-     * It can be run 0, 1, 2 or more times per frame. Updating physics is done at a constant
-     * rate/tick (at roughly 50Hz or 0.02), which is why it is not ran as often as a standard [update].
-     *
-     * @param deltaTime - This specifies the time elapsed since the last frame update. Likely, it's going
-     *                    to be somewhere around 50Hz. For the most part, you might not need this.
-     */
-    open fun physicsUpdate(engine: DropbearEngine, deltaTime: Float) {}
-
-    /**
-     * This function is called at the end of the script execution.
-     *
-     * It is run at the end of execution of a scene, such as when the scene switches. It is also ran once throughout
-     * the lifecycle of a script class. It is best to think about it like `sceneExit()` instead of `appExit()`
-     *
-     * It would be used to clean up any memory related resources (such as `SceneLoadHandle` or any memory related items).
-     *
-     * # Note
-     *
-     * The script module does not lose state (such as variables) when destroyed. It is cached internally (within the system manager),
-     * therefore counters and other related stuff will not lose track.
-     */
-    open fun destroy(engine: DropbearEngine) {}
-
-    /**
-     * Internal: This attaches the [DropbearEngine] fascade (typically created through some external location)
-     * to the existing system to be used.
-     */
-    fun attachEngine(engine: DropbearEngine) {
-        engineRef = engine
-        currentEntity?.engine = engine
-    }
-
-    /**
-     * Internal: Sets the current entity of this [System] to something.
-     */
-    fun setCurrentEntity(entity: Long) {
-        val engine = engineRef ?: run {
-            currentEntity = null
-            return
-        }
-
-        val reference = EntityRef(EntityId(entity))
-        reference.engine = engine
-        currentEntity = reference
-    }
-
-    /**
-     * Internal: Clears the current entity used.
-     */
-    fun clearCurrentEntity() {
-        currentEntity = null
-    }
-}
diff --git a/src/commonMain/kotlin/com/dropbear/asset/AssetHandle.kt b/src/commonMain/kotlin/com/dropbear/asset/AssetHandle.kt
index ab765ee..e6b31b1 100644
--- a/src/commonMain/kotlin/com/dropbear/asset/AssetHandle.kt
+++ b/src/commonMain/kotlin/com/dropbear/asset/AssetHandle.kt
@@ -11,8 +11,8 @@ class AssetHandle(private val id: Long): Handle(id) {
      *
      * It can return null if the asset is not a model.
      */
-    fun asModelHandle(engine: DropbearEngine): ModelHandle? {
-        val result = engine.native.isModelHandle(id)
+    fun asModelHandle(): ModelHandle? {
+        val result = isModelHandle(id)
         return if (result) {
             ModelHandle(id)
         } else {
@@ -20,20 +20,6 @@ class AssetHandle(private val id: Long): Handle(id) {
         }
     }
 
-    /**
-     * Converts an [AssetHandle] to a [TextureHandle].
-     *
-     * It can return null if the asset is not a texture.
-     */
-    fun asTextureHandle(engine: DropbearEngine): TextureHandle? {
-        val result = engine.native.isTextureHandle(id)
-        return if (result) {
-            TextureHandle(id)
-        } else {
-            null
-        }
-    }
-
     override fun asAssetHandle(): AssetHandle {
         return this
     }
@@ -41,4 +27,13 @@ class AssetHandle(private val id: Long): Handle(id) {
     override fun toString(): String {
         return "AssetHandle(id=$id)"
     }
-}
\ No newline at end of file
+}
+
+/**
+ * Converts an [AssetHandle] to a [TextureHandle].
+ *
+ * It can return null if the asset is not a texture.
+ */
+expect fun AssetHandle.asTextureHandle(): TextureHandle?
+
+expect fun isModelHandle(id: Long): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/asset/TextureHandle.kt b/src/commonMain/kotlin/com/dropbear/asset/TextureHandle.kt
index 3d658bb..c542985 100644
--- a/src/commonMain/kotlin/com/dropbear/asset/TextureHandle.kt
+++ b/src/commonMain/kotlin/com/dropbear/asset/TextureHandle.kt
@@ -12,11 +12,13 @@ class TextureHandle(private val id: Long): Handle(id) {
     /**
      * Fetches the name of that specific texture
      */
-    fun getName(engine: DropbearEngine): String? {
-        return engine.native.getTextureName(id)
+    fun getName(): String? {
+        return getTextureName(id)
     }
 
     override fun toString(): String {
         return "TextureHandle(id=$id)"
     }
-}
\ No newline at end of file
+}
+
+expect fun TextureHandle.getTextureName(id: Long): String?
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/ecs/Component.kt b/src/commonMain/kotlin/com/dropbear/ecs/Component.kt
new file mode 100644
index 0000000..4975ddd
--- /dev/null
+++ b/src/commonMain/kotlin/com/dropbear/ecs/Component.kt
@@ -0,0 +1,24 @@
+package com.dropbear.ecs
+
+import com.dropbear.EntityId
+
+/**
+ * A custom property that *can* be attached to an entity in the dropbear ECS system.
+ *
+ * @param parentEntity - The [com.dropbear.EntityId] to which this component is attached.
+ * @param typeName - The string name of the component type as defined in Rust. The name is
+ *                   found as the type name, such as `component_registry.register_with_default::<Camera3D>();`,
+ *                   where the type name would be `"Camera3D"`.
+ */
+abstract class Component(
+    val parentEntity: EntityId,
+    val typeName: String,
+) {
+    override fun toString(): String {
+        return "Component(parentEntity: ${this.parentEntity}, typeName: $typeName)"
+    }
+}
+
+interface ComponentType<T : Component> {
+    fun get(entityId: EntityId): T?
+}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/ecs/System.kt b/src/commonMain/kotlin/com/dropbear/ecs/System.kt
new file mode 100644
index 0000000..827d4b4
--- /dev/null
+++ b/src/commonMain/kotlin/com/dropbear/ecs/System.kt
@@ -0,0 +1,90 @@
+package com.dropbear.ecs
+
+import com.dropbear.DropbearEngine
+import com.dropbear.EntityId
+import com.dropbear.EntityRef
+
+/**
+ * A class that contains the basic information of a system.
+ *
+ * The dropbear engine follows an ECS paradigm, with logic being
+ * provided as Systems.
+ */
+open class System {
+    /**
+     * The current entity that is being run in the system. Most often than not, it
+     * will have an [com.dropbear.EntityRef] attached (because all Script components must be part
+     * of an entity).
+     */
+    var currentEntity: EntityRef? = null
+        private set
+
+    private var engineRef: DropbearEngine? = null
+
+    /**
+     * This function is called when the script module is initialised.
+     *
+     * It is only called once during scene execution. If you re-switch back
+     * to this scene after running the class, it will be run again.
+     */
+    open fun load(engine: DropbearEngine) {}
+
+    /**
+     * This function is called for each update.
+     *
+     * It is run once for each frame, and for every frame. Since this is synced to the frame rate, using
+     * the [deltaTime] variable can aid you in creating uniform player speeds (or something like that).
+     *
+     * @param deltaTime - This specifies the time elapsed since the last update.
+     */
+    open fun update(engine: DropbearEngine, deltaTime: Float) {}
+
+    /**
+     * This function is called for each update that is related to physics.
+     *
+     * It can be run 0, 1, 2 or more times per frame. Updating physics is done at a constant
+     * rate/tick (at roughly 50Hz or 0.02), which is why it is not ran as often as a standard [update].
+     *
+     * @param deltaTime - This specifies the time elapsed since the last frame update. Likely, it's going
+     *                    to be somewhere around 50Hz. For the most part, you might not need this.
+     */
+    open fun physicsUpdate(engine: DropbearEngine, deltaTime: Float) {}
+
+    /**
+     * This function is called at the end of the script execution.
+     *
+     * It is run at the end of execution of a scene, such as when the scene switches. It is also ran once throughout
+     * the lifecycle of a script class. It is best to think about it like `sceneExit()` instead of `appExit()`
+     *
+     * It would be used to clean up any memory related resources (such as `SceneLoadHandle` or any memory related items).
+     *
+     * # Note
+     *
+     * The script module does not lose state (such as variables) when destroyed. It is cached internally (within the system manager),
+     * therefore counters and other related stuff will not lose track.
+     */
+    open fun destroy(engine: DropbearEngine) {}
+
+    /**
+     * Internal: This attaches the [DropbearEngine] fascade (typically created through some external location)
+     * to the existing system to be used.
+     */
+    fun attachEngine(engine: DropbearEngine) {
+        engineRef = engine
+    }
+
+    /**
+     * Internal: Sets the current entity of this [System] to something.
+     */
+    fun setCurrentEntity(entity: Long) {
+        val reference = EntityRef(EntityId(entity))
+        currentEntity = reference
+    }
+
+    /**
+     * Internal: Clears the current entity used.
+     */
+    fun clearCurrentEntity() {
+        currentEntity = null
+    }
+}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/ffi/DropbearEngine.kt b/src/commonMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
deleted file mode 100644
index 6c4ae28..0000000
--- a/src/commonMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.dropbear.ffi
-
-expect fun getEntity(label: String): Long?
-expect fun getAsset(eucaURI: String): Long?
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/ffi/NativeEngine.kt b/src/commonMain/kotlin/com/dropbear/ffi/NativeEngine.kt
index 9a5507a..7d2b758 100644
--- a/src/commonMain/kotlin/com/dropbear/ffi/NativeEngine.kt
+++ b/src/commonMain/kotlin/com/dropbear/ffi/NativeEngine.kt
@@ -1,123 +1,9 @@
 package com.dropbear.ffi
 
-import com.dropbear.Camera
-import com.dropbear.EntityId
-import com.dropbear.EntityRef
-import com.dropbear.EntityTransform
-import com.dropbear.asset.AssetHandle
-import com.dropbear.asset.ModelHandle
-import com.dropbear.asset.TextureHandle
-import com.dropbear.input.Gamepad
-import com.dropbear.input.GamepadButton
-import com.dropbear.input.KeyCode
-import com.dropbear.input.MouseButton
-import com.dropbear.math.Transform
-import com.dropbear.math.Vector2D
-import com.dropbear.math.Vector3D
-import com.dropbear.physics.Collider
-import com.dropbear.physics.Index
-import com.dropbear.physics.RigidBody
-import com.dropbear.scene.SceneLoadHandle
-import com.dropbear.scene.SceneLoadStatus
-import com.dropbear.utils.Progress
-
 /**
- * Native functions
+ * Native information about dropbear engine.
  *
- * Class that describes all the functions that can
- * be communicated with the `eucalyptus_core` dynamic library
+ * This class contains handles to various native subsystems such as world, input, graphics, and more. Different
+ * targets (JVM, Native) will have different implementations for managing these handles. Check them out!
  */
-expect class NativeEngine {
-    fun getEntity(label: String): Long?
-    fun getAsset(eucaURI: String): Long?
-
-    fun getEntityLabel(entityHandle: Long): String?
-
-    fun getModel(entityHandle: Long): Long?
-    fun setModel(entityHandle: Long, modelHandle: Long)
-    fun isUsingModel(entityHandle: Long, modelHandle: Long): Boolean
-    fun isModelHandle(id: Long): Boolean
-
-    fun getTexture(entityHandle: Long, name: String): Long?
-    fun setTextureOverride(entityHandle: Long, oldMaterialName: String, newTextureHandle: TextureHandle)
-    fun isUsingTexture(entityHandle: Long, textureHandle: Long): Boolean
-    fun isTextureHandle(id: Long): Boolean
-    fun getTextureName(textureHandle: Long): String?
-    fun getAllTextures(entityHandle: Long): Array<String>
-
-    fun getCamera(label: String): Camera?
-    fun getAttachedCamera(entityId: EntityId): Camera?
-    fun setCamera(camera: Camera);
-
-    fun getTransform(entityId: EntityId): EntityTransform?
-    fun propagateTransform(entityId: EntityId): Transform?
-    fun setTransform(entityId: EntityId, transform: EntityTransform)
-
-    fun getChildren(entityId: EntityId): Array<EntityRef>?
-    fun getChildByLabel(entityId: EntityId, label: String): EntityRef?
-    fun getParent(entityId: EntityId): EntityRef?
-
-    fun switchToSceneImmediate(sceneName: String)
-    fun loadSceneAsync(sceneName: String): SceneLoadHandle?
-    fun loadSceneAsync(sceneName: String, loadingScene: String): SceneLoadHandle?
-    fun switchToSceneAsync(sceneLoadHandle: SceneLoadHandle)
-    fun getSceneLoadProgress(sceneLoadHandle: SceneLoadHandle): Progress
-    fun getSceneLoadStatus(sceneLoadHandle: SceneLoadHandle): SceneLoadStatus
-
-    // ------------------------ MODEL PROPERTIES -------------------------
-
-    fun getStringProperty(entityHandle: Long, label: String): String?
-    fun getIntProperty(entityHandle: Long, label: String): Int?
-    fun getLongProperty(entityHandle: Long, label: String): Long?
-    fun getDoubleProperty(entityHandle: Long, label: String): Double?
-    fun getFloatProperty(entityHandle: Long, label: String): Float?
-    fun getBoolProperty(entityHandle: Long, label: String): Boolean?
-    fun getVec3Property(entityHandle: Long, label: String): FloatArray?
-
-    fun setStringProperty(entityHandle: Long, label: String, value: String)
-    fun setIntProperty(entityHandle: Long, label: String, value: Int)
-    fun setLongProperty(entityHandle: Long, label: String, value: Long)
-    fun setFloatProperty(entityHandle: Long, label: String, value: Double)
-    fun setBoolProperty(entityHandle: Long, label: String, value: Boolean)
-    fun setVec3Property(entityHandle: Long, label: String, value: FloatArray)
-
-
-    // --------------------------- INPUT STATE ---------------------------
-
-    /**
-     * Prints the input state, typically used for debugging.
-     */
-    fun printInputState()
-    fun isKeyPressed(key: KeyCode): Boolean
-    fun getMousePosition(): Vector2D?
-    fun isMouseButtonPressed(button: MouseButton): Boolean
-    fun getMouseDelta(): Vector2D?
-    fun isCursorLocked(): Boolean
-    fun setCursorLocked(locked: Boolean)
-    fun isCursorHidden(): Boolean
-    fun setCursorHidden(hidden: Boolean)
-    fun getLastMousePos(): Vector2D?
-    fun getConnectedGamepads(): List<Gamepad>
-    fun isGamepadButtonPressed(id: Long, button: GamepadButton): Boolean
-
-    // -------------------------------------------------------------------
-
-    // physics stuff
-
-    // EntityRef.kt
-    fun setPhysicsEnabled(entityId: Long, enabled: Boolean)
-    fun isPhysicsEnabled(entityId: Long): Boolean
-    fun getRigidBody(entityId: Long): RigidBody?
-    fun getAllColliders(entityId: Long): List<Collider>
-
-    // physics/RigidBody.kt
-    fun applyImpulse(index: Index, x: Double, y: Double, z: Double)
-    fun applyTorqueImpulse(index: Index, x: Double, y: Double, z: Double)
-    fun setRigidbody(rigidBody: RigidBody)
-    fun getChildColliders(index: Index): List<Collider>
-
-    // physics/Collider.kt
-    fun setCollider(collider: Collider)
-
-    fun quit()
-}
\ No newline at end of file
+expect class NativeEngine
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/input/Gamepad.kt b/src/commonMain/kotlin/com/dropbear/input/Gamepad.kt
index 920a9a0..7664888 100644
--- a/src/commonMain/kotlin/com/dropbear/input/Gamepad.kt
+++ b/src/commonMain/kotlin/com/dropbear/input/Gamepad.kt
@@ -10,13 +10,14 @@ class Gamepad(
     val id: Long,
     val leftStickPosition: Vector2D,
     val rightStickPosition: Vector2D,
-    val native: NativeEngine,
 ) {
     fun isButtonPressed(button: GamepadButton): Boolean {
-        return native.isGamepadButtonPressed(id, button)
+        return isGamepadButtonPressed(id, button)
     }
 
     override fun toString(): String {
         return "Gamepad $id @ ($leftStickPosition ; $rightStickPosition)"
     }
-}
\ No newline at end of file
+}
+
+expect fun Gamepad.isGamepadButtonPressed(id: Long, button: GamepadButton): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/input/InputState.kt b/src/commonMain/kotlin/com/dropbear/input/InputState.kt
index 38a97e7..fd06c75 100644
--- a/src/commonMain/kotlin/com/dropbear/input/InputState.kt
+++ b/src/commonMain/kotlin/com/dropbear/input/InputState.kt
@@ -13,49 +13,16 @@ import com.dropbear.math.Vector2D
  * The InputState does not have any values that can be mutated, only
  * queried. 
  */
-class InputState(private val native: NativeEngine) {
-
-    fun printInputState() {
-        native.printInputState()
-    }
-
-    fun isKeyPressed(key: KeyCode): Boolean {
-        return native.isKeyPressed(key)
-    }
-
-    fun getMousePosition(): Vector2D {
-        return native.getMousePosition() ?: Vector2D(0.0, 0.0)
-    }
-
-    fun isMouseButtonPressed(button: MouseButton): Boolean {
-        return native.isMouseButtonPressed(button)
-    }
-
-    fun getMouseDelta(): Vector2D {
-        return native.getMouseDelta() ?: Vector2D(0.0, 0.0)
-    }
-
-    fun isCursorLocked(): Boolean {
-        return native.isCursorLocked()
-    }
-
-    fun setCursorLocked(locked: Boolean) {
-        return native.setCursorLocked(locked)
-    }
-
-    fun getLastMousePos(): Vector2D {
-        return native.getLastMousePos() ?: Vector2D(0.0, 0.0)
-    }
-
-    fun isCursorHidden(): Boolean {
-        return native.isCursorHidden()
-    }
-
-    fun setCursorHidden(hidden: Boolean) {
-        return native.setCursorHidden(hidden)
-    }
-
-    fun getConnectedGamepads(): List<Gamepad> {
-        return native.getConnectedGamepads()
-    }
+expect class InputState() {
+    fun printInputState()
+    fun isKeyPressed(key: KeyCode): Boolean
+    fun getMousePosition(): Vector2D
+    fun isMouseButtonPressed(button: MouseButton): Boolean
+    fun getMouseDelta(): Vector2D
+    fun isCursorLocked(): Boolean
+    fun setCursorLocked(locked: Boolean)
+    fun getLastMousePos(): Vector2D
+    fun isCursorHidden(): Boolean
+    fun setCursorHidden(hidden: Boolean)
+    fun getConnectedGamepads(): List<Gamepad>
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/physics/Collider.kt b/src/commonMain/kotlin/com/dropbear/physics/Collider.kt
index 2ab0100..70c09b3 100644
--- a/src/commonMain/kotlin/com/dropbear/physics/Collider.kt
+++ b/src/commonMain/kotlin/com/dropbear/physics/Collider.kt
@@ -1,37 +1,52 @@
 package com.dropbear.physics
 
 import com.dropbear.EntityId
-import com.dropbear.ffi.NativeEngine
 import com.dropbear.math.Vector3D
 
 class Collider(
     internal val index: Index,
     internal val entity: EntityId,
     internal val id: UInt,
-    internal val native: NativeEngine
 ) {
     var colliderShape: ColliderShape
-        get() = native.getColliderShape(this)
-        set(value) = native.setColliderShape(this, value)
+        get() = getColliderShape(this)
+        set(value) = setColliderShape(this, value)
     var density: Double
-        get() = native.getColliderDensity(this)
-        set(value) = native.setColliderDensity(this, value)
+        get() = getColliderDensity(this)
+        set(value) = setColliderDensity(this, value)
     var friction: Double
-        get() = native.getColliderFriction(this)
-        set(value) = native.setColliderFriction(this, value)
+        get() = getColliderFriction(this)
+        set(value) = setColliderFriction(this, value)
     var restitution: Double
-        get() = native.getColliderRestitution(this)
-        set(value) = native.setColliderRestitution(this, value)
+        get() = getColliderRestitution(this)
+        set(value) = setColliderRestitution(this, value)
     var isSensor: Boolean
-        get() = native.getColliderIsSensor(this)
-        set(value) = native.setColliderIsSensor(this, value)
+        get() = getColliderIsSensor(this)
+        set(value) = setColliderIsSensor(this, value)
     var translation: Vector3D
-        get() = native.getColliderTranslation(this)
-        set(value) = native.setColliderTranslation(this, value)
+        get() = getColliderTranslation(this)
+        set(value) = setColliderTranslation(this, value)
     var rotation: Vector3D
-        get() = native.getColliderRotation(this)
-        set(value) = native.setColliderRotation(this, value)
+        get() = getColliderRotation(this)
+        set(value) = setColliderRotation(this, value)
     var mass: Double
-        get() = native.getColliderMass(this)
-        set(value) = native.setColliderMass(this, value)
-}
\ No newline at end of file
+        get() = getColliderMass(this)
+        set(value) = setColliderMass(this, value)
+}
+
+expect fun Collider.getColliderShape(collider: Collider): ColliderShape
+expect fun Collider.setColliderShape(collider: Collider, shape: ColliderShape)
+expect fun Collider.getColliderDensity(collider: Collider): Double
+expect fun Collider.setColliderDensity(collider: Collider, density: Double)
+expect fun Collider.getColliderFriction(collider: Collider): Double
+expect fun Collider.setColliderFriction(collider: Collider, friction: Double)
+expect fun Collider.getColliderRestitution(collider: Collider): Double
+expect fun Collider.setColliderRestitution(collider: Collider, restitution: Double)
+expect fun Collider.getColliderIsSensor(collider: Collider): Boolean
+expect fun Collider.setColliderIsSensor(collider: Collider, isSensor: Boolean)
+expect fun Collider.getColliderTranslation(collider: Collider): Vector3D
+expect fun Collider.setColliderTranslation(collider: Collider, translation: Vector3D)
+expect fun Collider.getColliderRotation(collider: Collider): Vector3D
+expect fun Collider.setColliderRotation(collider: Collider, rotation: Vector3D)
+expect fun Collider.getColliderMass(collider: Collider): Double
+expect fun Collider.setColliderMass(collider: Collider, mass: Double)
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/physics/ColliderGroup.kt b/src/commonMain/kotlin/com/dropbear/physics/ColliderGroup.kt
new file mode 100644
index 0000000..4f0a8ae
--- /dev/null
+++ b/src/commonMain/kotlin/com/dropbear/physics/ColliderGroup.kt
@@ -0,0 +1,23 @@
+package com.dropbear.physics
+
+import com.dropbear.ecs.Component
+import com.dropbear.EntityId
+import com.dropbear.ecs.ComponentType
+
+class ColliderGroup(
+    entity: EntityId,
+) : Component(entity, "ColliderGroup") {
+    fun getColliders(): List<Collider> {
+        return getColliderGroupColliders(this)
+    }
+
+    companion object : ComponentType<ColliderGroup> {
+        override fun get(entityId: EntityId): ColliderGroup? {
+            return if (colliderGroupExistsForEntity(entityId)) ColliderGroup(entityId) else null
+        }
+    }
+}
+
+expect fun ColliderGroup.getColliderGroupColliders(colliderGroup: ColliderGroup): List<Collider>
+
+expect fun colliderGroupExistsForEntity(entityId: EntityId): Boolean
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/physics/ColliderShape.kt b/src/commonMain/kotlin/com/dropbear/physics/ColliderShape.kt
index c72c9c5..7384658 100644
--- a/src/commonMain/kotlin/com/dropbear/physics/ColliderShape.kt
+++ b/src/commonMain/kotlin/com/dropbear/physics/ColliderShape.kt
@@ -1,80 +1,30 @@
 package com.dropbear.physics
 
 import com.dropbear.math.Vector3D
-import kotlin.math.PI
-import kotlin.math.pow
 
 sealed class ColliderShape {
 
     /**
      * Box shape with half-extents (half-width, half-height, half-depth).
      */
-    data class Box(val halfExtents: Vector3D) : ColliderShape() {
-        /**
-         * Returns the volume of the shape/box.
-         *
-         * In this case, volume is calculated as: [halfExtents].x * [halfExtents].y * [halfExtents].z
-         */
-        fun volume(): Double {
-            return halfExtents.x * halfExtents.y * halfExtents.z
-        }
-    }
+    data class Box(val halfExtents: Vector3D) : ColliderShape()
 
     /**
      * Sphere shape with radius.
      */
-    data class Sphere(val radius: Float) : ColliderShape() {
-        /**
-         * Returns the volume of the shape/sphere.
-         *
-         * In this case, volume is calculated as: (4/3) * π * [radius]^3
-         */
-        fun volume(): Double {
-            return (4.0 / 3.0) * PI * radius.toDouble().pow(3.0)
-        }
-    }
+    data class Sphere(val radius: Float) : ColliderShape()
 
     /**
      * Capsule shape along Y-axis.
      */
-    data class Capsule(val halfHeight: Float, val radius: Float) : ColliderShape() {
-        /**
-         * Returns the volume of the shape/capsule.
-         *
-         * In this case, volume is calculated as: (4/3) * π * [radius]^3 + π * [radius]^2 * (2 * [halfHeight])
-         */
-        fun volume(): Double {
-            val sphereVolume = (4.0 / 3.0) * PI * radius.toDouble().pow(3.0)
-            val cylinderVolume = PI * radius.toDouble().pow(2.0) * (2.0 * halfHeight.toDouble())
-            return sphereVolume + cylinderVolume
-        }
-    }
+    data class Capsule(val halfHeight: Float, val radius: Float) : ColliderShape()
 
     /**
      * Cylinder shape along Y-axis.
      */
-    data class Cylinder(val halfHeight: Float, val radius: Float) : ColliderShape() {
-        /**
-         * Returns the volume of the shape/cylinder.
-         *
-         * In this case, volume is calculated as: π * [radius]^2 * (2 * [halfHeight])
-         */
-        fun volume(): Double {
-            return PI * radius.toDouble().pow(2.0) * (2.0 * halfHeight.toDouble())
-        }
-    }
-
+    data class Cylinder(val halfHeight: Float, val radius: Float) : ColliderShape()
     /**
      * Cone shape along Y-axis.
      */
-    data class Cone(val halfHeight: Float, val radius: Float) : ColliderShape() {
-        /**
-         * Returns the volume of the shape/cone.
-         *
-         * In this case, volume is calculated as: (1/3) * π * [radius]^2 * (2 * [halfHeight])
-         */
-        fun volume(): Double {
-            return (1.0 / 3.0) * PI * radius.toDouble().pow(2.0) * (2.0 * halfHeight.toDouble())
-        }
-    }
+    data class Cone(val halfHeight: Float, val radius: Float) : ColliderShape()
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/physics/RigidBody.kt b/src/commonMain/kotlin/com/dropbear/physics/RigidBody.kt
index f90e0a9..2dfc72b 100644
--- a/src/commonMain/kotlin/com/dropbear/physics/RigidBody.kt
+++ b/src/commonMain/kotlin/com/dropbear/physics/RigidBody.kt
@@ -1,45 +1,47 @@
 package com.dropbear.physics
 
+import com.dropbear.ecs.Component
 import com.dropbear.EntityId
-import com.dropbear.exceptionOnError
-import com.dropbear.ffi.NativeEngine
+import com.dropbear.ecs.ComponentType
 import com.dropbear.math.Vector3D
 
 class RigidBody(
     internal val index: Index,
     internal val entity: EntityId,
-    internal var native: NativeEngine,
-) {
+) : Component(entity, "RigidBody") {
     var rigidBodyMode: RigidBodyMode
-        get() = native.getRigidbodyMode(this)
-        set(value) = native.setRigidbodyMode(this, value)
+        get() = getRigidbodyMode(this)
+        set(value) = setRigidbodyMode(this, value)
     var gravityScale: Double
-        get() = native.getRigidbodyGravityScale(this)
-        set(value) = native.setRigidbodyGravityScale(this, value)
+        get() = getRigidbodyGravityScale(this)
+        set(value) = setRigidbodyGravityScale(this, value)
     var canSleep: Boolean
-        get() = native.getRigidbodyCanSleep(this)
-        set(value) = native.setRigidbodyCanSleep(this, value)
+        get() = getRigidbodyCanSleep(this)
+        set(value) = setRigidbodyCanSleep(this, value)
     var ccdEnabled: Boolean
-        get() = native.getRigidbodyCcdEnabled(this)
-        set(value) = native.setRigidbodyCcdEnabled(this, value)
+        get() = getRigidbodyCcdEnabled(this)
+        set(value) = setRigidbodyCcdEnabled(this, value)
     var linearVelocity: Vector3D
-        get() = native.getRigidbodyLinearVelocity(this)
-        set(value) = native.setRigidbodyLinearVelocity(this, value)
+        get() = getRigidbodyLinearVelocity(this)
+        set(value) = setRigidbodyLinearVelocity(this, value)
     var angularVelocity: Vector3D
-        get() = native.getRigidbodyAngularVelocity(this)
-        set(value) = native.setRigidbodyAngularVelocity(this, value)
+        get() = getRigidbodyAngularVelocity(this)
+        set(value) = setRigidbodyAngularVelocity(this, value)
     var linearDamping: Double
-        get() = native.getRigidbodyLinearDamping(this)
-        set(value) = native.setRigidbodyLinearDamping(this, value)
+        get() = getRigidbodyLinearDamping(this)
+        set(value) = setRigidbodyLinearDamping(this, value)
     var angularDamping: Double
-        get() = native.getRigidbodyAngularDamping(this)
-        set(value) = native.setRigidbodyAngularDamping(this, value)
+        get() = getRigidbodyAngularDamping(this)
+        set(value) = setRigidbodyAngularDamping(this, value)
     var lockTranslation: AxisLock
-        get() = native.getRigidbodyLockTranslation(this)
-        set(value) = native.setRigidbodyLockTranslation(this, value)
+        get() = getRigidbodyLockTranslation(this)
+        set(value) = setRigidbodyLockTranslation(this, value)
     var lockRotation: AxisLock
-        get() = native.getRigidbodyLockRotation(this)
-        set(value) = native.setRigidbodyLockRotation(this, value)
+        get() = getRigidbodyLockRotation(this)
+        set(value) = setRigidbodyLockRotation(this, value)
+    var childColliders: List<EntityId>
+        get() = getRigidbodyChildren(this)
+        set(value) = setRigidbodyChildren(this, value)
 
     /**
      * Applies an instant force.
@@ -56,13 +58,9 @@ class RigidBody(
      * Typically used for jumping or explosions.
      */
     fun applyImpulse(x: Double, y: Double, z: Double) {
-        val native = native ?: if (exceptionOnError) {
-            throw IllegalStateException("Native engine is not initialised")
-        } else {
-            return
-        }
-        return native.applyImpulse(index, x, y, z)
+        return applyImpulse(index, x, y, z)
     }
+
     /**
      * Applies an instant torque/rotational impulse.
      *
@@ -78,39 +76,40 @@ class RigidBody(
      * Typically used for spinning objects.
      */
     fun applyTorqueImpulse(x: Double, y: Double, z: Double) {
-        val native = native ?: if (exceptionOnError) {
-            throw IllegalStateException("Native engine is not initialised")
-        } else {
-            return
-        }
-        return native.applyTorqueImpulse(index, x, y, z)
+        return applyTorqueImpulse(index, x, y, z)
     }
 
-    /**
-     * Pushes your changes to the [RigidBody] back to the physics engine.
-     */
-    fun setRigidbody() {
-        val native = native ?: if (exceptionOnError) {
-            throw IllegalStateException("Native engine is not initialised")
-        } else {
-            return
+    companion object : ComponentType<RigidBody> {
+        override fun get(entityId: EntityId): RigidBody? {
+            val index = rigidBodyExistsForEntity(entityId)
+            return if (index != null) RigidBody(index, entityId) else null
         }
-
-        native.setRigidbody(this)
     }
+}
 
-    /**
-     * Fetches all child [Collider] under this [RigidBody].
-     *
-     * Returns `null` if there is no component such as `ColliderGroup` attached to the
-     * entity, or an [emptyList] if there are no child colliders.
-     */
-    fun getChildColliders(): List<Collider>? {
-        val native = native ?: if (exceptionOnError) {
-            throw IllegalStateException("Native engine is not initialised")
-        } else {
-            return null
-        }
-        return native.getChildColliders(index)
-    }
-}
\ No newline at end of file
+expect fun RigidBody.getRigidbodyMode(rigidBody: RigidBody): RigidBodyMode
+expect fun RigidBody.setRigidbodyMode(rigidBody: RigidBody, mode: RigidBodyMode)
+expect fun RigidBody.getRigidbodyGravityScale(rigidBody: RigidBody): Double
+expect fun RigidBody.setRigidbodyGravityScale(rigidBody: RigidBody, gravityScale: Double)
+expect fun RigidBody.getRigidbodyCanSleep(rigidBody: RigidBody): Boolean
+expect fun RigidBody.setRigidbodyCanSleep(rigidBody: RigidBody, canSleep: Boolean)
+expect fun RigidBody.getRigidbodyCcdEnabled(rigidBody: RigidBody): Boolean
+expect fun RigidBody.setRigidbodyCcdEnabled(rigidBody: RigidBody, ccdEnabled: Boolean)
+expect fun RigidBody.getRigidbodyLinearVelocity(rigidBody: RigidBody): Vector3D
+expect fun RigidBody.setRigidbodyLinearVelocity(rigidBody: RigidBody, linearVelocity: Vector3D)
+expect fun RigidBody.getRigidbodyAngularVelocity(rigidBody: RigidBody): Vector3D
+expect fun RigidBody.setRigidbodyAngularVelocity(rigidBody: RigidBody, angularVelocity: Vector3D)
+expect fun RigidBody.getRigidbodyLinearDamping(rigidBody: RigidBody): Double
+expect fun RigidBody.setRigidbodyLinearDamping(rigidBody: RigidBody, linearDamping: Double)
+expect fun RigidBody.getRigidbodyAngularDamping(rigidBody: RigidBody): Double
+expect fun RigidBody.setRigidbodyAngularDamping(rigidBody: RigidBody, angularDamping: Double)
+expect fun RigidBody.getRigidbodyLockTranslation(rigidBody: RigidBody): AxisLock
+expect fun RigidBody.setRigidbodyLockTranslation(rigidBody: RigidBody, lockTranslation: AxisLock)
+expect fun RigidBody.getRigidbodyLockRotation(rigidBody: RigidBody): AxisLock
+expect fun RigidBody.setRigidbodyLockRotation(rigidBody: RigidBody, lockRotation: AxisLock)
+expect fun RigidBody.getRigidbodyChildren(rigidBody: RigidBody): List<EntityId>
+expect fun RigidBody.setRigidbodyChildren(rigidBody: RigidBody, children: List<EntityId>)
+expect fun RigidBody.applyImpulse(index: Index, x: Double, y: Double, z: Double)
+expect fun RigidBody.applyTorqueImpulse(index: Index, x: Double, y: Double, z: Double)
+
+expect fun rigidBodyExistsForEntity(entityId: EntityId): Index?
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/scene/SceneLoadHandle.kt b/src/commonMain/kotlin/com/dropbear/scene/SceneLoadHandle.kt
index fa9a446..503b233 100644
--- a/src/commonMain/kotlin/com/dropbear/scene/SceneLoadHandle.kt
+++ b/src/commonMain/kotlin/com/dropbear/scene/SceneLoadHandle.kt
@@ -8,7 +8,7 @@ import com.dropbear.ffi.NativeEngine
 /**
  * A handle that allows you to check the state of an async scene load.
  */
-class SceneLoadHandle(val id: Long, val sceneName: String, val native: NativeEngine) {
+class SceneLoadHandle(val id: Long, val sceneName: String) {
     /**
      * Switches the scene to the requested scene.
      *
@@ -19,18 +19,18 @@ class SceneLoadHandle(val id: Long, val sceneName: String, val native: NativeEng
      * is enabled or not.
      */
     fun switchTo() {
-        native.switchToSceneAsync(this)
+        switchToSceneAsync()
     }
 
     /**
      * Returns the progress of scene load.
      */
     fun progress(): Progress {
-        return native.getSceneLoadProgress(this)
+        return getSceneLoadProgress()
     }
 
     fun status(): SceneLoadStatus {
-        return native.getSceneLoadStatus(this)
+        return getSceneLoadStatus()
     }
 
     /**
@@ -61,4 +61,8 @@ class SceneLoadHandle(val id: Long, val sceneName: String, val native: NativeEng
     fun raw(): Long {
         return id
     }
-}
\ No newline at end of file
+}
+
+expect fun SceneLoadHandle.switchToSceneAsync(): SceneLoadHandle
+expect fun SceneLoadHandle.getSceneLoadProgress(): Progress
+expect fun SceneLoadHandle.getSceneLoadStatus(): SceneLoadStatus
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/scene/SceneManager.kt b/src/commonMain/kotlin/com/dropbear/scene/SceneManager.kt
index cf53fcf..301e522 100644
--- a/src/commonMain/kotlin/com/dropbear/scene/SceneManager.kt
+++ b/src/commonMain/kotlin/com/dropbear/scene/SceneManager.kt
@@ -1,8 +1,6 @@
 package com.dropbear.scene
 
-import com.dropbear.ffi.NativeEngine
-
-class SceneManager(val native: NativeEngine) {
+class SceneManager() {
     /**
      * Loads the resources of a scene asynchronously.
      *
@@ -11,20 +9,20 @@ class SceneManager(val native: NativeEngine) {
      * and check its status.
      */
     fun loadSceneAsync(sceneName: String): SceneLoadHandle? {
-        return native.loadSceneAsync(sceneName)
+        return loadSceneAsyncNative(sceneName)
     }
 
     /**
      * Loads the resources of a scene asynchronously.
      *
-     * This function is an overload, which contains a `loading_scene` parameter.
+     * This function is an overload, which contains a `loadingScene` parameter.
      * This allows you to specify a scene to display while the resources are being loaded.
      *
      * It must be preloaded (through the scene settings menu in eucalyptus-editor). If not preloaded, it will
-     * block/freeze the main thread/window to load the `loading_scene`
+     * block/freeze the main thread/window to load the `loadingScene`
      */
-    fun loadSceneAsync(sceneName: String, loading_scene: String): SceneLoadHandle? {
-        return native.loadSceneAsync(sceneName, loading_scene)
+    fun loadSceneAsync(sceneName: String, loadingScene: String): SceneLoadHandle? {
+        return loadSceneAsyncNative(sceneName, loadingScene)
     }
 
     /**
@@ -35,7 +33,7 @@ class SceneManager(val native: NativeEngine) {
      * as 3D objects. Use [loadSceneAsync] instead.
      */
     fun switchToSceneImmediate(sceneName: String) {
-        return native.switchToSceneImmediate(sceneName)
+        return switchToSceneImmediateNative(sceneName)
     }
 
     /**
@@ -44,4 +42,8 @@ class SceneManager(val native: NativeEngine) {
     fun getCurrentScene(): SceneMetadata {
         TODO("Not implemented yet...")
     }
-}
\ No newline at end of file
+}
+
+expect fun SceneManager.loadSceneAsyncNative(sceneName: String): SceneLoadHandle?
+expect fun SceneManager.loadSceneAsyncNative(sceneName: String, loading_scene: String): SceneLoadHandle?
+expect fun SceneManager.switchToSceneImmediateNative(sceneName: String)
\ No newline at end of file
diff --git a/src/commonMain/kotlin/com/dropbear/ui/UIManager.kt b/src/commonMain/kotlin/com/dropbear/ui/UIManager.kt
deleted file mode 100644
index 477288e..0000000
--- a/src/commonMain/kotlin/com/dropbear/ui/UIManager.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.dropbear.ui
-
-import com.dropbear.ffi.NativeEngine
-
-class UIManager(native: NativeEngine) {
-
-}
\ No newline at end of file
diff --git a/src/jvmMain/java/com/dropbear/NativeEngineLoader.java b/src/jvmMain/java/com/dropbear/NativeEngineLoader.java
deleted file mode 100644
index c267819..0000000
--- a/src/jvmMain/java/com/dropbear/NativeEngineLoader.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.dropbear;
-
-import java.lang.System;
-
-public class NativeEngineLoader {
-    private static boolean loaded = false;
-
-    /// Ensures that the eucalyptus_core library is loaded before accessing
-    /// any of the JNI static functions.
-    public static void ensureLoaded() {
-        if (!loaded) {
-            System.loadLibrary("eucalyptus_core");
-            loaded = true;
-        }
-    }
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/DropbearEngineNative.java b/src/jvmMain/java/com/dropbear/ffi/DropbearEngineNative.java
deleted file mode 100644
index dedb229..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/DropbearEngineNative.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.dropbear.ffi;
-
-import com.dropbear.NativeEngineLoader;
-
-public class DropbearEngineNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native void quit(long graphicsHandle);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/InputStateNative.java b/src/jvmMain/java/com/dropbear/ffi/InputStateNative.java
deleted file mode 100644
index 0beb819..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/InputStateNative.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.dropbear.ffi;
-
-import com.dropbear.NativeEngineLoader;
-import com.dropbear.input.Gamepad;
-
-public class InputStateNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    // input
-    public static native void printInputState(long inputHandle);
-    public static native boolean isKeyPressed(long inputHandle, int ordinal);
-    public static native float[] getMousePosition(long inputHandle);
-    public static native boolean isMouseButtonPressed(long inputHandle, int ordinal);
-    public static native float[] getMouseDelta(long inputHandle);
-    public static native boolean isCursorLocked(long inputHandle);
-    public static native void setCursorLocked(long inputHandle, long graphicsHandle, boolean locked);
-    public static native float[] getLastMousePos(long inputHandle);
-    public static native boolean isCursorHidden(long inputHandle);
-    public static native void setCursorHidden(long inputHandle, long graphicsHandle, boolean hidden);
-
-    // gamepad stuff
-    public static native Gamepad[] getConnectedGamepads(long inputHandle);
-    public static native boolean isGamepadButtonPressed(long inputHandle, long gamepadId, int gamepadButtonOrdinal);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/JNINative.java b/src/jvmMain/java/com/dropbear/ffi/JNINative.java
deleted file mode 100644
index 5b8285e..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/JNINative.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.dropbear.ffi;
-
-import com.dropbear.Camera;
-import com.dropbear.EntityTransform;
-import com.dropbear.NativeEngineLoader;
-import com.dropbear.math.Transform;
-import com.dropbear.scene.SceneLoadHandle;
-import com.dropbear.utils.Progress;
-
-/**
- * Describes all the functions that are available in
- * the `eucalyptus_core` dynamic library. 
- */
-public class JNINative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-    public static native long getEntity(long worldHandle, String label);
-    public static native long getAsset(long assetRegistryHandle, String eucaURI);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/PhysicsNative.java b/src/jvmMain/java/com/dropbear/ffi/PhysicsNative.java
deleted file mode 100644
index 069df3d..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/PhysicsNative.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.dropbear.ffi;
-
-import com.dropbear.NativeEngineLoader;
-import com.dropbear.physics.Collider;
-import com.dropbear.physics.RigidBody;
-
-public class PhysicsNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native void setPhysicsEnabled(long worldHandle, long physicsEngineHandle, long entityId, boolean enabled);
-    public static native boolean isPhysicsEnabled(long worldHandle, long physicsEngineHandle, long entityId);
-    public static native RigidBody getRigidBody(long worldHandle, long physicsEngineHandle, long entityId);
-    public static native Collider[] getAllColliders(long worldHandle, long physicsEngineHandle, long entityId);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/SceneNative.java b/src/jvmMain/java/com/dropbear/ffi/SceneNative.java
deleted file mode 100644
index 3b0e828..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/SceneNative.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.dropbear.ffi;
-
-import com.dropbear.NativeEngineLoader;
-import com.dropbear.scene.SceneLoadHandle;
-import com.dropbear.scene.SceneLoadStatus;
-import com.dropbear.utils.Progress;
-
-public class SceneNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native SceneLoadHandle loadSceneAsync(long commandBufferHandle, long sceneLoader, String sceneName, NativeEngine engine);
-    public static native SceneLoadHandle loadSceneAsync(long commandBufferHandle, long sceneLoader, String sceneName, String loadingScene, NativeEngine engine);
-    public static native void switchToSceneAsync(long commandBufferHandle, SceneLoadHandle handle);
-    public static native void switchToSceneImmediate(long commandBufferHandle, String sceneName);
-    public static native Progress getSceneLoadProgress(long sceneLoader, SceneLoadHandle handle);
-    public static native SceneLoadStatus getSceneLoadStatus(long sceneLoader, SceneLoadHandle handle);
-}
\ No newline at end of file
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/CameraNative.java b/src/jvmMain/java/com/dropbear/ffi/components/CameraNative.java
deleted file mode 100644
index 0614a62..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/CameraNative.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.Camera;
-import com.dropbear.NativeEngineLoader;
-
-public class CameraNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native Camera getCamera(long worldHandle, String label);
-    public static native Camera getAttachedCamera(long worldHandle, long entityHandle);
-    public static native void setCamera(long worldHandle, Camera camera);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/ColliderNative.java b/src/jvmMain/java/com/dropbear/ffi/components/ColliderNative.java
deleted file mode 100644
index 59795c7..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/ColliderNative.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.physics.Collider;
-
-public class ColliderNative {
-    static {
-        com.dropbear.NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native void setCollider(long worldHandle, long physicsEngineHandle, Collider collider);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/CustomPropertiesNative.java b/src/jvmMain/java/com/dropbear/ffi/components/CustomPropertiesNative.java
deleted file mode 100644
index b0a9ae6..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/CustomPropertiesNative.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.NativeEngineLoader;
-
-public class CustomPropertiesNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    // properties
-    public static native String getStringProperty(long worldHandle, long entityHandle, String label);
-    public static native int getIntProperty(long worldHandle, long entityHandle, String label);
-    public static native long getLongProperty(long worldHandle, long entityHandle, String label);
-    public static native double getFloatProperty(long worldHandle, long entityHandle, String label);
-    public static native boolean getBoolProperty(long worldHandle, long entityHandle, String label);
-    public static native float[] getVec3Property(long worldHandle, long entityHandle, String label);
-
-    public static native void setStringProperty(long worldHandle, long entityHandle, String label, String value);
-    public static native void setIntProperty(long worldHandle, long entityHandle, String label, int value);
-    public static native void setLongProperty(long worldHandle, long entityHandle, String label, long value);
-    public static native void setFloatProperty(long worldHandle, long entityHandle, String label, double value);
-    public static native void setBoolProperty(long worldHandle, long entityHandle, String label, boolean value);
-    public static native void setVec3Property(long worldHandle, long entityHandle, String label, float[] value);
-
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/EntityTransformNative.java b/src/jvmMain/java/com/dropbear/ffi/components/EntityTransformNative.java
deleted file mode 100644
index 4e92fbf..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/EntityTransformNative.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.EntityTransform;
-import com.dropbear.NativeEngineLoader;
-import com.dropbear.math.Transform;
-
-public class EntityTransformNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native EntityTransform getTransform(long handle, long entityHandle);
-    public static native Transform propagateTransform(long worldHandle, long id);
-    public static native void setTransform(long worldHandle, long id, EntityTransform transform);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/HierarchyNative.java b/src/jvmMain/java/com/dropbear/ffi/components/HierarchyNative.java
deleted file mode 100644
index a5f51e6..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/HierarchyNative.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.NativeEngineLoader;
-
-public class HierarchyNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native long[] getChildren(long worldHandle, long entityId);
-    public static native long getChildByLabel(long worldHandle, long entityId, String label);
-    public static native long getParent(long worldHandle, long entityId);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/LabelNative.java b/src/jvmMain/java/com/dropbear/ffi/components/LabelNative.java
deleted file mode 100644
index 9b51b86..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/LabelNative.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.NativeEngineLoader;
-
-public class LabelNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native String getEntityLabel(long worldHandle, long entityHandle);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/MeshRendererNative.java b/src/jvmMain/java/com/dropbear/ffi/components/MeshRendererNative.java
deleted file mode 100644
index 0c32801..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/MeshRendererNative.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.NativeEngineLoader;
-
-public class MeshRendererNative {
-    static {
-        NativeEngineLoader.ensureLoaded();
-    }
-
-    // model
-    public static native long getModel(long worldHandle, long entityHandle);
-    public static native void setModel(long worldHandle, long assetHandle, long entityHandle, long modelHandle);
-    public static native boolean isModelHandle(long assetRegistryHandle, long handle);
-    public static native boolean isUsingModel(long worldHandle, long entityHandle, long modelHandle);
-
-    // texture
-    public static native long getTexture(long worldHandle, long assetHandle, long entityHandle, String name);
-    public static native String getTextureName(long assetHandle, long textureHandle);
-    public static native void setTexture(long worldHandle, long assetRegistryHandle, long entityHandle,
-                                         String oldMaterialName, long textureHandle);
-    public static native boolean isTextureHandle(long assetRegistryHandle, long handle);
-    public static native boolean isUsingTexture(long worldHandle, long entityHandle, long textureHandle);
-
-    public static native String[] getAllTextures(long worldHandle, long entityHandle);
-}
diff --git a/src/jvmMain/java/com/dropbear/ffi/components/RigidBodyNative.java b/src/jvmMain/java/com/dropbear/ffi/components/RigidBodyNative.java
deleted file mode 100644
index fa4f6c0..0000000
--- a/src/jvmMain/java/com/dropbear/ffi/components/RigidBodyNative.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.dropbear.ffi.components;
-
-import com.dropbear.physics.Collider;
-import com.dropbear.physics.Index;
-import com.dropbear.physics.RigidBody;
-
-public class RigidBodyNative {
-    static {
-        com.dropbear.NativeEngineLoader.ensureLoaded();
-    }
-
-    public static native void applyImpulse(long physicsEngineHandle, Index rigidBodyId, double x, double y, double z);
-    public static native void applyTorqueImpulse(long physicsEngineHandle, Index rigidBodyId, double x, double y, double z);
-
-    public static native void setRigidBody(long worldHandle, long physicsEngineHandle, RigidBody rigidBody);
-    public static native Collider[] getChildColliders(long worldHandle, long physicsEngineHandle, Index rigidBodyId);
-}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/Camera.jvm.kt b/src/jvmMain/kotlin/com/dropbear/Camera.jvm.kt
new file mode 100644
index 0000000..ca85207
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/Camera.jvm.kt
@@ -0,0 +1,81 @@
+package com.dropbear
+
+import com.dropbear.math.Vector3D
+
+actual fun Camera.getCameraEye(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraEye(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraTarget(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraTarget(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraUp(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraUp(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraAspect(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.getCameraFovY(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraFovY(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraZNear(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraZNear(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraZFar(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraZFar(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraYaw(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraYaw(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraPitch(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraPitch(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraSpeed(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraSpeed(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraSensitivity(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraSensitivity(entity: EntityId, value: Double) {
+}
+
+actual fun cameraExistsForEntity(entity: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/CustomProperties.jvm.kt b/src/jvmMain/kotlin/com/dropbear/CustomProperties.jvm.kt
new file mode 100644
index 0000000..8923627
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/CustomProperties.jvm.kt
@@ -0,0 +1,93 @@
+package com.dropbear
+
+actual fun CustomProperties.getStringProperty(
+    entityHandle: Long,
+    label: String
+): String? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getIntProperty(entityHandle: Long, label: String): Int? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getLongProperty(
+    entityHandle: Long,
+    label: String
+): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getDoubleProperty(
+    entityHandle: Long,
+    label: String
+): Double? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getFloatProperty(
+    entityHandle: Long,
+    label: String
+): Float? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getBoolProperty(
+    entityHandle: Long,
+    label: String
+): Boolean? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getVec3Property(
+    entityHandle: Long,
+    label: String
+): FloatArray? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.setStringProperty(
+    entityHandle: Long,
+    label: String,
+    value: String
+) {
+}
+
+actual fun CustomProperties.setIntProperty(
+    entityHandle: Long,
+    label: String,
+    value: Int
+) {
+}
+
+actual fun CustomProperties.setLongProperty(
+    entityHandle: Long,
+    label: String,
+    value: Long
+) {
+}
+
+actual fun CustomProperties.setFloatProperty(
+    entityHandle: Long,
+    label: String,
+    value: Double
+) {
+}
+
+actual fun CustomProperties.setBoolProperty(
+    entityHandle: Long,
+    label: String,
+    value: Boolean
+) {
+}
+
+actual fun CustomProperties.setVec3Property(
+    entityHandle: Long,
+    label: String,
+    value: FloatArray
+) {
+}
+
+actual fun customPropertiesExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/DropbearEngine.jvm.kt b/src/jvmMain/kotlin/com/dropbear/DropbearEngine.jvm.kt
new file mode 100644
index 0000000..ed78c58
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/DropbearEngine.jvm.kt
@@ -0,0 +1,16 @@
+package com.dropbear
+
+actual fun getEntity(label: String): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun getCamera(label: String): Camera? {
+    TODO("Not yet implemented")
+}
+
+actual fun getAsset(eucaURI: String): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun quit() {
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/DynamicLibraryLoader.java b/src/jvmMain/kotlin/com/dropbear/DynamicLibraryLoader.java
new file mode 100644
index 0000000..e7aa643
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/DynamicLibraryLoader.java
@@ -0,0 +1,12 @@
+package com.dropbear;
+
+/// Interface for dynamic library loading, allowing for custom components not within the dropbear component
+/// library.
+public interface DynamicLibraryLoader {
+    /// Ensures that the library is loaded before accessing
+    /// any of the JNI static functions.
+    void ensureLoaded();
+
+    /// Forces the library to have a loaded boolean variable.
+    boolean isLoaded();
+}
diff --git a/src/jvmMain/kotlin/com/dropbear/EntityRef.jvm.kt b/src/jvmMain/kotlin/com/dropbear/EntityRef.jvm.kt
new file mode 100644
index 0000000..a607a2c
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/EntityRef.jvm.kt
@@ -0,0 +1,20 @@
+package com.dropbear
+
+actual fun EntityRef.getEntityLabel(entity: EntityId): String? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getChildren(entityId: EntityId): Array<EntityRef>? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getChildByLabel(
+    entityId: EntityId,
+    label: String
+): EntityRef? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getParent(entityId: EntityId): EntityRef? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/EntityTransform.jvm.kt b/src/jvmMain/kotlin/com/dropbear/EntityTransform.jvm.kt
new file mode 100644
index 0000000..4291a56
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/EntityTransform.jvm.kt
@@ -0,0 +1,31 @@
+package com.dropbear
+
+import com.dropbear.math.Transform
+
+actual fun EntityTransform.getLocalTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityTransform.setLocalTransform(
+    entityId: EntityId,
+    transform: Transform
+) {
+}
+
+actual fun EntityTransform.getWorldTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityTransform.setWorldTransform(
+    entityId: EntityId,
+    transform: Transform
+) {
+}
+
+actual fun EntityTransform.propagateTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun entityTransformExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/EucalyptusCoreLoader.java b/src/jvmMain/kotlin/com/dropbear/EucalyptusCoreLoader.java
new file mode 100644
index 0000000..7cf5c14
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/EucalyptusCoreLoader.java
@@ -0,0 +1,20 @@
+package com.dropbear;
+
+import java.lang.System;
+
+public class EucalyptusCoreLoader implements DynamicLibraryLoader {
+    private static boolean loaded = false;
+
+    @Override
+    public void ensureLoaded() {
+        if (!loaded) {
+            System.loadLibrary("eucalyptus_core");
+            loaded = true;
+        }
+    }
+
+    @Override
+    public boolean isLoaded() {
+        return loaded;
+    }
+}
diff --git a/src/jvmMain/kotlin/com/dropbear/MeshRenderer.jvm.kt b/src/jvmMain/kotlin/com/dropbear/MeshRenderer.jvm.kt
new file mode 100644
index 0000000..b41d5dc
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/MeshRenderer.jvm.kt
@@ -0,0 +1,37 @@
+package com.dropbear
+
+import com.dropbear.asset.ModelHandle
+import com.dropbear.asset.TextureHandle
+
+actual fun MeshRenderer.getModel(id: EntityId): ModelHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setModel(id: EntityId, model: ModelHandle?) {
+}
+
+actual fun MeshRenderer.getAllTextureIds(id: EntityId): List<TextureHandle>? {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.getMaterialNames(id: EntityId): List<String> {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setMaterialNames(id: EntityId, names: Array<String>) {
+}
+
+actual fun MeshRenderer.getTexture(id: EntityId, materialName: String): Long {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setTextureOverride(
+    id: EntityId,
+    materialName: String,
+    textureHandle: Long
+) {
+}
+
+actual fun meshRendererExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/asset/AssetHandle.jvm.kt b/src/jvmMain/kotlin/com/dropbear/asset/AssetHandle.jvm.kt
new file mode 100644
index 0000000..983549e
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/asset/AssetHandle.jvm.kt
@@ -0,0 +1,9 @@
+package com.dropbear.asset
+
+actual fun AssetHandle.asTextureHandle(): TextureHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun isModelHandle(id: Long): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/asset/TextureHandle.jvm.kt b/src/jvmMain/kotlin/com/dropbear/asset/TextureHandle.jvm.kt
new file mode 100644
index 0000000..9c5832c
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/asset/TextureHandle.jvm.kt
@@ -0,0 +1,5 @@
+package com.dropbear.asset
+
+actual fun TextureHandle.getTextureName(id: Long): String? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/ffi/DropbearEngine.kt b/src/jvmMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
deleted file mode 100644
index 07453b1..0000000
--- a/src/jvmMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.dropbear.ffi
-
-import com.dropbear.DropbearEngine
-
-actual fun getEntity(label: String): Long? {
-    TODO("Not yet implemented")
-}
-actual fun getAsset(eucaURI: String): Long? {
-    DropbearEngine.native.assetHandle
-    TODO("Not yet implemented")
-}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/ffi/NativeEngine.jvm.kt b/src/jvmMain/kotlin/com/dropbear/ffi/NativeEngine.jvm.kt
index b903a66..9bcb833 100644
--- a/src/jvmMain/kotlin/com/dropbear/ffi/NativeEngine.jvm.kt
+++ b/src/jvmMain/kotlin/com/dropbear/ffi/NativeEngine.jvm.kt
@@ -1,37 +1,6 @@
 package com.dropbear.ffi
 
-import com.dropbear.Camera
-import com.dropbear.EntityId
-import com.dropbear.EntityRef
-import com.dropbear.EntityTransform
-import com.dropbear.asset.TextureHandle
-import com.dropbear.exception.DropbearNativeException
-import com.dropbear.exceptionOnError
-import com.dropbear.ffi.JNINative.*
-import com.dropbear.ffi.InputStateNative.*
-import com.dropbear.ffi.DropbearEngineNative.*
-import com.dropbear.ffi.components.HierarchyNative.*
-import com.dropbear.ffi.components.CameraNative.*
-import com.dropbear.ffi.components.ColliderNative
-import com.dropbear.ffi.components.LabelNative.*
-import com.dropbear.ffi.components.MeshRendererNative.*
-import com.dropbear.ffi.components.EntityTransformNative.*
-import com.dropbear.ffi.components.CustomPropertiesNative.*
-import com.dropbear.ffi.components.RigidBodyNative
-import com.dropbear.input.Gamepad
-import com.dropbear.input.GamepadButton
-import com.dropbear.input.KeyCode
-import com.dropbear.input.MouseButton
-import com.dropbear.input.MouseButtonCodes
 import com.dropbear.logging.Logger
-import com.dropbear.math.Transform
-import com.dropbear.math.Vector2D
-import com.dropbear.physics.Collider
-import com.dropbear.physics.Index
-import com.dropbear.physics.RigidBody
-import com.dropbear.scene.SceneLoadHandle
-import com.dropbear.scene.SceneLoadStatus
-import com.dropbear.utils.Progress
 
 actual class NativeEngine {
     internal var worldHandle: Long = 0L
@@ -75,409 +44,4 @@ actual class NativeEngine {
             return
         }
     }
-
-    actual fun getEntityLabel(entityHandle: Long) : String? {
-        val result = getEntityLabel(worldHandle, entityHandle) ?: if (exceptionOnError) {
-            throw DropbearNativeException("Unable to get entity label for entity $entityHandle")
-        } else {
-            return null
-        }
-        return result
-    }
-
-    actual fun getEntity(label: String): Long? {
-        val result = getEntity(worldHandle, label)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get entity: returned -1")
-            } else {
-                null
-            }
-        } else if (result == 0L) {
-            null
-        } else {
-            result
-        }
-    }
-
-
-    actual fun getTransform(entityId: EntityId): EntityTransform? {
-        return getTransform(worldHandle, entityId.id)
-    }
-
-    actual fun propagateTransform(entityId: EntityId): Transform? {
-        return propagateTransform(worldHandle, entityId.id)
-    }
-
-    actual fun setTransform(entityId: EntityId, transform: EntityTransform) {
-        return setTransform(worldHandle, entityId.id, transform)
-    }
-
-    actual fun printInputState() {
-        return printInputState(inputHandle)
-    }
-
-    actual fun isKeyPressed(key: KeyCode): Boolean {
-        return isKeyPressed(inputHandle, key.ordinal)
-    }
-
-    actual fun getMousePosition(): Vector2D? {
-        val result = getMousePosition(inputHandle);
-        return Vector2D(result[0].toDouble(), result[1].toDouble())
-    }
-
-    actual fun isMouseButtonPressed(button: MouseButton): Boolean {
-        val buttonCode: Int = when (button) {
-            MouseButton.Left -> MouseButtonCodes.LEFT
-            MouseButton.Right -> MouseButtonCodes.RIGHT
-            MouseButton.Middle -> MouseButtonCodes.MIDDLE
-            MouseButton.Back -> MouseButtonCodes.BACK
-            MouseButton.Forward -> MouseButtonCodes.FORWARD
-            is MouseButton.Other -> button.value
-        }
-
-        return isMouseButtonPressed(inputHandle, buttonCode)
-    }
-
-    actual fun getConnectedGamepads(): List<Gamepad> {
-        val result = getConnectedGamepads(inputHandle)
-        return result.toList()
-    }
-
-    actual fun isGamepadButtonPressed(id: Long, button: GamepadButton): Boolean {
-        return isGamepadButtonPressed(inputHandle, id, button.ordinal)
-    }
-
-    actual fun getMouseDelta(): Vector2D? {
-        val result = getMouseDelta(inputHandle);
-        return Vector2D(result[0].toDouble(), result[1].toDouble())
-    }
-
-    actual fun isCursorLocked(): Boolean {
-        return isCursorLocked(inputHandle)
-    }
-
-    actual fun setCursorLocked(locked: Boolean) {
-        setCursorLocked(inputHandle, commandBufferHandle, locked)
-    }
-
-    actual fun getLastMousePos(): Vector2D? {
-        val result = getLastMousePos(inputHandle);
-        return Vector2D(result[0].toDouble(), result[1].toDouble())
-    }
-
-    actual fun getStringProperty(entityHandle: Long, label: String): String? {
-        return getStringProperty(worldHandle, entityHandle, label)
-    }
-
-    actual fun getIntProperty(entityHandle: Long, label: String): Int? {
-        val result = getIntProperty(worldHandle, entityHandle, label)
-        return if (result == 650911) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get integer property for entity $label")
-            } else {
-                null
-            }
-        } else {
-            result
-        }
-    }
-
-    actual fun getLongProperty(entityHandle: Long, label: String): Long? {
-        val result = getLongProperty(worldHandle, entityHandle, label)
-        return if (result == 6509112938) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get long property for entity $label")
-            } else {
-                null
-            }
-        } else {
-            result
-        }
-    }
-
-    actual fun getFloatProperty(entityHandle: Long, label: String): Float? {
-        val result = getFloatProperty(worldHandle, entityHandle, label)
-        return if (result.isNaN()) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get float property for entity $label")
-            } else {
-                null
-            }
-        } else {
-            result.toFloat()
-        }
-    }
-
-    actual fun getDoubleProperty(entityHandle: Long, label: String): Double? {
-        val result = getFloatProperty(worldHandle, entityHandle, label)
-        return if (result.isNaN()) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get double (float) property")
-            } else {
-                null
-            }
-        } else {
-            result
-        }
-    }
-
-    actual fun getBoolProperty(entityHandle: Long, label: String): Boolean? {
-        return getBoolProperty(worldHandle, entityHandle, label)
-    }
-
-    actual fun getVec3Property(entityHandle: Long, label: String): FloatArray? {
-        return getVec3Property(worldHandle, entityHandle, label)
-    }
-
-    actual fun setStringProperty(entityHandle: Long, label: String, value: String) {
-        setStringProperty(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun setIntProperty(entityHandle: Long, label: String, value: Int) {
-        setIntProperty(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun setLongProperty(entityHandle: Long, label: String, value: Long) {
-        setLongProperty(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun setFloatProperty(entityHandle: Long, label: String, value: Double) {
-        setFloatProperty(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun setBoolProperty(entityHandle: Long, label: String, value: Boolean) {
-        setBoolProperty(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun setVec3Property(entityHandle: Long, label: String, value: FloatArray) {
-        setVec3Property(worldHandle, entityHandle, label, value)
-    }
-
-    actual fun getCamera(label: String): Camera? {
-        return getCamera(worldHandle, label)
-    }
-
-    actual fun getAttachedCamera(entityId: EntityId): Camera? {
-        return getAttachedCamera(worldHandle, entityId.id)
-    }
-
-    actual fun setCamera(camera: Camera) {
-        setCamera(worldHandle, camera)
-    }
-
-    actual fun isCursorHidden(): Boolean {
-        return isCursorHidden(inputHandle)
-    }
-
-    actual fun setCursorHidden(hidden: Boolean) {
-        setCursorHidden(inputHandle, commandBufferHandle, hidden)
-    }
-
-    actual fun getModel(entityHandle: Long): Long? {
-        val result = getModel(worldHandle, entityHandle)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get model for entity $entityHandle")
-            } else {
-                null
-            }
-        } else if (result == 0L) {
-            null
-        } else {
-            result
-        }
-    }
-
-    actual fun setModel(entityHandle: Long, modelHandle: Long) {
-        setModel(worldHandle, assetHandle, entityHandle, modelHandle)
-    }
-
-    actual fun getTexture(entityHandle: Long, name: String): Long? {
-        val result = getTexture(worldHandle, assetHandle, entityHandle, name)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get texture for entity $entityHandle")
-            } else {
-                null
-            }
-        } else if (result == 0L) {
-            null
-        } else {
-            result
-        }
-    }
-
-    actual fun setTextureOverride(entityHandle: Long, oldMaterialName: String, newTextureHandle: TextureHandle) {
-        return setTexture(
-            worldHandle,
-            assetHandle,
-            entityHandle,
-            oldMaterialName,
-            newTextureHandle.raw()
-        )
-    }
-
-    actual fun getTextureName(textureHandle: Long): String? {
-        return getTextureName(assetHandle, textureHandle)
-    }
-
-    actual fun isUsingModel(entityHandle: Long, modelHandle: Long): Boolean {
-        return isUsingModel(worldHandle, entityHandle, modelHandle)
-    }
-
-    actual fun isUsingTexture(entityHandle: Long, textureHandle: Long): Boolean {
-        return isUsingTexture(worldHandle, entityHandle, textureHandle)
-    }
-
-    actual fun getAsset(eucaURI: String): Long? {
-        val result = getAsset(assetHandle, eucaURI)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get asset for URI $eucaURI")
-            } else {
-                null
-            }
-        } else if (result == 0L) {
-            // no asset found
-            null
-        } else {
-            result
-        }
-    }
-
-    actual fun isModelHandle(id: Long): Boolean {
-        return isModelHandle(assetHandle, id)
-    }
-
-    actual fun isTextureHandle(id: Long): Boolean {
-        return isTextureHandle(assetHandle, id)
-    }
-
-    actual fun getAllTextures(entityHandle: Long): Array<String> {
-        return getAllTextures(worldHandle, entityHandle) ?: emptyArray()
-    }
-
-    actual fun getChildren(entityId: EntityId): Array<EntityRef>? {
-        val result = getChildren(worldHandle, entityId.id)
-        // i shouldn't expect it to return null unless an error, otherwise it must
-        // return an empty array
-        if (result == null) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to query for all children for entity ${entityId.id}")
-            } else {
-                return null
-            }
-        } else {
-            val entityRefs = mutableListOf<EntityRef>()
-            result.forEach { e ->
-                entityRefs.add(EntityRef(EntityId(e)))
-            }
-            return entityRefs.toTypedArray() // must be an array so it cannot be mutated
-        }
-    }
-
-    actual fun getChildByLabel(entityId: EntityId, label: String): EntityRef? {
-        val result = getChildByLabel(worldHandle, entityId.id, label)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get child by label $entityId $label")
-            } else {
-                null
-            }
-        } else if (result == -2L) {
-            null
-        } else {
-            EntityRef(EntityId(result))
-        }
-    }
-
-    actual fun getParent(entityId: EntityId): EntityRef? {
-        val result = getParent(worldHandle, entityId.id)
-        return if (result == -1L) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("Unable to get parent of entity $entityId")
-            } else {
-                null
-            }
-        } else if (result == -2L) {
-            null
-        } else {
-            EntityRef(EntityId(result))
-        }
-    }
-
-    actual fun quit() {
-        quit(commandBufferHandle)
-    }
-
-    actual fun switchToSceneImmediate(sceneName: String) {
-        SceneNative.switchToSceneImmediate(commandBufferHandle, sceneName)
-    }
-
-    actual fun loadSceneAsync(sceneName: String): SceneLoadHandle? {
-        return SceneNative.loadSceneAsync(commandBufferHandle, sceneLoaderHandle, sceneName, this)
-    }
-
-    actual fun loadSceneAsync(sceneName: String, loadingScene: String): SceneLoadHandle? {
-        return SceneNative.loadSceneAsync(commandBufferHandle, sceneLoaderHandle, sceneName, loadingScene, this)
-    }
-
-    actual fun switchToSceneAsync(sceneLoadHandle: SceneLoadHandle) {
-        SceneNative.switchToSceneAsync(commandBufferHandle, sceneLoadHandle) // will throw exception from JNI interface
-    }
-
-    actual fun getSceneLoadProgress(sceneLoadHandle: SceneLoadHandle): Progress {
-        return SceneNative.getSceneLoadProgress(sceneLoaderHandle, sceneLoadHandle)
-    }
-
-    actual fun getSceneLoadStatus(sceneLoadHandle: SceneLoadHandle): SceneLoadStatus {
-        return SceneNative.getSceneLoadStatus(sceneLoaderHandle, sceneLoadHandle)
-    }
-
-    actual fun setPhysicsEnabled(entityId: Long, enabled: Boolean) {
-        return PhysicsNative.setPhysicsEnabled(worldHandle, physicsEngineHandle, entityId, enabled)
-    }
-
-    actual fun isPhysicsEnabled(entityId: Long): Boolean {
-        return PhysicsNative.isPhysicsEnabled(worldHandle, physicsEngineHandle, entityId)
-    }
-
-    actual fun getRigidBody(entityId: Long): RigidBody? {
-        val result = PhysicsNative.getRigidBody(worldHandle, physicsEngineHandle, entityId)
-        result.native = this@NativeEngine
-        return result
-    }
-
-    actual fun getAllColliders(entityId: Long): List<Collider> {
-        val result = PhysicsNative.getAllColliders(worldHandle, physicsEngineHandle, entityId)
-        result.forEach {
-            it.native = this@NativeEngine
-        }
-        return result.toList()
-    }
-
-    actual fun applyImpulse(index: Index, x: Double, y: Double, z: Double) {
-        return RigidBodyNative.applyImpulse(physicsEngineHandle, index, x, y, z)
-    }
-
-    actual fun applyTorqueImpulse(index: Index, x: Double, y: Double, z: Double) {
-        return RigidBodyNative.applyTorqueImpulse(physicsEngineHandle, index, x, y, z)
-    }
-
-    actual fun setRigidbody(rigidBody: RigidBody) {
-        return RigidBodyNative.setRigidBody(worldHandle, physicsEngineHandle, rigidBody)
-    }
-
-    actual fun getChildColliders(index: Index): List<Collider> {
-        val result = RigidBodyNative.getChildColliders(worldHandle, physicsEngineHandle, index)
-        result.forEach {
-            it.native = this@NativeEngine
-        }
-        return result.toList()
-    }
-
-    actual fun setCollider(collider: Collider) {
-        return ColliderNative.setCollider(worldHandle, physicsEngineHandle, collider)
-    }
-}
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/host/SystemManager.kt b/src/jvmMain/kotlin/com/dropbear/host/SystemManager.kt
index 70abe46..670429c 100644
--- a/src/jvmMain/kotlin/com/dropbear/host/SystemManager.kt
+++ b/src/jvmMain/kotlin/com/dropbear/host/SystemManager.kt
@@ -1,7 +1,7 @@
 package com.dropbear.host
 
 import com.dropbear.DropbearEngine
-import com.dropbear.System
+import com.dropbear.ecs.System
 import com.dropbear.logging.LogLevel
 import com.dropbear.logging.LogWriter
 import com.dropbear.logging.Logger
diff --git a/src/jvmMain/kotlin/com/dropbear/input/Gamepad.jvm.kt b/src/jvmMain/kotlin/com/dropbear/input/Gamepad.jvm.kt
new file mode 100644
index 0000000..ea1c67c
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/input/Gamepad.jvm.kt
@@ -0,0 +1,8 @@
+package com.dropbear.input
+
+actual fun Gamepad.isGamepadButtonPressed(
+    id: Long,
+    button: GamepadButton
+): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/input/InputState.jvm.kt b/src/jvmMain/kotlin/com/dropbear/input/InputState.jvm.kt
new file mode 100644
index 0000000..d41379b
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/input/InputState.jvm.kt
@@ -0,0 +1,46 @@
+package com.dropbear.input
+
+import com.dropbear.math.Vector2D
+
+actual class InputState actual constructor() {
+    actual fun printInputState() {
+    }
+
+    actual fun isKeyPressed(key: KeyCode): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun getMousePosition(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isMouseButtonPressed(button: MouseButton): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun getMouseDelta(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isCursorLocked(): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun setCursorLocked(locked: Boolean) {
+    }
+
+    actual fun getLastMousePos(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isCursorHidden(): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun setCursorHidden(hidden: Boolean) {
+    }
+
+    actual fun getConnectedGamepads(): List<Gamepad> {
+        TODO("Not yet implemented")
+    }
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/physics/Collider.jvm.kt b/src/jvmMain/kotlin/com/dropbear/physics/Collider.jvm.kt
new file mode 100644
index 0000000..f711398
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/physics/Collider.jvm.kt
@@ -0,0 +1,80 @@
+package com.dropbear.physics
+
+import com.dropbear.math.Vector3D
+
+actual fun Collider.getColliderShape(collider: Collider): ColliderShape {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderShape(
+    collider: Collider,
+    shape: ColliderShape
+) {
+}
+
+actual fun Collider.setColliderDensity(
+    collider: Collider,
+    density: Double
+) {
+}
+
+actual fun Collider.getColliderFriction(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderFriction(
+    collider: Collider,
+    friction: Double
+) {
+}
+
+actual fun Collider.getColliderRestitution(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderRestitution(
+    collider: Collider,
+    restitution: Double
+) {
+}
+
+actual fun Collider.getColliderIsSensor(collider: Collider): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderIsSensor(
+    collider: Collider,
+    isSensor: Boolean
+) {
+}
+
+actual fun Collider.getColliderTranslation(collider: Collider): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderTranslation(
+    collider: Collider,
+    translation: Vector3D
+) {
+}
+
+actual fun Collider.setColliderRotation(
+    collider: Collider,
+    rotation: Vector3D
+) {
+}
+
+actual fun Collider.getColliderRotation(collider: Collider): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.getColliderMass(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderMass(collider: Collider, mass: Double) {
+}
+
+actual fun Collider.getColliderDensity(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/physics/ColliderGroup.jvm.kt b/src/jvmMain/kotlin/com/dropbear/physics/ColliderGroup.jvm.kt
new file mode 100644
index 0000000..24537dc
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/physics/ColliderGroup.jvm.kt
@@ -0,0 +1,11 @@
+package com.dropbear.physics
+
+import com.dropbear.EntityId
+
+actual fun ColliderGroup.getColliderGroupColliders(colliderGroup: ColliderGroup): List<Collider> {
+    TODO("Not yet implemented")
+}
+
+actual fun colliderGroupExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/physics/RigidBody.jvm.kt b/src/jvmMain/kotlin/com/dropbear/physics/RigidBody.jvm.kt
new file mode 100644
index 0000000..c37176a
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/physics/RigidBody.jvm.kt
@@ -0,0 +1,135 @@
+package com.dropbear.physics
+
+import com.dropbear.EntityId
+import com.dropbear.math.Vector3D
+
+actual fun RigidBody.getRigidbodyMode(rigidBody: RigidBody): RigidBodyMode {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyMode(
+    rigidBody: RigidBody,
+    mode: RigidBodyMode
+) {
+}
+
+actual fun RigidBody.getRigidbodyGravityScale(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyGravityScale(
+    rigidBody: RigidBody,
+    gravityScale: Double
+) {
+}
+
+actual fun RigidBody.getRigidbodyCanSleep(rigidBody: RigidBody): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyCanSleep(
+    rigidBody: RigidBody,
+    canSleep: Boolean
+) {
+}
+
+actual fun RigidBody.getRigidbodyCcdEnabled(rigidBody: RigidBody): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyCcdEnabled(
+    rigidBody: RigidBody,
+    ccdEnabled: Boolean
+) {
+}
+
+actual fun RigidBody.getRigidbodyLinearVelocity(rigidBody: RigidBody): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLinearVelocity(
+    rigidBody: RigidBody,
+    linearVelocity: Vector3D
+) {
+}
+
+actual fun RigidBody.getRigidbodyAngularVelocity(rigidBody: RigidBody): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyAngularVelocity(
+    rigidBody: RigidBody,
+    angularVelocity: Vector3D
+) {
+}
+
+actual fun RigidBody.getRigidbodyLinearDamping(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.getRigidbodyAngularDamping(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyAngularDamping(
+    rigidBody: RigidBody,
+    angularDamping: Double
+) {
+}
+
+actual fun RigidBody.getRigidbodyLockTranslation(rigidBody: RigidBody): AxisLock {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLockTranslation(
+    rigidBody: RigidBody,
+    lockTranslation: AxisLock
+) {
+}
+
+actual fun RigidBody.getRigidbodyLockRotation(rigidBody: RigidBody): AxisLock {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLockRotation(
+    rigidBody: RigidBody,
+    lockRotation: AxisLock
+) {
+}
+
+actual fun RigidBody.getRigidbodyChildren(rigidBody: RigidBody): List<EntityId> {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyChildren(
+    rigidBody: RigidBody,
+    children: List<EntityId>
+) {
+}
+
+actual fun RigidBody.applyImpulse(
+    index: Index,
+    x: Double,
+    y: Double,
+    z: Double
+) {
+}
+
+actual fun RigidBody.applyTorqueImpulse(
+    index: Index,
+    x: Double,
+    y: Double,
+    z: Double
+) {
+}
+
+actual fun RigidBody.
+        setRigidbodyLinearDamping(
+    rigidBody: RigidBody,
+    linearDamping: Double
+) {
+}
+
+actual fun rigidBodyExistsForEntity(entityId: EntityId): Index? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/scene/SceneLoadHandle.jvm.kt b/src/jvmMain/kotlin/com/dropbear/scene/SceneLoadHandle.jvm.kt
new file mode 100644
index 0000000..56bbcfc
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/scene/SceneLoadHandle.jvm.kt
@@ -0,0 +1,15 @@
+package com.dropbear.scene
+
+import com.dropbear.utils.Progress
+
+actual fun SceneLoadHandle.switchToSceneAsync(): SceneLoadHandle {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneLoadHandle.getSceneLoadProgress(): Progress {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneLoadHandle.getSceneLoadStatus(): SceneLoadStatus {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/com/dropbear/scene/SceneManager.jvm.kt b/src/jvmMain/kotlin/com/dropbear/scene/SceneManager.jvm.kt
new file mode 100644
index 0000000..7524afa
--- /dev/null
+++ b/src/jvmMain/kotlin/com/dropbear/scene/SceneManager.jvm.kt
@@ -0,0 +1,15 @@
+package com.dropbear.scene
+
+actual fun SceneManager.loadSceneAsyncNative(sceneName: String): SceneLoadHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneManager.loadSceneAsyncNative(
+    sceneName: String,
+    loading_scene: String
+): SceneLoadHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneManager.switchToSceneImmediateNative(sceneName: String) {
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/Camera.native.kt b/src/nativeMain/kotlin/com/dropbear/Camera.native.kt
new file mode 100644
index 0000000..3a451f1
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/Camera.native.kt
@@ -0,0 +1,81 @@
+package com.dropbear
+
+import com.dropbear.math.Vector3D
+
+actual fun Camera.getCameraEye(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraEye(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraTarget(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraTarget(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraUp(entity: EntityId): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraUp(entity: EntityId, value: Vector3D) {
+}
+
+actual fun Camera.getCameraAspect(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.getCameraFovY(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraFovY(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraZNear(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraZNear(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraZFar(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraZFar(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraYaw(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.getCameraPitch(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraYaw(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.setCameraPitch(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraSpeed(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraSpeed(entity: EntityId, value: Double) {
+}
+
+actual fun Camera.getCameraSensitivity(entity: EntityId): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Camera.setCameraSensitivity(entity: EntityId, value: Double) {
+}
+
+actual fun cameraExistsForEntity(entity: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/CustomProperties.native.kt b/src/nativeMain/kotlin/com/dropbear/CustomProperties.native.kt
new file mode 100644
index 0000000..8923627
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/CustomProperties.native.kt
@@ -0,0 +1,93 @@
+package com.dropbear
+
+actual fun CustomProperties.getStringProperty(
+    entityHandle: Long,
+    label: String
+): String? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getIntProperty(entityHandle: Long, label: String): Int? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getLongProperty(
+    entityHandle: Long,
+    label: String
+): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getDoubleProperty(
+    entityHandle: Long,
+    label: String
+): Double? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getFloatProperty(
+    entityHandle: Long,
+    label: String
+): Float? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getBoolProperty(
+    entityHandle: Long,
+    label: String
+): Boolean? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.getVec3Property(
+    entityHandle: Long,
+    label: String
+): FloatArray? {
+    TODO("Not yet implemented")
+}
+
+actual fun CustomProperties.setStringProperty(
+    entityHandle: Long,
+    label: String,
+    value: String
+) {
+}
+
+actual fun CustomProperties.setIntProperty(
+    entityHandle: Long,
+    label: String,
+    value: Int
+) {
+}
+
+actual fun CustomProperties.setLongProperty(
+    entityHandle: Long,
+    label: String,
+    value: Long
+) {
+}
+
+actual fun CustomProperties.setFloatProperty(
+    entityHandle: Long,
+    label: String,
+    value: Double
+) {
+}
+
+actual fun CustomProperties.setBoolProperty(
+    entityHandle: Long,
+    label: String,
+    value: Boolean
+) {
+}
+
+actual fun CustomProperties.setVec3Property(
+    entityHandle: Long,
+    label: String,
+    value: FloatArray
+) {
+}
+
+actual fun customPropertiesExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt b/src/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt
new file mode 100644
index 0000000..ed78c58
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt
@@ -0,0 +1,16 @@
+package com.dropbear
+
+actual fun getEntity(label: String): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun getCamera(label: String): Camera? {
+    TODO("Not yet implemented")
+}
+
+actual fun getAsset(eucaURI: String): Long? {
+    TODO("Not yet implemented")
+}
+
+actual fun quit() {
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/EntityRef.native.kt b/src/nativeMain/kotlin/com/dropbear/EntityRef.native.kt
new file mode 100644
index 0000000..a607a2c
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/EntityRef.native.kt
@@ -0,0 +1,20 @@
+package com.dropbear
+
+actual fun EntityRef.getEntityLabel(entity: EntityId): String? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getChildren(entityId: EntityId): Array<EntityRef>? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getChildByLabel(
+    entityId: EntityId,
+    label: String
+): EntityRef? {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityRef.getParent(entityId: EntityId): EntityRef? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/EntityTransform.native.kt b/src/nativeMain/kotlin/com/dropbear/EntityTransform.native.kt
new file mode 100644
index 0000000..4291a56
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/EntityTransform.native.kt
@@ -0,0 +1,31 @@
+package com.dropbear
+
+import com.dropbear.math.Transform
+
+actual fun EntityTransform.getLocalTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityTransform.setLocalTransform(
+    entityId: EntityId,
+    transform: Transform
+) {
+}
+
+actual fun EntityTransform.getWorldTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun EntityTransform.setWorldTransform(
+    entityId: EntityId,
+    transform: Transform
+) {
+}
+
+actual fun EntityTransform.propagateTransform(entityId: EntityId): Transform {
+    TODO("Not yet implemented")
+}
+
+actual fun entityTransformExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/MeshRenderer.native.kt b/src/nativeMain/kotlin/com/dropbear/MeshRenderer.native.kt
new file mode 100644
index 0000000..b41d5dc
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/MeshRenderer.native.kt
@@ -0,0 +1,37 @@
+package com.dropbear
+
+import com.dropbear.asset.ModelHandle
+import com.dropbear.asset.TextureHandle
+
+actual fun MeshRenderer.getModel(id: EntityId): ModelHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setModel(id: EntityId, model: ModelHandle?) {
+}
+
+actual fun MeshRenderer.getAllTextureIds(id: EntityId): List<TextureHandle>? {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.getMaterialNames(id: EntityId): List<String> {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setMaterialNames(id: EntityId, names: Array<String>) {
+}
+
+actual fun MeshRenderer.getTexture(id: EntityId, materialName: String): Long {
+    TODO("Not yet implemented")
+}
+
+actual fun MeshRenderer.setTextureOverride(
+    id: EntityId,
+    materialName: String,
+    textureHandle: Long
+) {
+}
+
+actual fun meshRendererExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/asset/AssetHandle.native.kt b/src/nativeMain/kotlin/com/dropbear/asset/AssetHandle.native.kt
new file mode 100644
index 0000000..983549e
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/asset/AssetHandle.native.kt
@@ -0,0 +1,9 @@
+package com.dropbear.asset
+
+actual fun AssetHandle.asTextureHandle(): TextureHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun isModelHandle(id: Long): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/asset/TextureHandle.native.kt b/src/nativeMain/kotlin/com/dropbear/asset/TextureHandle.native.kt
new file mode 100644
index 0000000..9c5832c
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/asset/TextureHandle.native.kt
@@ -0,0 +1,5 @@
+package com.dropbear.asset
+
+actual fun TextureHandle.getTextureName(id: Long): String? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/ffi/ConverterUtilities.kt b/src/nativeMain/kotlin/com/dropbear/ffi/ConverterUtilities.kt
deleted file mode 100644
index 2ad7f8d..0000000
--- a/src/nativeMain/kotlin/com/dropbear/ffi/ConverterUtilities.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-@file:OptIn(ExperimentalForeignApi::class, ExperimentalNativeApi::class)
-@file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
-
-package com.dropbear.ffi
-
-import com.dropbear.EntityId
-import com.dropbear.exception.DropbearNativeException
-import com.dropbear.ffi.generated.ColliderShape
-import com.dropbear.ffi.generated.ColliderShape_Box
-import com.dropbear.ffi.generated.ColliderShape_Capsule
-import com.dropbear.ffi.generated.ColliderShape_Cone
-import com.dropbear.ffi.generated.ColliderShape_Cylinder
-import com.dropbear.ffi.generated.ColliderShape_Sphere
-import com.dropbear.ffi.generated.RigidBodyMode
-import com.dropbear.ffi.generated.SceneLoadResult
-import com.dropbear.ffi.generated.Vector3D
-import com.dropbear.physics.AxisLock
-import com.dropbear.physics.Collider
-import com.dropbear.physics.Index
-import com.dropbear.physics.RigidBody
-import com.dropbear.scene.SceneLoadStatus
-import kotlinx.cinterop.ExperimentalForeignApi
-import kotlin.experimental.ExperimentalNativeApi
-
-internal fun SceneLoadResult.fromNative(): SceneLoadStatus {
-    return when (this) {
-        SceneLoadResult.SCENE_LOAD_PENDING -> SceneLoadStatus.PENDING
-        SceneLoadResult.SCENE_LOAD_SUCCESS -> SceneLoadStatus.READY
-        SceneLoadResult.SCENE_LOAD_ERROR -> SceneLoadStatus.FAILED
-    }
-}
-
-internal fun Vector3D.toKotlin(): com.dropbear.math.Vector3D {
-    return com.dropbear.math.Vector3D(this.x, this.y, this.z)
-}
-
-internal fun RigidBodyMode.toKotlin(): com.dropbear.physics.RigidBodyMode {
-    return when (this) {
-        RigidBodyMode.RIGIDBODY_MODE_DYNAMIC -> com.dropbear.physics.RigidBodyMode.Dynamic
-        RigidBodyMode.RIGIDBODY_MODE_FIXED -> com.dropbear.physics.RigidBodyMode.Fixed
-        RigidBodyMode.RIGIDBODY_MODE_KINEMATIC_POSITION -> com.dropbear.physics.RigidBodyMode.KinematicPosition
-        RigidBodyMode.RIGIDBODY_MODE_KINEMATIC_VELOCITY -> com.dropbear.physics.RigidBodyMode.KinematicVelocity
-    }
-}
-
-internal fun com.dropbear.ffi.generated.AxisLock.toKotlin(): AxisLock {
-    return AxisLock(
-        this.x,
-        this.y,
-        this.z,
-    )
-}
-
-internal fun com.dropbear.ffi.generated.RigidBody.toKotlin(nativeEngine: NativeEngine): RigidBody {
-    return RigidBody(
-        index = Index(this.index.index, this.index.generation),
-        entity = EntityId(this.entity),
-        rigidBodyMode = this.mode.toKotlin(),
-        gravityScale = this.gravity_scale,
-        canSleep = this.can_sleep,
-        ccdEnabled = this.ccd_enabled,
-        linearVelocity = this.linear_velocity.toKotlin(),
-        angularVelocity = this.angualar_velocity.toKotlin(),
-        linearDamping = this.linear_damping,
-        angularDamping = this.angular_damping,
-        lockTranslation = this.lock_translation.toKotlin(),
-        lockRotation = this.lock_rotation.toKotlin(),
-        native = nativeEngine
-    )
-}
-
-internal fun RigidBody.populateCStruct(cBody: com.dropbear.ffi.generated.RigidBody) {
-    cBody.index.index = this.index.index
-    cBody.index.generation = this.index.generation
-    cBody.entity = this.entity.id
-    cBody.mode = when (this.rigidBodyMode) {
-        com.dropbear.physics.RigidBodyMode.Dynamic -> RigidBodyMode.RIGIDBODY_MODE_DYNAMIC
-        com.dropbear.physics.RigidBodyMode.Fixed -> RigidBodyMode.RIGIDBODY_MODE_FIXED
-        com.dropbear.physics.RigidBodyMode.KinematicPosition -> RigidBodyMode.RIGIDBODY_MODE_KINEMATIC_POSITION
-        com.dropbear.physics.RigidBodyMode.KinematicVelocity -> RigidBodyMode.RIGIDBODY_MODE_KINEMATIC_VELOCITY
-    }
-    cBody.gravity_scale = this.gravityScale
-    cBody.can_sleep = this.canSleep
-    cBody.ccd_enabled = this.ccdEnabled
-
-    cBody.linear_velocity.x = this.linearVelocity.x
-    cBody.linear_velocity.y = this.linearVelocity.y
-    cBody.linear_velocity.z = this.linearVelocity.z
-
-    cBody.angualar_velocity.x = this.angularVelocity.x
-    cBody.angualar_velocity.y = this.angularVelocity.y
-    cBody.angualar_velocity.z = this.angularVelocity.z
-
-    cBody.linear_damping = this.linearDamping
-    cBody.angular_damping = this.angularDamping
-
-    cBody.lock_translation.x = this.lockTranslation.x
-    cBody.lock_translation.y = this.lockTranslation.y
-    cBody.lock_translation.z = this.lockTranslation.z
-
-    cBody.lock_rotation.x = this.lockRotation.x
-    cBody.lock_rotation.y = this.lockRotation.y
-    cBody.lock_rotation.z = this.lockRotation.z
-}
-
-internal fun ColliderShape.toKotlin(): com.dropbear.physics.ColliderShape {
-    return when (this.tag) {
-        ColliderShape_Box -> {
-            com.dropbear.physics.ColliderShape.Box(
-                halfExtents = com.dropbear.math.Vector3D(
-                    this.data.box.half_extents.x,
-                    this.data.box.half_extents.y,
-                    this.data.box.half_extents.z
-                )
-            )
-        }
-        ColliderShape_Sphere -> {
-            com.dropbear.physics.ColliderShape.Sphere(this.data.sphere.radius)
-        }
-        ColliderShape_Capsule -> {
-            com.dropbear.physics.ColliderShape.Capsule(this.data.capsule.half_height, this.data.capsule.radius)
-        }
-        ColliderShape_Cylinder -> {
-            com.dropbear.physics.ColliderShape.Cylinder(this.data.cylinder.half_height, this.data.cylinder.radius)
-        }
-        ColliderShape_Cone -> {
-            com.dropbear.physics.ColliderShape.Cone(this.data.cone.half_height, this.data.cone.radius)
-        }
-        else -> throw DropbearNativeException("Unknown collider tag: ${this.tag}")
-    }
-}
-
-internal fun com.dropbear.ffi.generated.Collider.toKotlin(nativeEngine: NativeEngine): Collider {
-    return Collider(
-        index = Index(this.index.index, this.index.generation),
-        entity = EntityId(this.entity),
-        colliderShape = this.collider_shape.toKotlin(),
-        density = this.density,
-        friction = this.friction,
-        restitution = this.restitution,
-        isSensor = this.is_sensor,
-        translation = this.translation.toKotlin(),
-        rotation = this.rotation.toKotlin(),
-        native = nativeEngine,
-        id = this.id,
-    )
-}
-
-internal fun Collider.populateCStruct(struct: com.dropbear.ffi.generated.Collider) {
-    struct.index.index = this.index.index
-    struct.index.generation = this.index.generation
-    struct.entity = this.entity.id
-    struct.density = this.density
-    struct.friction = this.friction
-    struct.restitution = this.restitution
-    struct.is_sensor = this.isSensor
-
-    struct.translation.x = this.translation.x
-    struct.translation.y = this.translation.y
-    struct.translation.z = this.translation.z
-
-    struct.rotation.x = this.rotation.x
-    struct.rotation.y = this.rotation.y
-    struct.rotation.z = this.rotation.z
-
-    this.colliderShape.populateCStruct(struct.collider_shape)
-}
-
-internal fun com.dropbear.physics.ColliderShape.populateCStruct(struct: ColliderShape) {
-    when (this) {
-        is com.dropbear.physics.ColliderShape.Box -> {
-            struct.tag = ColliderShape_Box
-            struct.data.box.half_extents.x = this.halfExtents.x
-            struct.data.box.half_extents.y = this.halfExtents.y
-            struct.data.box.half_extents.z = this.halfExtents.z
-        }
-        is com.dropbear.physics.ColliderShape.Sphere -> {
-            struct.tag = ColliderShape_Sphere
-            struct.data.sphere.radius = this.radius
-        }
-        is com.dropbear.physics.ColliderShape.Capsule -> {
-            struct.tag = ColliderShape_Capsule
-            struct.data.capsule.half_height = this.halfHeight
-            struct.data.capsule.radius = this.radius
-        }
-        is com.dropbear.physics.ColliderShape.Cylinder -> {
-            struct.tag = ColliderShape_Cylinder
-            struct.data.cylinder.half_height = this.halfHeight
-            struct.data.cylinder.radius = this.radius
-        }
-        is com.dropbear.physics.ColliderShape.Cone -> {
-            struct.tag = ColliderShape_Cone
-            struct.data.cone.half_height = this.halfHeight
-            struct.data.cone.radius = this.radius
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/ffi/DropbearEngine.kt b/src/nativeMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
deleted file mode 100644
index d7097b3..0000000
--- a/src/nativeMain/kotlin/com/dropbear/ffi/DropbearEngine.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.dropbear.ffi
-
-import com.dropbear.DropbearEngine
-
-actual fun getEntity(label: String): Long? {
-    TODO("Not yet implemented")
-}
-actual fun getAsset(eucaURI: String): Long? {
-    DropbearEngine.native
-    TODO("Not yet implemented")
-}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt b/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
index 69b1200..61d52e1 100644
--- a/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
+++ b/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
@@ -1,36 +1,15 @@
 @file:OptIn(ExperimentalForeignApi::class, ExperimentalNativeApi::class)
 @file:Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
 
-/// guys how do i remove the reinterpret error its genuinely pmo and intellij keeps
-/// on catching it.
-
 package com.dropbear.ffi
 
-import com.dropbear.Camera
-import com.dropbear.EntityId
-import com.dropbear.EntityRef
-import com.dropbear.EntityTransform
-import com.dropbear.asset.TextureHandle
 import com.dropbear.exception.DropbearNativeException
-import com.dropbear.exception.PrematureSceneSwitchException
 import com.dropbear.exceptionOnError
-import com.dropbear.ffi.generated.*
-import com.dropbear.input.Gamepad
-import com.dropbear.input.GamepadButton
-import com.dropbear.input.KeyCode
-import com.dropbear.input.MouseButton
-import com.dropbear.input.MouseButtonCodes
+import com.dropbear.ffi.generated.DropbearContext
 import com.dropbear.logging.Logger
-import com.dropbear.math.Transform
-import com.dropbear.math.Vector2D
-import com.dropbear.physics.AxisLock
-import com.dropbear.physics.Collider
-import com.dropbear.physics.Index
-import com.dropbear.physics.RigidBody
-import com.dropbear.scene.SceneLoadHandle
-import com.dropbear.scene.SceneLoadStatus
-import com.dropbear.utils.Progress
-import kotlinx.cinterop.*
+import kotlinx.cinterop.COpaquePointer
+import kotlinx.cinterop.ExperimentalForeignApi
+import kotlinx.cinterop.interpretCPointer
 import kotlin.experimental.ExperimentalNativeApi
 
 actual class NativeEngine {
@@ -88,1563 +67,4 @@ actual class NativeEngine {
             }
         }
     }
-
-    actual fun getEntity(label: String): Long? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outEntity = alloc<LongVar>()
-            val result = dropbear_get_entity(
-                label = label,
-                world_ptr = world.reinterpret(),
-                out_entity = outEntity.ptr
-            )
-            return if (result == 0) outEntity.value else if (exceptionOnError) {
-                throw DropbearNativeException("getEntity failed with code: $result")
-            } else {
-                println("getEntity failed with code: $result")
-                null
-            }
-        }
-    }
-
-    actual fun getEntityLabel(entityHandle: Long): String? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val bufferSize = 256
-            val outLabel = allocArray<ByteVar>(bufferSize)
-
-            val result = dropbear_get_entity_name(
-                world_ptr = world.reinterpret(),
-                entity_id = entityHandle,
-                out_name = outLabel,
-                max_len = bufferSize.toULong()
-            )
-
-            if (result == 0) {
-                return outLabel.toKString()
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getEntityLabel failed with code for entity '$entityHandle': $result")
-                } else {
-                    println("getEntityLabel failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getTransform(entityId: EntityId): EntityTransform? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outTransform = alloc<NativeEntityTransform>()
-            val result = dropbear_get_transform(
-                world_ptr = world.reinterpret(),
-                entity_handle = entityId.id,
-                out_transform = outTransform.ptr
-            )
-            if (result == 0) {
-                return EntityTransform(
-                    local = Transform(
-                        position = com.dropbear.math.Vector3D(
-                            outTransform.local.position_x,
-                            outTransform.local.position_y,
-                            outTransform.local.position_z
-                        ),
-                        rotation = com.dropbear.math.QuaternionD(
-                            outTransform.local.rotation_x,
-                            outTransform.local.rotation_y,
-                            outTransform.local.rotation_z,
-                            outTransform.local.rotation_w
-                        ),
-                        scale = com.dropbear.math.Vector3D(
-                            outTransform.local.scale_x, outTransform.local.scale_y,
-                            outTransform.local.scale_z
-                        )
-                    ),
-                    world = Transform(
-                        position = com.dropbear.math.Vector3D(
-                            outTransform.world.position_x,
-                            outTransform.world.position_y,
-                            outTransform.world.position_z
-                        ),
-                        rotation = com.dropbear.math.QuaternionD(
-                            outTransform.world.rotation_x,
-                            outTransform.world.rotation_y,
-                            outTransform.world.rotation_z,
-                            outTransform.world.rotation_w
-                        ),
-                        scale = com.dropbear.math.Vector3D(
-                            outTransform.world.scale_x,
-                            outTransform.world.scale_y,
-                            outTransform.world.scale_z
-                        )
-                    )
-                )
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getTransform failed with code: $result")
-                } else {
-                    println("getTransform failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun propagateTransform(entityId: EntityId): Transform? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outTransform = alloc<NativeTransform>()
-            val result = dropbear_propagate_transform(
-                world_ptr = world.reinterpret(),
-                entity_id = entityId.id,
-                out_transform = outTransform.ptr
-            )
-            if (result == 0) {
-                return Transform(
-                    position = com.dropbear.math.Vector3D(
-                        outTransform.position_x,
-                        outTransform.position_y,
-                        outTransform.position_z
-                    ),
-                    rotation = com.dropbear.math.QuaternionD(
-                        outTransform.rotation_x,
-                        outTransform.rotation_y,
-                        outTransform.rotation_z,
-                        outTransform.rotation_w
-                    ),
-                    scale = com.dropbear.math.Vector3D(
-                        outTransform.scale_x,
-                        outTransform.scale_y,
-                        outTransform.scale_z
-                    )
-                )
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("propagateTransform failed with code: $result")
-                } else {
-                    println("propagateTransform failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun setTransform(entityId: EntityId, transform: EntityTransform) {
-        val worldHandle = worldHandle ?: return
-        memScoped {
-            val nativeTransform = cValue<NativeEntityTransform> {
-                local.position_x = transform.local.position.x
-                local.position_y = transform.local.position.y
-                local.position_z = transform.local.position.z
-                local.rotation_w = transform.local.rotation.w
-                local.rotation_x = transform.local.rotation.x
-                local.rotation_y = transform.local.rotation.y
-                local.rotation_z = transform.local.rotation.z
-                local.scale_x = transform.local.scale.x
-                local.scale_y = transform.local.scale.y
-                local.scale_z = transform.local.scale.z
-
-                world.position_x = transform.world.position.x
-                world.position_y = transform.world.position.y
-                world.position_z = transform.world.position.z
-                world.rotation_w = transform.world.rotation.w
-                world.rotation_x = transform.world.rotation.x
-                world.rotation_y = transform.world.rotation.y
-                world.rotation_z = transform.world.rotation.z
-                world.scale_x = transform.world.scale.x
-                world.scale_y = transform.world.scale.y
-                world.scale_z = transform.world.scale.z
-            }
-
-            val result = dropbear_set_transform(
-                world_ptr = worldHandle.reinterpret(),
-                entity_id = entityId.id,
-                transform = nativeTransform
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("setTransform failed with code: $result")
-                } else {
-                    println("setTransform failed with code: $result")
-                }
-            }
-        }
-    }
-
-    actual fun printInputState() {
-        val input = inputHandle ?: return
-        dropbear_print_input_state(input_ptr = input.reinterpret())
-    }
-
-    actual fun isKeyPressed(key: KeyCode): Boolean {
-        val input = inputHandle ?: return false
-        memScoped {
-            val out = alloc<IntVar>()
-            val result = dropbear_is_key_pressed(
-                input.reinterpret(),
-                key.ordinal,
-                out.ptr
-            )
-            return if (result == 0) out.value != 0 else if (exceptionOnError) {
-                throw DropbearNativeException("isKeyPressed failed with code: $result")
-            } else {
-                println("isKeyPressed failed with code: $result")
-                false
-            }
-        }
-    }
-
-    actual fun getMousePosition(): Vector2D? {
-        val input = inputHandle ?: return null
-        memScoped {
-            val xVar = alloc<FloatVar>()
-            val yVar = alloc<FloatVar>()
-
-            val result = dropbear_get_mouse_position(
-                input.reinterpret(),
-                xVar.ptr,
-                yVar.ptr
-            )
-
-            if (result == 0) {
-                val x = xVar.value.toDouble()
-                val y = yVar.value.toDouble()
-                return Vector2D(x, y)
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getMousePosition failed with code: $result")
-                } else {
-                    println("getMousePosition failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun isMouseButtonPressed(button: MouseButton): Boolean {
-        val buttonCode: Int = when (button) {
-            MouseButton.Left -> MouseButtonCodes.LEFT
-            MouseButton.Right -> MouseButtonCodes.RIGHT
-            MouseButton.Middle -> MouseButtonCodes.MIDDLE
-            MouseButton.Back -> MouseButtonCodes.BACK
-            MouseButton.Forward -> MouseButtonCodes.FORWARD
-            is MouseButton.Other -> button.value
-        }
-
-        val input = inputHandle ?: return false
-
-        memScoped {
-            val pressedVar = alloc<IntVar>()
-
-            val result = dropbear_is_mouse_button_pressed(
-                input.reinterpret(),
-                buttonCode,
-                pressedVar.ptr
-            )
-
-            if (result == 0) {
-                return pressedVar.value != 0
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("isMouseButtonPressed failed with code: $result")
-                } else {
-                    println("isMouseButtonPressed failed with code: $result")
-                    return false
-                }
-            }
-        }
-    }
-
-    actual fun getMouseDelta(): Vector2D? {
-        val input = inputHandle ?: return null
-        memScoped {
-            val deltaXVar = alloc<FloatVar>()
-            val deltaYVar = alloc<FloatVar>()
-
-            val result = dropbear_get_mouse_delta(
-                input.reinterpret(),
-                deltaXVar.ptr,
-                deltaYVar.ptr
-            )
-
-            if (result == 0) {
-                val deltaX = deltaXVar.value.toDouble()
-                val deltaY = deltaYVar.value.toDouble()
-                return Vector2D(deltaX, deltaY)
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getMouseDelta failed with code: $result")
-                } else {
-                    println("getMouseDelta failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun isCursorLocked(): Boolean {
-        val input = inputHandle ?: return false
-        memScoped {
-            val lockedVar = alloc<IntVar>()
-
-            val result = dropbear_is_cursor_locked(
-                input.reinterpret(),
-                lockedVar.ptr
-            )
-
-            if (result == 0) {
-                return lockedVar.value != 0
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("isCursorLocked failed with code: $result")
-                } else {
-                    println("isCursorLocked failed with code: $result")
-                    return false
-                }
-            }
-        }
-    }
-
-    actual fun setCursorLocked(locked: Boolean) {
-        val lockedInt = if (locked) 1 else 0
-        val input = inputHandle ?: return
-        val graphics = commandBufferHandle ?: return
-
-        val result = dropbear_set_cursor_locked(
-            input.reinterpret(),
-            graphics.reinterpret(),
-            lockedInt
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setCursorLocked failed with code: $result")
-            } else {
-                println("setCursorLocked failed with code: $result")
-            }
-        }
-    }
-
-    actual fun getLastMousePos(): Vector2D? {
-        val input = inputHandle ?: return null
-        memScoped {
-            val xVar = alloc<FloatVar>()
-            val yVar = alloc<FloatVar>()
-
-            val result = dropbear_get_last_mouse_pos(
-                input.reinterpret(),
-                xVar.ptr,
-                yVar.ptr
-            )
-
-            if (result == 0) {
-                val x = xVar.value.toDouble()
-                val y = yVar.value.toDouble()
-                return Vector2D(x, y)
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getLastMousePos failed with code: $result")
-                } else {
-                    println("getLastMousePos failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun isCursorHidden(): Boolean {
-        val input = inputHandle ?: return false
-        memScoped {
-            val hiddenVar = alloc<IntVar>()
-
-            val result = dropbear_is_cursor_hidden(
-                input.reinterpret(),
-                hiddenVar.ptr
-            )
-
-            if (result == 0) {
-                return hiddenVar.value != 0
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("isCursorHidden failed with code: $result")
-                } else {
-                    println("isCursorHidden failed with code: $result")
-                    return false
-                }
-            }
-        }
-    }
-
-    actual fun setCursorHidden(hidden: Boolean) {
-        val hiddenInt = if (hidden) 1 else 0
-        val input = inputHandle ?: return
-        val graphics = commandBufferHandle ?: return
-
-        val result = dropbear_set_cursor_hidden(
-            input.reinterpret(),
-            graphics.reinterpret(),
-            hiddenInt
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setCursorHidden failed with code: $result")
-            } else {
-                println("setCursorHidden failed with code: $result")
-            }
-        }
-    }
-
-    actual fun getConnectedGamepads(): List<Gamepad> {
-        val input = inputHandle ?: return emptyList()
-        memScoped {
-            val gamepadsPtr = alloc<CPointerVar<com.dropbear.ffi.generated.Gamepad>>()
-            val count = alloc<IntVar>()
-
-            val result = dropbear_get_connected_gamepads(
-                input.reinterpret(),
-                gamepadsPtr.ptr,
-                count.ptr
-            )
-
-            if (result == 0) {
-                val gamepadArray = gamepadsPtr.value
-                val gamepadCount = count.value
-
-                if (gamepadArray == null || gamepadCount == 0) {
-                    return emptyList()
-                }
-
-                return List(gamepadCount) { index ->
-                    val nativeGamepad = gamepadArray[index]
-                    Gamepad(
-                        id = nativeGamepad.id.toLong(),
-                        leftStickPosition = Vector2D(
-                            x = nativeGamepad.left_stick_pos.x,
-                            y = nativeGamepad.left_stick_pos.y
-                        ),
-                        rightStickPosition = Vector2D(
-                            x = nativeGamepad.right_stick_pos.x,
-                            y = nativeGamepad.right_stick_pos.y
-                        ),
-                        native = this@NativeEngine
-                    )
-                }
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getConnectedGamepads failed with code: $result")
-                } else {
-                    println("getConnectedGamepads failed with code: $result")
-                    return emptyList()
-                }
-            }
-        }
-    }
-
-    actual fun isGamepadButtonPressed(id: Long, button: GamepadButton): Boolean {
-        val input = inputHandle ?: return false
-        memScoped {
-            val outPressed = alloc<IntVar>()
-
-            val result = dropbear_is_gamepad_button_pressed(
-                input_ptr = input.reinterpret(),
-                gamepad_id = id,
-                ordinal = button.ordinal,
-                out_pressed = outPressed.ptr
-            )
-
-            return if (result == 0) {
-                outPressed.value != 0
-            } else if (exceptionOnError) {
-                throw DropbearNativeException(
-                    "isGamepadButtonPressed failed for gamepadId='$id' button='${button.name}' with code: $result"
-                )
-            } else {
-                println(
-                    "isGamepadButtonPressed failed for gamepadId='$id' button='${button.name}' with code: $result"
-                )
-                false
-            }
-        }
-    }
-
-    actual fun getStringProperty(entityHandle: Long, label: String): String? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<CPointerVar<ByteVar>>()
-
-            val result = dropbear_get_string_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr
-            )
-
-            if (result == 0) {
-                val string = output.value?.toKString()
-                return string
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getStringProperty [$label] failed with code: $result")
-                } else {
-                    println("getStringProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getIntProperty(entityHandle: Long, label: String): Int? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<IntVar>()
-
-            val result = dropbear_get_int_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr,
-            )
-
-            if (result == 0) {
-                return output.value
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getIntProperty [$label] failed with code: $result")
-                } else {
-                    println("getIntProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getLongProperty(entityHandle: Long, label: String): Long? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<LongVar>()
-
-            val result = dropbear_get_long_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr
-            )
-
-            if (result == 0) {
-                return output.value
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getLongProperty [$label] failed with code: $result")
-                } else {
-                    println("getLongProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getFloatProperty(entityHandle: Long, label: String): Float? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<DoubleVar>()
-
-            val result = dropbear_get_float_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr
-            )
-
-            if (result == 0) {
-                return output.value.toFloat()
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getFloatProperty [$label] failed with code: $result")
-                } else {
-                    println("getFloatProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getDoubleProperty(entityHandle: Long, label: String): Double? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<DoubleVar>()
-
-            val result = dropbear_get_float_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr
-            )
-
-            if (result == 0) {
-                return output.value
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getDoubleProperty [$label] failed with code: $result")
-                } else {
-                    println("getDoubleProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getBoolProperty(entityHandle: Long, label: String): Boolean? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val output = alloc<IntVar>()
-
-            val result = dropbear_get_bool_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                output.ptr
-            )
-
-            if (result == 0) {
-                return output.value != 0
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getBoolProperty [$label] failed with code: $result")
-                } else {
-                    println("getBoolProperty [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getVec3Property(entityHandle: Long, label: String): FloatArray? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outVec = alloc<Vector3D>()
-
-            val result = dropbear_get_vec3_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                outVec.ptr
-            )
-
-            if (result == 0) {
-                return floatArrayOf(outVec.x.toFloat(), outVec.y.toFloat(), outVec.z.toFloat())
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getVec3Property [$label] failed with code: $result")
-                } else {
-                    println("getVec3Property [$label] failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun setStringProperty(entityHandle: Long, label: String, value: String) {
-        val world = worldHandle ?: return
-
-        val result = dropbear_set_string_property(
-            world.reinterpret(),
-            entityHandle,
-            label,
-            value
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setStringProperty [$label] failed with code: $result")
-            } else {
-                println("setStringProperty [$label] failed with code: $result")
-            }
-        }
-    }
-
-    actual fun setIntProperty(entityHandle: Long, label: String, value: Int) {
-        val world = worldHandle ?: return
-
-        val result = dropbear_set_int_property(
-            world.reinterpret(),
-            entityHandle,
-            label,
-            value
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setIntProperty [$label] failed with code: $result")
-            } else {
-                println("setIntProperty [$label] failed with code: $result")
-            }
-        }
-    }
-
-    actual fun setLongProperty(entityHandle: Long, label: String, value: Long) {
-        val world = worldHandle ?: return
-
-        val result = dropbear_set_long_property(
-            world.reinterpret(),
-            entityHandle,
-            label,
-            value
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setLongProperty [$label] failed with code: $result")
-            } else {
-                println("setLongProperty [$label] failed with code: $result")
-            }
-        }
-    }
-
-    actual fun setFloatProperty(entityHandle: Long, label: String, value: Double) {
-        val world = worldHandle ?: return
-
-        val result = dropbear_set_float_property(
-            world.reinterpret(),
-            entityHandle,
-            label,
-            value
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setFloatProperty [$label] failed with code: $result")
-            } else {
-                println("setFloatProperty [$label] failed with code: $result")
-            }
-        }
-    }
-
-    actual fun setBoolProperty(entityHandle: Long, label: String, value: Boolean) {
-        val world = worldHandle ?: return
-        val intValue = if (value) 1 else 0
-
-        val result = dropbear_set_bool_property(
-            world.reinterpret(),
-            entityHandle,
-            label,
-            intValue
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setBoolProperty [$label] failed with code: $result")
-            } else {
-                println("setBoolProperty [$label] failed with code: $result")
-            }
-        }
-    }
-
-    actual fun setVec3Property(entityHandle: Long, label: String, value: FloatArray) {
-        val world = worldHandle ?: return
-
-        if (value.size < 3) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setVec3Property: FloatArray must have at least 3 elements")
-            } else {
-                println("setVec3Property: FloatArray must have at least 3 elements")
-                return
-            }
-        }
-
-        memScoped {
-            val vec = cValue<Vector3D> {
-                x = value[0].toDouble()
-                y = value[1].toDouble()
-                z = value[2].toDouble()
-            }
-
-            val result = dropbear_set_vec3_property(
-                world.reinterpret(),
-                entityHandle,
-                label,
-                vec
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("setVec3Property [$label] failed with code: $result")
-                } else {
-                    println("setVec3Property [$label] failed with code: $result")
-                }
-            }
-        }
-    }
-
-    actual fun getCamera(label: String): Camera? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outCamera = alloc<NativeCamera>()
-
-            val result = dropbear_get_camera(
-                world.reinterpret(),
-                label,
-                outCamera.ptr
-            )
-
-            if (result == 0) {
-                return Camera(
-                    label = outCamera.label?.toKString() ?: "",
-                    id = EntityId(outCamera.entity_id),
-                    eye = com.dropbear.math.Vector3D(
-                        outCamera.eye.x,
-                        outCamera.eye.y,
-                        outCamera.eye.z
-                    ),
-                    target = com.dropbear.math.Vector3D(
-                        outCamera.target.x,
-                        outCamera.target.y,
-                        outCamera.target.z
-                    ),
-                    up = com.dropbear.math.Vector3D(
-                        outCamera.up.x,
-                        outCamera.up.y,
-                        outCamera.up.z
-                    ),
-                    aspect = outCamera.aspect,
-                    fov_y = outCamera.fov_y,
-                    znear = outCamera.znear,
-                    zfar = outCamera.zfar,
-                    yaw = outCamera.yaw,
-                    pitch = outCamera.pitch,
-                    speed = outCamera.speed,
-                    sensitivity = outCamera.sensitivity
-                )
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getCamera failed with code: $result")
-                } else {
-                    println("getCamera failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getAttachedCamera(entityId: EntityId): Camera? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outCamera = alloc<NativeCamera>()
-
-            val result = dropbear_get_attached_camera(
-                world.reinterpret(),
-                entityId.id,
-                outCamera.ptr
-            )
-
-            if (result == 0) {
-                return Camera(
-                    label = outCamera.label?.toKString() ?: "",
-                    id = EntityId(outCamera.entity_id),
-                    eye = com.dropbear.math.Vector3D(
-                        outCamera.eye.x,
-                        outCamera.eye.y,
-                        outCamera.eye.z
-                    ),
-                    target = com.dropbear.math.Vector3D(
-                        outCamera.target.x,
-                        outCamera.target.y,
-                        outCamera.target.z
-                    ),
-                    up = com.dropbear.math.Vector3D(
-                        outCamera.up.x,
-                        outCamera.up.y,
-                        outCamera.up.z
-                    ),
-                    aspect = outCamera.aspect,
-                    fov_y = outCamera.fov_y,
-                    znear = outCamera.znear,
-                    zfar = outCamera.zfar,
-                    yaw = outCamera.yaw,
-                    pitch = outCamera.pitch,
-                    speed = outCamera.speed,
-                    sensitivity = outCamera.sensitivity
-                )
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getAttachedCamera failed with code: $result")
-                } else {
-                    println("getAttachedCamera failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun setCamera(camera: Camera) {
-        val world = worldHandle ?: return
-        memScoped {
-            val nativeCamera = cValue<NativeCamera> {
-                label = camera.label.cstr.ptr
-                entity_id = camera.id.id
-
-                eye.x = camera.eye.x
-                eye.y = camera.eye.y
-                eye.z = camera.eye.z
-
-                target.x = camera.target.x
-                target.y = camera.target.y
-                target.z = camera.target.z
-
-                up.x = camera.up.x
-                up.y = camera.up.y
-                up.z = camera.up.z
-
-                aspect = camera.aspect
-                fov_y = camera.fov_y
-                znear = camera.znear
-                zfar = camera.zfar
-
-                yaw = camera.yaw
-                pitch = camera.pitch
-                speed = camera.speed
-                sensitivity = camera.sensitivity
-            }
-
-            val result = dropbear_set_camera(
-                world.reinterpret(),
-                nativeCamera
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("setCamera failed with code: $result")
-                } else {
-                    println("setCamera failed with code: $result")
-                }
-            }
-        }
-    }
-
-    actual fun getModel(entityHandle: Long): Long? {
-        val world = worldHandle ?: return null
-        val asset = assetHandle ?: return null
-        memScoped {
-            val outModel = alloc<LongVar>()
-            val result = dropbear_get_model(
-                world.reinterpret(),
-                asset.reinterpret(),
-                entityHandle,
-                outModel.ptr
-            )
-            return if (result == 0) outModel.value else if (exceptionOnError) throw DropbearNativeException("getModel failed with code: $result") else null
-        }
-    }
-
-    actual fun setModel(entityHandle: Long, modelHandle: Long) {
-        val world = worldHandle ?: return
-        val asset = assetHandle ?: return
-
-        val result = dropbear_set_model(
-            world.reinterpret(),
-            asset.reinterpret(),
-            entityHandle,
-            modelHandle
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setModel failed with code: $result")
-            } else {
-                println("setModel failed with code: $result")
-            }
-        }
-    }
-
-    actual fun getTexture(entityHandle: Long, name: String): Long? {
-        val world = worldHandle ?: return null
-        val asset = assetHandle ?: return null
-        memScoped {
-            val outTexture = alloc<LongVar>()
-            val result = dropbear_get_texture(
-                world.reinterpret(),
-                asset.reinterpret(),
-                entityHandle,
-                name,
-                outTexture.ptr
-            )
-            return if (result == 0) outTexture.value else if (exceptionOnError) throw DropbearNativeException("getTexture failed with code: $result") else null
-        }
-    }
-
-    actual fun isUsingModel(entityHandle: Long, modelHandle: Long): Boolean {
-        val world = worldHandle ?: return false
-        memScoped {
-            val outUsing = alloc<IntVar>()
-            val result = dropbear_is_using_model(
-                world.reinterpret(),
-                entityHandle,
-                modelHandle,
-                outUsing.ptr
-            )
-            return if (result == 0) outUsing.value != 0 else false
-        }
-    }
-
-    actual fun isUsingTexture(entityHandle: Long, textureHandle: Long): Boolean {
-        val world = worldHandle ?: return false
-        memScoped {
-            val outUsing = alloc<IntVar>()
-            val result = dropbear_is_using_texture(
-                world.reinterpret(),
-                entityHandle,
-                textureHandle,
-                outUsing.ptr
-            )
-            return if (result == 0) outUsing.value != 0 else false
-        }
-    }
-
-    actual fun getAsset(eucaURI: String): Long? {
-        val asset = assetHandle ?: return null
-        memScoped {
-            val outAsset = alloc<LongVar>()
-            val result = dropbear_get_asset(
-                asset.reinterpret(),
-                eucaURI,
-                outAsset.ptr
-            )
-            return if (result == 0) outAsset.value else null
-        }
-    }
-
-    actual fun isModelHandle(id: Long): Boolean {
-        val asset = assetHandle ?: return false
-        memScoped {
-            val outIsModel = alloc<IntVar>()
-            val result = dropbear_is_model_handle(
-                asset.reinterpret(),
-                id,
-                outIsModel.ptr
-            )
-            return if (result == 0) outIsModel.value != 0 else false
-        }
-    }
-
-    actual fun isTextureHandle(id: Long): Boolean {
-        val asset = assetHandle ?: return false
-        memScoped {
-            val outIsTexture = alloc<IntVar>()
-            val result = dropbear_is_texture_handle(
-                asset.reinterpret(),
-                id,
-                outIsTexture.ptr
-            )
-            return if (result == 0) outIsTexture.value != 0 else false
-        }
-    }
-
-    actual fun setTextureOverride(entityHandle: Long, oldMaterialName: String, newTextureHandle: TextureHandle) {
-        val world = worldHandle ?: return
-        val asset = assetHandle ?: return
-
-        val result = dropbear_set_texture(
-            world.reinterpret(),
-            asset.reinterpret(),
-            entityHandle,
-            oldMaterialName,
-            newTextureHandle.raw()
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("setTextureOverride failed with code: $result")
-            } else {
-                println("setTextureOverride failed with code: $result")
-            }
-        }
-    }
-
-    actual fun getTextureName(textureHandle: Long): String? {
-        val asset = assetHandle ?: return null
-        memScoped {
-            val outName = alloc<CPointerVar<ByteVar>>()
-            val result = dropbear_get_texture_name(
-                asset.reinterpret(),
-                textureHandle,
-                outName.ptr
-            )
-            return if (result == 0) outName.value?.toKString() else if (exceptionOnError) throw DropbearNativeException("getTextureName failed with code: $result") else null
-        }
-    }
-
-    actual fun getAllTextures(entityHandle: Long): Array<String> {
-        val world = worldHandle ?: return emptyArray()
-        val asset = assetHandle ?: return emptyArray()
-        memScoped {
-            val outTextures = alloc<CPointerVar<CPointerVar<ByteVar>>>()
-            val outCount = alloc<ULongVar>()
-
-            val result = dropbear_get_all_textures(
-                asset.reinterpret(),
-                world.reinterpret(),
-                entityHandle,
-                outTextures.ptr,
-                outCount.ptr
-            )
-
-            if (result == 0) {
-                val count = outCount.value.toInt()
-                val textureArray = Array(count) { i ->
-                    outTextures.value!![i]?.toKString() ?: ""
-                }
-                return textureArray
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getAllTextures failed with code: $result")
-                } else {
-                    println("getAllTextures failed with code: $result")
-                    return emptyArray()
-                }
-            }
-        }
-    }
-
-    actual fun getChildren(entityId: EntityId): Array<EntityRef>? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outChildren = alloc<CPointerVar<LongVar>>()
-            val outCount = alloc<ULongVar>()
-
-            val result = dropbear_get_children(
-                world.reinterpret(),
-                entityId.id,
-                outChildren.ptr,
-                outCount.ptr
-            )
-
-            if (result == 0) {
-                val count = outCount.value.toInt()
-                val childArray = Array(count) { i ->
-                    EntityRef(EntityId(outChildren.value!![i]))
-                }
-                return childArray
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getChildren failed with code: $result")
-                } else {
-                    println("getChildren failed with code: $result")
-                    return null
-                }
-            }
-        }
-    }
-
-    actual fun getChildByLabel(entityId: EntityId, label: String): EntityRef? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outChild = alloc<LongVar>()
-            val result = dropbear_get_child_by_label(
-                world.reinterpret(),
-                entityId.id,
-                label,
-                outChild.ptr
-            )
-            return if (result == 0) EntityRef(EntityId(outChild.value)) else if (exceptionOnError) throw DropbearNativeException("getChildByLabel failed with code: $result") else null
-        }
-    }
-
-    actual fun getParent(entityId: EntityId): EntityRef? {
-        val world = worldHandle ?: return null
-        memScoped {
-            val outParent = alloc<LongVar>()
-            val result = dropbear_get_parent(
-                world.reinterpret(),
-                entityId.id,
-                outParent.ptr
-            )
-            return if (result == 0) EntityRef(EntityId(outParent.value)) else if (exceptionOnError) throw DropbearNativeException("getParent failed with code: $result") else null
-        }
-    }
-
-    actual fun quit() {
-        val command = commandBufferHandle ?: if (exceptionOnError) throw DropbearNativeException("Unable to quit: graphicsHandle does not exist") else return
-        dropbear_quit(command.reinterpret())
-    }
-
-    actual fun loadSceneAsync(sceneName: String): SceneLoadHandle? {
-        val sceneLoader = sceneLoaderHandle ?: if (exceptionOnError) throw DropbearNativeException("sceneLoaderHandle is empty") else return null
-        val commandBuffer = commandBufferHandle ?: if (exceptionOnError) throw DropbearNativeException("commandBufferHandle is empty") else return null
-        memScoped {
-            val outHandle = alloc<com.dropbear.ffi.generated.SceneLoadHandle>()
-            val result = dropbear_load_scene_async_1(
-                command_ptr = commandBuffer.reinterpret(),
-                scene_loader_ptr = sceneLoader.reinterpret(),
-                name = sceneName,
-                sceneLoadHandle = outHandle.ptr
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("loadSceneAsync failed with code: $result")
-                } else {
-                    println("loadSceneAsync failed with code: $result")
-                }
-            }
-
-            return SceneLoadHandle(
-                id = outHandle.id,
-                sceneName = outHandle.name?.toKString() ?: throw Exception("loadSceneAsync failed: sceneName is null"),
-                native = this@NativeEngine,
-            )
-        }
-    }
-
-    actual fun loadSceneAsync(sceneName: String, loadingScene: String): SceneLoadHandle? {
-        val sceneLoader = sceneLoaderHandle ?: if (exceptionOnError) throw DropbearNativeException("sceneLoaderHandle is empty") else return null
-        val commandBuffer = commandBufferHandle ?: if (exceptionOnError) throw DropbearNativeException("commandBufferHandle is empty") else return null
-        memScoped {
-            val outHandle = alloc<com.dropbear.ffi.generated.SceneLoadHandle>()
-            val result = dropbear_load_scene_async_2(
-                command_ptr = commandBuffer.reinterpret(),
-                scene_loader_ptr = sceneLoader.reinterpret(),
-                name = sceneName,
-                loadingScene = loadingScene,
-                sceneLoadHandle = outHandle.ptr
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("loadSceneAsync with loading scene failed with code: $result")
-                } else {
-                    println("loadSceneAsync with loading scene failed with code: $result")
-                }
-            }
-
-            return SceneLoadHandle(
-                id = outHandle.id,
-                sceneName = outHandle.name?.toKString() ?: throw Exception("loadSceneAsync with loading scene failed: sceneName is null"),
-                native = this@NativeEngine,
-            )
-        }
-    }
-
-    actual fun switchToSceneAsync(sceneLoadHandle: SceneLoadHandle) {
-        val command = commandBufferHandle ?: if (exceptionOnError) throw DropbearNativeException("commandBufferHandle is empty") else return
-        memScoped {
-            val nativeHandle = alloc<com.dropbear.ffi.generated.SceneLoadHandle>()
-            nativeHandle.id = sceneLoadHandle.id
-            nativeHandle.name = sceneLoadHandle.sceneName.cstr.ptr
-
-            val result = dropbear_switch_to_scene_async(command.reinterpret(), nativeHandle.readValue())
-
-            if (result == -10) {
-                throw PrematureSceneSwitchException("Attempted to switch to scene before it finished loading")
-            }
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("switchToSceneAsync failed with code: $result")
-                } else {
-                    println("switchToSceneAsync failed with code: $result")
-                }
-            }
-        }
-    }
-
-    actual fun switchToSceneImmediate(sceneName: String) {
-        val command = commandBufferHandle ?: if (exceptionOnError) throw DropbearNativeException("commandBufferHandle is empty") else return
-        val result = dropbear_switch_to_scene_immediate(
-            command_ptr = command.reinterpret(),
-            name = sceneName,
-        )
-
-        if (result != 0) {
-            if (exceptionOnError) {
-                throw DropbearNativeException("switchToSceneImmediate failed with code: $result")
-            } else {
-                println("switchToSceneImmediate failed with code: $result")
-            }
-        }
-    }
-
-    actual fun getSceneLoadProgress(sceneLoadHandle: SceneLoadHandle): Progress {
-        val sceneLoader = sceneLoaderHandle ?: if (exceptionOnError) throw DropbearNativeException("sceneLoaderHandle is empty") else return Progress.nothing("Error: commandBufferHandle is empty")
-        memScoped {
-            val nativeHandle = alloc<com.dropbear.ffi.generated.SceneLoadHandle>()
-            nativeHandle.id = sceneLoadHandle.id
-            nativeHandle.name = sceneLoadHandle.sceneName.cstr.ptr
-
-            val outProgress = alloc<com.dropbear.ffi.generated.Progress>()
-
-            val result = dropbear_get_scene_load_progress(
-                scene_loader_ptr = sceneLoader.reinterpret(),
-                handle = nativeHandle.readValue(),
-                progress = outProgress.ptr
-            )
-
-            if (result != 0) {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getSceneLoadProgress failed with code: $result")
-                } else {
-                    println("getSceneLoadProgress failed with code: $result")
-                }
-            }
-
-            val progress = Progress(outProgress.current, outProgress.total, outProgress.message?.toKString());
-
-            return progress
-        }
-    }
-
-    actual fun getSceneLoadStatus(sceneLoadHandle: SceneLoadHandle): SceneLoadStatus {
-        val sceneLoader = sceneLoaderHandle ?: if (exceptionOnError) throw DropbearNativeException("sceneLoaderHandle is empty") else return SceneLoadStatus.FAILED
-        memScoped {
-            val nativeHandle = alloc<com.dropbear.ffi.generated.SceneLoadHandle>()
-            nativeHandle.id = sceneLoadHandle.id
-            nativeHandle.name = sceneLoadHandle.sceneName.cstr.ptr
-
-            val nativeStatus = alloc<SceneLoadResult.Var>()
-
-            val result = dropbear_get_scene_load_status(
-                scene_loader_ptr = sceneLoader.reinterpret(),
-                handle = nativeHandle.readValue(),
-                result = nativeStatus.ptr
-            )
-            if (result == 0) {
-                return nativeStatus.value.fromNative()
-            } else {
-                if (exceptionOnError) {
-                    throw DropbearNativeException("getSceneLoadStatus failed with code: $result")
-                } else {
-                    println("getSceneLoadStatus failed with code: $result")
-                    return SceneLoadStatus.FAILED
-                }
-            }
-        }
-    }
-
-    actual fun setPhysicsEnabled(entityId: Long, enabled: Boolean) {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Physics engine handle is null") else return
-
-        val result = dropbear_set_physics_enabled(
-            world.reinterpret(),
-            pe.reinterpret(),
-            entityId,
-            enabled
-        )
-
-        handleResult(result, "setPhysicsEnabled")
-    }
-
-    actual fun isPhysicsEnabled(entityId: Long): Boolean {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return false
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Physics engine handle is null") else return false
-
-        memScoped {
-            val outEnabled = alloc<BooleanVar>()
-
-            val result = dropbear_is_physics_enabled(
-                world.reinterpret(),
-                pe.reinterpret(),
-                entityId,
-                outEnabled.ptr
-            )
-
-            if (result != 0) {
-                handleResult(result, "isPhysicsEnabled")
-                return false
-            }
-
-            return outEnabled.value
-        }
-    }
-
-    actual fun getRigidBody(entityId: Long): RigidBody? {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return null
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Physics engine handle is null") else return null
-
-        memScoped {
-            val outRigidBody = alloc<com.dropbear.ffi.generated.RigidBody>()
-
-            val result = dropbear_get_rigidbody(
-                world.reinterpret(),
-                pe.reinterpret(),
-                entityId,
-                outRigidBody.ptr
-            )
-
-            if (result != 0) {
-                handleResult(result, "getRigidBody")
-                return null
-            }
-
-            return outRigidBody.toKotlin(this@NativeEngine)
-        }
-    }
-
-    actual fun getAllColliders(entityId: Long): List<Collider> {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return emptyList()
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Physics engine handle is null") else return emptyList()
-
-        memScoped {
-            val outCollidersPtr = alloc<CPointerVar<com.dropbear.ffi.generated.Collider>>()
-            val outCount = alloc<UIntVar>()
-
-            val result = dropbear_get_all_colliders(
-                world.reinterpret(),
-                pe.reinterpret(),
-                entityId,
-                outCollidersPtr.ptr,
-                outCount.ptr
-            )
-
-            if (result != 0) {
-                handleResult(result, "getAllColliders")
-                return emptyList()
-            }
-
-            val count = outCount.value.toInt()
-            val cArray = outCollidersPtr.value
-
-            if (cArray == null || count == 0) {
-                return emptyList()
-            }
-
-            val list = ArrayList<Collider>(count)
-            for (i in 0 until count) {
-                val cCollider = cArray[i]
-                list.add(cCollider.toKotlin(this@NativeEngine))
-            }
-
-            dropbear_free_colliders(cArray, outCount.value)
-
-            return list
-        }
-    }
-
-    actual fun applyImpulse(index: Index, x: Double, y: Double, z: Double) {
-        val pe = physicsEngineHandle ?: return
-
-        memScoped {
-            val cIndex = alloc<com.dropbear.ffi.generated.Index>()
-            cIndex.index = index.index
-            cIndex.generation = index.generation
-
-            val cImpulse = alloc<com.dropbear.ffi.generated.Vector3D>()
-            cImpulse.x = x
-            cImpulse.y = y
-            cImpulse.z = z
-
-            dropbear_apply_impulse(
-                pe.reinterpret(),
-                cIndex.readValue(),
-                cImpulse.readValue()
-            )
-        }
-    }
-
-    actual fun applyTorqueImpulse(index: Index, x: Double, y: Double, z: Double) {
-        val pe = physicsEngineHandle ?: return
-
-        memScoped {
-            val cIndex = alloc<com.dropbear.ffi.generated.Index>()
-            cIndex.index = index.index
-            cIndex.generation = index.generation
-
-            val cTorque = alloc<Vector3D>()
-            cTorque.x = x
-            cTorque.y = y
-            cTorque.z = z
-
-            dropbear_apply_torque_impulse(
-                pe.reinterpret(),
-                cIndex.readValue(),
-                cTorque.readValue()
-            )
-        }
-    }
-
-    actual fun setRigidbody(rigidBody: RigidBody) {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Handle null") else return
-
-        memScoped {
-            val cBody = alloc<com.dropbear.ffi.generated.RigidBody>()
-            rigidBody.populateCStruct(cBody)
-
-            val result = dropbear_set_rigidbody(
-                world.reinterpret(),
-                pe.reinterpret(),
-                cBody.readValue()
-            )
-            handleResult(result, "setRigidbody")
-        }
-    }
-
-    actual fun getChildColliders(index: Index): List<Collider> {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return emptyList()
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Handle null") else return emptyList()
-
-        memScoped {
-            val cIndex = alloc<com.dropbear.ffi.generated.Index>()
-            cIndex.index = index.index
-            cIndex.generation = index.generation
-
-            val outCollidersPtr = alloc<CPointerVar<com.dropbear.ffi.generated.Collider>>()
-            val outCount = alloc<UIntVar>()
-
-            val result = dropbear_get_child_colliders(
-                world.reinterpret(),
-                pe.reinterpret(),
-                cIndex.readValue(),
-                outCollidersPtr.ptr,
-                outCount.ptr
-            )
-
-            if (result != 0) {
-                handleResult(result, "getChildColliders")
-                return emptyList()
-            }
-
-            val count = outCount.value.toInt()
-            val cArray = outCollidersPtr.value
-
-            if (cArray == null || count == 0) return emptyList()
-
-            val list = ArrayList<Collider>(count)
-            for (i in 0 until count) {
-                list.add(cArray[i].toKotlin(this@NativeEngine))
-            }
-
-            dropbear_free_colliders(cArray, outCount.value)
-            return list
-        }
-    }
-
-    actual fun setCollider(collider: Collider) {
-        val world = worldHandle ?: if (exceptionOnError) throw DropbearNativeException("world handle null") else return
-        val pe = physicsEngineHandle ?: if (exceptionOnError) throw DropbearNativeException("Handle null") else return
-
-        memScoped {
-            val cCollider = alloc<com.dropbear.ffi.generated.Collider>()
-            collider.populateCStruct(cCollider)
-
-            val result = dropbear_set_collider(
-                world.reinterpret(),
-                pe.reinterpret(),
-                cCollider.readValue()
-            )
-            handleResult(result, "setCollider")
-        }
-    }
-}
-
-private fun handleResult(result: Int, funcName: String) {
-    if (result != 0) {
-        val msg = "$funcName failed with code: $result"
-        if (exceptionOnError) {
-            throw DropbearNativeException(msg)
-        } else {
-            Logger.error(msg)
-        }
-    }
 }
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt b/src/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt
new file mode 100644
index 0000000..ea1c67c
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt
@@ -0,0 +1,8 @@
+package com.dropbear.input
+
+actual fun Gamepad.isGamepadButtonPressed(
+    id: Long,
+    button: GamepadButton
+): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/input/InputState.native.kt b/src/nativeMain/kotlin/com/dropbear/input/InputState.native.kt
new file mode 100644
index 0000000..d41379b
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/input/InputState.native.kt
@@ -0,0 +1,46 @@
+package com.dropbear.input
+
+import com.dropbear.math.Vector2D
+
+actual class InputState actual constructor() {
+    actual fun printInputState() {
+    }
+
+    actual fun isKeyPressed(key: KeyCode): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun getMousePosition(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isMouseButtonPressed(button: MouseButton): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun getMouseDelta(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isCursorLocked(): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun setCursorLocked(locked: Boolean) {
+    }
+
+    actual fun getLastMousePos(): Vector2D {
+        TODO("Not yet implemented")
+    }
+
+    actual fun isCursorHidden(): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    actual fun setCursorHidden(hidden: Boolean) {
+    }
+
+    actual fun getConnectedGamepads(): List<Gamepad> {
+        TODO("Not yet implemented")
+    }
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt b/src/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt
new file mode 100644
index 0000000..5de9593
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt
@@ -0,0 +1,80 @@
+package com.dropbear.physics
+
+import com.dropbear.math.Vector3D
+
+actual fun Collider.getColliderShape(collider: Collider): ColliderShape {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderShape(
+    collider: Collider,
+    shape: ColliderShape
+) {
+}
+
+actual fun Collider.setColliderDensity(
+    collider: Collider,
+    density: Double
+) {
+}
+
+actual fun Collider.getColliderFriction(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderFriction(
+    collider: Collider,
+    friction: Double
+) {
+}
+
+actual fun Collider.getColliderRestitution(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderRestitution(
+    collider: Collider,
+    restitution: Double
+) {
+}
+
+actual fun Collider.getColliderIsSensor(collider: Collider): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderIsSensor(
+    collider: Collider,
+    isSensor: Boolean
+) {
+}
+
+actual fun Collider.getColliderTranslation(collider: Collider): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderTranslation(
+    collider: Collider,
+    translation: Vector3D
+) {
+}
+
+actual fun Collider.getColliderRotation(collider: Collider): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderRotation(
+    collider: Collider,
+    rotation: Vector3D
+) {
+}
+
+actual fun Collider.getColliderMass(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun Collider.setColliderMass(collider: Collider, mass: Double) {
+}
+
+actual fun Collider.getColliderDensity(collider: Collider): Double {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt b/src/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt
new file mode 100644
index 0000000..24537dc
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt
@@ -0,0 +1,11 @@
+package com.dropbear.physics
+
+import com.dropbear.EntityId
+
+actual fun ColliderGroup.getColliderGroupColliders(colliderGroup: ColliderGroup): List<Collider> {
+    TODO("Not yet implemented")
+}
+
+actual fun colliderGroupExistsForEntity(entityId: EntityId): Boolean {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt b/src/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt
new file mode 100644
index 0000000..93d12d1
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt
@@ -0,0 +1,134 @@
+package com.dropbear.physics
+
+import com.dropbear.EntityId
+import com.dropbear.math.Vector3D
+
+actual fun RigidBody.setRigidbodyMode(
+    rigidBody: RigidBody,
+    mode: RigidBodyMode
+) {
+}
+
+actual fun RigidBody.getRigidbodyMode(rigidBody: RigidBody): RigidBodyMode {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.getRigidbodyGravityScale(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyGravityScale(
+    rigidBody: RigidBody,
+    gravityScale: Double
+) {
+}
+
+actual fun RigidBody.getRigidbodyCanSleep(rigidBody: RigidBody): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyCanSleep(
+    rigidBody: RigidBody,
+    canSleep: Boolean
+) {
+}
+
+actual fun RigidBody.getRigidbodyCcdEnabled(rigidBody: RigidBody): Boolean {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyCcdEnabled(
+    rigidBody: RigidBody,
+    ccdEnabled: Boolean
+) {
+}
+
+actual fun RigidBody.getRigidbodyLinearVelocity(rigidBody: RigidBody): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLinearDamping(
+    rigidBody: RigidBody,
+    linearDamping: Double
+) {
+}
+
+actual fun RigidBody.setRigidbodyLinearVelocity(
+    rigidBody: RigidBody,
+    linearVelocity: Vector3D
+) {
+}
+
+actual fun RigidBody.getRigidbodyAngularVelocity(rigidBody: RigidBody): Vector3D {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyAngularVelocity(
+    rigidBody: RigidBody,
+    angularVelocity: Vector3D
+) {
+}
+
+actual fun RigidBody.getRigidbodyLinearDamping(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.getRigidbodyAngularDamping(rigidBody: RigidBody): Double {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyAngularDamping(
+    rigidBody: RigidBody,
+    angularDamping: Double
+) {
+}
+
+actual fun RigidBody.getRigidbodyLockTranslation(rigidBody: RigidBody): AxisLock {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLockTranslation(
+    rigidBody: RigidBody,
+    lockTranslation: AxisLock
+) {
+}
+
+actual fun RigidBody.getRigidbodyLockRotation(rigidBody: RigidBody): AxisLock {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyLockRotation(
+    rigidBody: RigidBody,
+    lockRotation: AxisLock
+) {
+}
+
+actual fun RigidBody.getRigidbodyChildren(rigidBody: RigidBody): List<EntityId> {
+    TODO("Not yet implemented")
+}
+
+actual fun RigidBody.setRigidbodyChildren(
+    rigidBody: RigidBody,
+    children: List<EntityId>
+) {
+}
+
+actual fun RigidBody.applyImpulse(
+    index: Index,
+    x: Double,
+    y: Double,
+    z: Double
+) {
+}
+
+actual fun RigidBody.applyTorqueImpulse(
+    index: Index,
+    x: Double,
+    y: Double,
+    z: Double
+) {
+}
+
+actual fun rigidBodyExistsForEntity(entityId: EntityId): Index? {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt b/src/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt
new file mode 100644
index 0000000..56bbcfc
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt
@@ -0,0 +1,15 @@
+package com.dropbear.scene
+
+import com.dropbear.utils.Progress
+
+actual fun SceneLoadHandle.switchToSceneAsync(): SceneLoadHandle {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneLoadHandle.getSceneLoadProgress(): Progress {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneLoadHandle.getSceneLoadStatus(): SceneLoadStatus {
+    TODO("Not yet implemented")
+}
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt b/src/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt
new file mode 100644
index 0000000..7524afa
--- /dev/null
+++ b/src/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt
@@ -0,0 +1,15 @@
+package com.dropbear.scene
+
+actual fun SceneManager.loadSceneAsyncNative(sceneName: String): SceneLoadHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneManager.loadSceneAsyncNative(
+    sceneName: String,
+    loading_scene: String
+): SceneLoadHandle? {
+    TODO("Not yet implemented")
+}
+
+actual fun SceneManager.switchToSceneImmediateNative(sceneName: String) {
+}
\ No newline at end of file