kitgit

tirbofish/dropbear · diff

bd6a938 · Thribhu K

feature: native kotlin fix: fixed up model not being saved properly refactor: removed building for the time being. jarvis, run github actions

Unverified

diff --git a/crates/dropbear-engine/src/model.rs b/crates/dropbear-engine/src/model.rs
index fd4db41..51612e9 100644
--- a/crates/dropbear-engine/src/model.rs
+++ b/crates/dropbear-engine/src/model.rs
@@ -1132,6 +1132,7 @@ impl Model {
         B: AsRef<[u8]>,
     {
         puffin::profile_function!(label.unwrap_or("unlabelled model"));
+        log::debug!("Loading model: {:?}", label);
         let mut registry = registry.write();
 
         let model_label = label
diff --git a/crates/eucalyptus-core/src/component.rs b/crates/eucalyptus-core/src/component.rs
index 176f098..dad4208 100644
--- a/crates/eucalyptus-core/src/component.rs
+++ b/crates/eucalyptus-core/src/component.rs
@@ -2,7 +2,7 @@ use crate::hierarchy::EntityTransformExt;
 use crate::physics::PhysicsState;
 use crate::ser::model::EucalyptusModel;
 use crate::states::{SerializedMaterialCustomisation, SerializedMeshRenderer};
-use crate::utils::{AsFile, ResolveReference};
+use crate::utils::{ResolveReference};
 use downcast_rs::{Downcast, impl_downcast};
 use dropbear_engine::asset::{ASSET_REGISTRY, Handle};
 use dropbear_engine::entity::{EntityTransform, MeshRenderer, Transform};
@@ -600,7 +600,7 @@ impl Component for MeshRenderer {
                 match crate::metadata::find_asset_by_uuid(&project_root, uuid) {
                     Ok(entry) => {
                         if let crate::resource::ResourceReference::File(rel) = &entry.location {
-                            let abs = project_root.join("resources").join(rel);
+                            let abs = project_root.join(rel);
                             match ResourceReference::from_path(&abs) {
                                 Ok(engine_ref) => {
                                     log::debug!("Loading model '{}' via UUID {}", entry.name, uuid);
diff --git a/crates/eucalyptus-editor/src/build.rs b/crates/eucalyptus-editor/src/build.rs
index e5d36e1..5aa33a6 100644
--- a/crates/eucalyptus-editor/src/build.rs
+++ b/crates/eucalyptus-editor/src/build.rs
@@ -4,10 +4,8 @@ use crossbeam_channel::Sender;
 use eucalyptus_core::APP_INFO;
 use eucalyptus_core::config::ProjectConfig;
 use eucalyptus_core::runtime::RuntimeProjectConfig;
-use eucalyptus_core::scene::SceneConfig;
 use magna_carta::Target;
 use ron::ser::PrettyConfig;
-use semver::Version;
 use std::fs;
 use std::path::{Path, PathBuf};
 use std::time::UNIX_EPOCH;
@@ -16,83 +14,85 @@ use tokio::{fs as tokio_fs, process::Command, task};
 /// Builds a eucalyptus project into a single bundle.
 ///
 /// Returns the path of the build directory
-pub fn build(project_config: PathBuf) -> anyhow::Result<PathBuf> {
+pub fn build(_project_config: PathBuf) -> anyhow::Result<PathBuf> {
     // todo: remake this entire function
     return Err(anyhow::anyhow!("Not implemented yet"));
-    log::info!("Started project building");
-    // create a build directory
-    let project_root = project_config
-        .parent()
-        .ok_or(anyhow::anyhow!("Unable to locate parent folder of config"))?
-        .to_path_buf();
-    let build_dir = project_root.join("build/output");
 
-    if build_dir.exists() {
-        fs::remove_dir_all(&build_dir)?;
-    }
-    fs::create_dir_all(&build_dir)?;
-    log::debug!("Readied build directory");
-
-    // load the project config manually to avoid overwriting global state
-    let ron_str = fs::read_to_string(&project_config)?;
-    let mut config: ProjectConfig = ron::de::from_str(&ron_str)?;
-    config.project_path = project_root.clone();
-    log::debug!("Loaded project config");
-
-    // load scenes
-    let mut scenes = Vec::new();
-    let scene_folder = project_root.join("resources").join("scenes");
-    if scene_folder.exists() {
-        for entry in fs::read_dir(scene_folder)? {
-            let entry = entry?;
-            let path = entry.path();
-            if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("eucs") {
-                match SceneConfig::read_from(&path) {
-                    Ok(scene) => {
-                        scenes.push(scene);
-                    }
-                    Err(e) => {
-                        log::warn!("Failed to load scene {:?} during build: {}", path, e);
-                    }
-                }
-            }
-        }
-    }
+    
+    // log::info!("Started project building");
+    // // create a build directory
+    // let project_root = project_config
+    //     .parent()
+    //     .ok_or(anyhow::anyhow!("Unable to locate parent folder of config"))?
+    //     .to_path_buf();
+    // let build_dir = project_root.join("build/output");
+
+    // if build_dir.exists() {
+    //     fs::remove_dir_all(&build_dir)?;
+    // }
+    // fs::create_dir_all(&build_dir)?;
+    // log::debug!("Readied build directory");
+
+    // // load the project config manually to avoid overwriting global state
+    // let ron_str = fs::read_to_string(&project_config)?;
+    // let mut config: ProjectConfig = ron::de::from_str(&ron_str)?;
+    // config.project_path = project_root.clone();
+    // log::debug!("Loaded project config");
+
+    // // load scenes
+    // let mut scenes = Vec::new();
+    // let scene_folder = project_root.join("resources").join("scenes");
+    // if scene_folder.exists() {
+    //     for entry in fs::read_dir(scene_folder)? {
+    //         let entry = entry?;
+    //         let path = entry.path();
+    //         if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("eucs") {
+    //             match SceneConfig::read_from(&path) {
+    //                 Ok(scene) => {
+    //                     scenes.push(scene);
+    //                 }
+    //                 Err(e) => {
+    //                     log::warn!("Failed to load scene {:?} during build: {}", path, e);
+    //                 }
+    //             }
+    //         }
+    //     }
+    // }
 
-    // convert to runtime project config
-    let runtime_config = RuntimeProjectConfig {
-        project_name: config.project_name.clone(),
-        runtime_settings: config.runtime_settings.clone(),
-        scenes,
-        authors: config.authors.clone(),
-        editor_version: Version::parse(env!("CARGO_PKG_VERSION"))?,
-        project_version: Version::parse(config.project_version.clone().as_str())?,
-        initial_scene: config
-            .runtime_settings
-            .initial_scene
-            .ok_or(anyhow::anyhow!(
-                "Project was expected to be an initial scene"
-            ))?,
-    };
-    log::debug!("Converted to runtime project config");
-
-    // export to .eupak
-    let eupak_path = build_dir.join("data.eupak");
-    let config_bytes = postcard::to_stdvec::<RuntimeProjectConfig>(&runtime_config)?;
-    fs::write(&eupak_path, config_bytes)?;
-    log::debug!("Exported scene config to {:?}", eupak_path);
-
-    // copy resources
-    let resources_src = project_root.join("resources");
-    let resources_dst = build_dir.join("resources");
-    if resources_src.exists() {
-        copy_dir_recursive(&resources_src, &resources_dst)?;
-        log::debug!("Copied resources to {:?}", resources_dst);
-    }
+    // // convert to runtime project config
+    // let runtime_config = RuntimeProjectConfig {
+    //     project_name: config.project_name.clone(),
+    //     runtime_settings: config.runtime_settings.clone(),
+    //     scenes,
+    //     authors: config.authors.clone(),
+    //     editor_version: Version::parse(env!("CARGO_PKG_VERSION"))?,
+    //     project_version: Version::parse(config.project_version.clone().as_str())?,
+    //     initial_scene: config
+    //         .runtime_settings
+    //         .initial_scene
+    //         .ok_or(anyhow::anyhow!(
+    //             "Project was expected to be an initial scene"
+    //         ))?,
+    // };
+    // log::debug!("Converted to runtime project config");
+
+    // // export to .eupak
+    // let eupak_path = build_dir.join("data.eupak");
+    // let config_bytes = postcard::to_stdvec::<RuntimeProjectConfig>(&runtime_config)?;
+    // fs::write(&eupak_path, config_bytes)?;
+    // log::debug!("Exported scene config to {:?}", eupak_path);
+
+    // // copy resources
+    // let resources_src = project_root.join("resources");
+    // let resources_dst = build_dir.join("resources");
+    // if resources_src.exists() {
+    //     copy_dir_recursive(&resources_src, &resources_dst)?;
+    //     log::debug!("Copied resources to {:?}", resources_dst);
+    // }
 
-    log::info!("Success creating data.eupak file!");
+    // log::info!("Success creating data.eupak file!");
 
-    Ok(build_dir)
+    // Ok(build_dir)
 }
 
 fn copy_dir_recursive(src: &Path, dst: &Path) -> anyhow::Result<()> {
diff --git a/crates/eucalyptus-editor/src/editor/mod.rs b/crates/eucalyptus-editor/src/editor/mod.rs
index 3ff929c..57a9c52 100644
--- a/crates/eucalyptus-editor/src/editor/mod.rs
+++ b/crates/eucalyptus-editor/src/editor/mod.rs
@@ -737,49 +737,6 @@ impl Editor {
         Ok(())
     }
 
-    pub(crate) fn queue_scene_load_by_name(&mut self, scene_name: &str) -> anyhow::Result<()> {
-        if scene_name.trim().is_empty() {
-            return Err(anyhow::anyhow!("Scene name cannot be empty"));
-        }
-
-        let should_persist_current = self.current_scene_name.is_some()
-            && self.is_world_loaded.is_fully_loaded()
-            && self.world.len() > 0
-            && {
-                let scenes = SCENES.read();
-                !scenes.is_empty()
-            };
-
-        if should_persist_current {
-            self.save_current_scene()?;
-        }
-
-        if let Some(current) = self.current_scene_name.as_deref() {
-            states::unload_scene(current);
-        }
-
-        let scene = states::load_scene(scene_name)?;
-
-        {
-            let mut scenes = SCENES.write();
-            scenes.retain(|existing| existing.scene_name != scene.scene_name);
-            scenes.insert(0, scene.clone());
-        }
-
-        {
-            let mut project = PROJECT.write();
-            project.last_opened_scene = Some(scene.scene_name.clone());
-            project.write_to_all()?;
-        }
-
-        log::info!("Scene '{}' staged for loading", scene.scene_name);
-
-        self.current_scene_name = Some(scene.scene_name.clone());
-        self.pending_scene_load = Some(PendingSceneLoad { scene });
-
-        Ok(())
-    }
-
     fn cleanup_scene_resources(
         &mut self,
         graphics: std::sync::Arc<dropbear_engine::graphics::SharedGraphicsContext>,
diff --git a/scripting/dropbear.def b/scripting/dropbear.def
index 1c12c33..3fc87f0 100644
--- a/scripting/dropbear.def
+++ b/scripting/dropbear.def
@@ -1,4 +1,3 @@
 package: com.dropbear.ffi.generated
 headers: dropbear.h
-headerFilter: *.h
-libraryPaths: src
\ No newline at end of file
+headerFilter: *.h
\ No newline at end of file
diff --git a/scripting/jvmMain/java/com/dropbear/asset/ModelNative.java b/scripting/jvmMain/java/com/dropbear/asset/ModelNative.java
index acf273b..f7cb7c3 100644
--- a/scripting/jvmMain/java/com/dropbear/asset/ModelNative.java
+++ b/scripting/jvmMain/java/com/dropbear/asset/ModelNative.java
@@ -2,6 +2,7 @@ package com.dropbear.asset;
 
 import com.dropbear.EucalyptusCoreLoader;
 import com.dropbear.asset.model.*;
+import java.util.List;
 
 public class ModelNative {
     static {
@@ -9,9 +10,9 @@ public class ModelNative {
     }
 
     public static native String getLabel(long assetManagerHandle, String modelName);
-    public static native Mesh[] getMeshes(long assetManagerHandle, long modelHandle);
-    public static native Material[] getMaterials(long assetManagerHandle, long modelHandle);
-    public static native Skin[] getSkins(long assetManagerHandle, long modelHandle);
-    public static native Animation[] getAnimations(long assetManagerHandle, long modelHandle);
-    public static native Node[] getNodes(long assetManagerHandle, long modelHandle);
+    public static native List<Mesh> getMeshes(long assetManagerHandle, long modelHandle);
+    public static native List<Material> getMaterials(long assetManagerHandle, long modelHandle);
+    public static native List<Skin> getSkins(long assetManagerHandle, long modelHandle);
+    public static native List<Animation> getAnimations(long assetManagerHandle, long modelHandle);
+    public static native List<Node> getNodes(long assetManagerHandle, long modelHandle);
 }
diff --git a/scripting/jvmMain/java/com/dropbear/physics/ColliderGroupNative.java b/scripting/jvmMain/java/com/dropbear/physics/ColliderGroupNative.java
index 59b05be..55417e9 100644
--- a/scripting/jvmMain/java/com/dropbear/physics/ColliderGroupNative.java
+++ b/scripting/jvmMain/java/com/dropbear/physics/ColliderGroupNative.java
@@ -1,6 +1,7 @@
 package com.dropbear.physics;
 
 import com.dropbear.EucalyptusCoreLoader;
+import java.util.List;
 
 public class ColliderGroupNative {
     static {
@@ -8,5 +9,5 @@ public class ColliderGroupNative {
     }
 
     public static native boolean colliderGroupExistsForEntity(long worldPtr, long entityId);
-    public static native Collider[] getColliderGroupColliders(long worldPtr, long physicsPtr, long entityId);
+    public static native List<Collider> getColliderGroupColliders(long worldPtr, long physicsPtr, long entityId);
 }
\ No newline at end of file
diff --git a/scripting/jvmMain/java/com/dropbear/physics/KinematicCharacterControllerNative.java b/scripting/jvmMain/java/com/dropbear/physics/KinematicCharacterControllerNative.java
index daa6c54..6250cea 100644
--- a/scripting/jvmMain/java/com/dropbear/physics/KinematicCharacterControllerNative.java
+++ b/scripting/jvmMain/java/com/dropbear/physics/KinematicCharacterControllerNative.java
@@ -3,6 +3,7 @@ package com.dropbear.physics;
 import com.dropbear.EucalyptusCoreLoader;
 import com.dropbear.math.Vector3d;
 import com.dropbear.math.Quaterniond;
+import java.util.List;
 
 // fuck, this got a long ass name
 public class KinematicCharacterControllerNative {
@@ -14,6 +15,6 @@ public class KinematicCharacterControllerNative {
 
     public static native void moveCharacter(long worldHandle, long physicsHandle, long entityHandle, Vector3d translation, double deltaTime);
     public static native void setRotation(long worldHandle, long physicsHandle, long entityHandle, Quaterniond rotation);
-    public static native CharacterCollision[] getHit(long worldHandle, long entity);
+    public static native List<CharacterCollision> getHit(long worldHandle, long entity);
     public static native CharacterMovementResult getMovementResult(long worldHandle, long entity);
 }
diff --git a/scripting/jvmMain/kotlin/com/dropbear/host/HotSwapUtility.kt b/scripting/jvmMain/kotlin/com/dropbear/host/HotSwapUtility.kt
index a78165d..98b62a1 100644
--- a/scripting/jvmMain/kotlin/com/dropbear/host/HotSwapUtility.kt
+++ b/scripting/jvmMain/kotlin/com/dropbear/host/HotSwapUtility.kt
@@ -33,17 +33,23 @@ class HotSwapUtility(
         InstantiationException::class
     )
     fun getInstance(parameterTypes: Array<Class<*>>, args: Array<out Any?>): Any {
-        val clazz = classLoader.loadClass(className)
-        if (clazz.isAnnotationPresent(Metadata::class.java)) {
-            try {
-                val instanceField = clazz.getDeclaredField("INSTANCE")
-                return instanceField.get(null)
-            } catch (e: NoSuchFieldException) {
-                Logger.error("Failed to get instance of class: ${e.message}")
+        try {
+            val clazz = classLoader.loadClass(className)
+            if (clazz.isAnnotationPresent(Metadata::class.java)) {
+                try {
+                    val instanceField = clazz.getDeclaredField("INSTANCE")
+                    return instanceField.get(null)
+                } catch (e: NoSuchFieldException) {
+                    Logger.error("Failed to get instance of class: ${e.message}")
+                }
             }
+            val constructor = clazz.getConstructor(*parameterTypes)
+            return constructor.newInstance(*args)
+        } catch (e: ClassNotFoundException) {
+            throw ClassNotFoundException("Class not found: $className. It seems like you have not generated your magna-carta manifest file.\n$e")
+        } catch (e: Exception) {
+            throw e
         }
-        val constructor = clazz.getConstructor(*parameterTypes)
-        return constructor.newInstance(*args)
     }
 
     fun reloadJar(newJarFilePath: String) {
diff --git a/scripting/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt b/scripting/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt
index 68530f7..71047e1 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/DropbearEngine.native.kt
@@ -1,19 +1,41 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear
 
-import com.dropbear.components.Camera
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.ui.UIInstruction
+import kotlinx.cinterop.*
 
-internal actual fun getEntity(label: String): Long? {
-    TODO("Not yet implemented")
+internal actual fun getEntity(label: String): Long? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val rc = dropbear_engine_get_entity(world, label, out.ptr)
+    if (rc != 0) null else out.value.toLong()
 }
 
-internal actual fun getAsset(eucaURI: String): Long? {
-    TODO("Not yet implemented")
+internal actual fun getAsset(eucaURI: String): Long? = memScoped {
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped null
+    val outId = alloc<ULongVar>()
+    val outPresent = alloc<BooleanVar>()
+
+    val kindVar = alloc<UIntVar>()
+    // Try Texture
+    kindVar.value = AssetKind_Texture
+    var rc = dropbear_engine_get_asset(assets, eucaURI, kindVar.ptr, outId.ptr, outPresent.ptr)
+    if (rc == 0 && outPresent.value) return@memScoped outId.value.toLong()
+
+    // Try Model
+    kindVar.value = AssetKind_Model
+    rc = dropbear_engine_get_asset(assets, eucaURI, kindVar.ptr, outId.ptr, outPresent.ptr)
+    if (rc == 0 && outPresent.value) outId.value.toLong() else null
 }
 
 internal actual fun quit() {
-
+    val cmd = DropbearEngine.native.commandBufferHandle ?: return
+    memScoped { dropbear_engine_quit(cmd) }
 }
 
 internal actual fun renderUI(instructions: List<UIInstruction>) {
+    // UI rendering via native scripting is not yet wired
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/EntityRef.native.kt b/scripting/nativeMain/kotlin/com/dropbear/EntityRef.native.kt
index bc9bdbf..ccb3a53 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/EntityRef.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/EntityRef.native.kt
@@ -1,20 +1,40 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear
 
-internal actual fun EntityRef.Companion.getEntityLabel(entity: EntityId): String {
-    TODO("Not yet implemented")
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
+
+internal actual fun EntityRef.Companion.getEntityLabel(entity: EntityId): String = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped ""
+    val out = alloc<CPointerVar<ByteVar>>()
+    val rc = dropbear_entity_get_label(world, entity.raw.toULong(), out.ptr)
+    if (rc != 0) "" else out.value?.toKString() ?: ""
 }
 
-internal actual fun EntityRef.getChildren(entityId: EntityId): Array<EntityRef>? {
-    TODO("Not yet implemented")
+internal actual fun EntityRef.getChildren(entityId: EntityId): Array<EntityRef>? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<u64Array>()
+    val rc = dropbear_entity_get_children(world, entityId.raw.toULong(), out.ptr)
+    if (rc != 0) return@memScoped null
+    val ptr = out.values ?: return@memScoped emptyArray()
+    val len = out.length.toInt()
+    Array(len) { i -> EntityRef(EntityId(ptr[i].toLong())) }
 }
 
-internal actual fun EntityRef.getChildByLabel(
-    entityId: EntityId,
-    label: String
-): EntityRef? {
-    TODO("Not yet implemented")
+internal actual fun EntityRef.getChildByLabel(entityId: EntityId, label: String): EntityRef? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_entity_get_child_by_label(world, entityId.raw.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else EntityRef(EntityId(out.value.toLong()))
 }
 
-internal actual fun EntityRef.getParent(entityId: EntityId): EntityRef? {
-    TODO("Not yet implemented")
+internal actual fun EntityRef.getParent(entityId: EntityId): EntityRef? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_entity_get_parent(world, entityId.raw.toULong(), out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else EntityRef(EntityId(out.value.toLong()))
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/animation/AnimationComponent.native.kt b/scripting/nativeMain/kotlin/com/dropbear/animation/AnimationComponent.native.kt
index 0e3595d..11ece3c 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/animation/AnimationComponent.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/animation/AnimationComponent.native.kt
@@ -1,50 +1,101 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.animation
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-actual fun AnimationComponent.getActiveAnimationIndex(): Int? {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getActiveAnimationIndex(): Int? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<IntVar>()
+    val present = alloc<BooleanVar>()
+    dropbear_animation_get_active_animation_index(world, parentEntity.raw.toULong(), out.ptr, present.ptr)
+    if (!present.value) null else out.value
 }
 
-actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) {
+actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    if (index == null) {
+        dropbear_animation_set_active_animation_index(world, parentEntity.raw.toULong(), null)
+    } else {
+        val iv = alloc<IntVar>(); iv.value = index
+        val pv = alloc<CPointerVar<IntVar>>(); pv.value = iv.ptr
+        dropbear_animation_set_active_animation_index(world, parentEntity.raw.toULong(), pv.ptr)
+    }
 }
 
-actual fun AnimationComponent.getTime(): Double {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getTime(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_animation_get_time(world, parentEntity.raw.toULong(), out.ptr)
+    out.value
 }
 
-actual fun AnimationComponent.setTime(value: Double) {
+actual fun AnimationComponent.setTime(value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_animation_set_time(world, parentEntity.raw.toULong(), value)
 }
 
-actual fun AnimationComponent.getSpeed(): Double {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getSpeed(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val out = alloc<DoubleVar>()
+    dropbear_animation_get_speed(world, parentEntity.raw.toULong(), out.ptr)
+    out.value
 }
 
-actual fun AnimationComponent.setSpeed(value: Double) {
+actual fun AnimationComponent.setSpeed(value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_animation_set_speed(world, parentEntity.raw.toULong(), value)
 }
 
-actual fun AnimationComponent.getLooping(): Boolean {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getLooping(): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_animation_get_looping(world, parentEntity.raw.toULong(), out.ptr)
+    out.value
 }
 
-actual fun AnimationComponent.setLooping(value: Boolean) {
+actual fun AnimationComponent.setLooping(value: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_animation_set_looping(world, parentEntity.raw.toULong(), value)
 }
 
-actual fun AnimationComponent.getIsPlaying(): Boolean {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getIsPlaying(): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_animation_get_is_playing(world, parentEntity.raw.toULong(), out.ptr)
+    out.value
 }
 
-actual fun AnimationComponent.setIsPlaying(value: Boolean) {
+actual fun AnimationComponent.setIsPlaying(value: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_animation_set_is_playing(world, parentEntity.raw.toULong(), value)
 }
 
-actual fun AnimationComponent.getIndexFromString(name: String): Int? {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getIndexFromString(name: String): Int? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<IntVar>()
+    val present = alloc<BooleanVar>()
+    dropbear_animation_get_index_from_string(world, parentEntity.raw.toULong(), name, out.ptr, present.ptr)
+    if (!present.value) null else out.value
 }
 
-actual fun AnimationComponent.getAvailableAnimations(): List<String> {
-    TODO("Not yet implemented")
+actual fun AnimationComponent.getAvailableAnimations(): List<String> = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped emptyList()
+    val out = alloc<StringArray>()
+    val rc = dropbear_animation_get_available_animations(world, parentEntity.raw.toULong(), out.ptr)
+    if (rc != 0) return@memScoped emptyList()
+    val ptr = out.values ?: return@memScoped emptyList()
+    val len = out.length.toInt()
+    (0 until len).mapNotNull { i -> ptr[i]?.toKString() }
 }
 
-actual fun animationComponentExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+actual fun animationComponentExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_animation_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/asset/Model.native.kt b/scripting/nativeMain/kotlin/com/dropbear/asset/Model.native.kt
index 43092c5..ed69c06 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/asset/Model.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/asset/Model.native.kt
@@ -1,31 +1,26 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.asset
 
+import com.dropbear.DropbearEngine
 import com.dropbear.asset.model.Animation
 import com.dropbear.asset.model.Material
 import com.dropbear.asset.model.Mesh
 import com.dropbear.asset.model.Node
 import com.dropbear.asset.model.Skin
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-actual fun Model.getLabel(): String {
-    TODO("Not yet implemented")
-}
-
-actual fun Model.getMeshes(): List<Mesh> {
-    return emptyList()
-}
-
-actual fun Model.getMaterials(): List<Material> {
-    return emptyList()
+actual fun Model.getLabel(): String = memScoped {
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped ""
+    val out = alloc<CPointerVar<ByteVar>>()
+    val rc = dropbear_asset_model_get_label(assets, id.toULong(), out.ptr)
+    if (rc != 0) "" else out.value?.toKString() ?: ""
 }
 
-actual fun Model.getSkins(): List<Skin> {
-    return emptyList()
-}
-
-actual fun Model.getAnimations(): List<Animation> {
-    return emptyList()
-}
-
-actual fun Model.getNodes(): List<Node> {
-    return emptyList()
-}
+actual fun Model.getMeshes(): List<Mesh> = emptyList()      // complex C array parsing deferred
+actual fun Model.getMaterials(): List<Material> = emptyList()
+actual fun Model.getSkins(): List<Skin> = emptyList()
+actual fun Model.getAnimations(): List<Animation> = emptyList()
+actual fun Model.getNodes(): List<Node> = emptyList()
diff --git a/scripting/nativeMain/kotlin/com/dropbear/asset/Texture.native.kt b/scripting/nativeMain/kotlin/com/dropbear/asset/Texture.native.kt
index 3a9d161..9ea1a62 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/asset/Texture.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/asset/Texture.native.kt
@@ -1,13 +1,30 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.asset
 
-actual fun Texture.getLabel(): String? {
-    TODO("Not yet implemented")
-}
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-actual fun Texture.getWidth(): Int {
-    TODO("Not yet implemented")
+actual fun Texture.getLabel(): String? = memScoped {
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped null
+    val out = alloc<CPointerVar<ByteVar>>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_asset_texture_get_label(assets, id.toULong(), out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value?.toKString()
 }
 
-actual fun Texture.getHeight(): Int {
-    TODO("Not yet implemented")
+actual fun Texture.getWidth(): Int = memScoped {
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped 0
+    val out = alloc<UIntVar>()
+    dropbear_asset_texture_get_width(assets, id.toULong(), out.ptr)
+    out.value.toInt()
 }
+
+actual fun Texture.getHeight(): Int = memScoped {
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped 0
+    val out = alloc<UIntVar>()
+    dropbear_asset_texture_get_height(assets, id.toULong(), out.ptr)
+    out.value.toInt()
+}
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/components/Camera.native.kt b/scripting/nativeMain/kotlin/com/dropbear/components/Camera.native.kt
index d6f717d..9d46467 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/components/Camera.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/components/Camera.native.kt
@@ -1,82 +1,147 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.components
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun Camera.getCameraEye(entity: EntityId): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraEye(entity: EntityId): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_camera_get_eye(world, entity.raw.toULong(), out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Camera.setCameraEye(entity: EntityId, value: Vector3d) {
+internal actual fun Camera.setCameraEye(entity: EntityId, value: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val v = allocVec3(value)
+    dropbear_camera_set_eye(world, entity.raw.toULong(), v.ptr)
 }
 
-internal actual fun Camera.getCameraTarget(entity: EntityId): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraTarget(entity: EntityId): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_camera_get_target(world, entity.raw.toULong(), out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Camera.setCameraTarget(entity: EntityId, value: Vector3d) {
+internal actual fun Camera.setCameraTarget(entity: EntityId, value: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val v = allocVec3(value)
+    dropbear_camera_set_target(world, entity.raw.toULong(), v.ptr)
 }
 
-internal actual fun Camera.getCameraUp(entity: EntityId): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraUp(entity: EntityId): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_camera_get_up(world, entity.raw.toULong(), out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Camera.setCameraUp(entity: EntityId, value: Vector3d) {
+internal actual fun Camera.setCameraUp(entity: EntityId, value: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val v = allocVec3(value)
+    dropbear_camera_set_up(world, entity.raw.toULong(), v.ptr)
 }
 
-internal actual fun Camera.getCameraAspect(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraAspect(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_aspect(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.getCameraFovY(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraFovY(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 60.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_fovy(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraFovY(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraFovY(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_fovy(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.getCameraZNear(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraZNear(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.1
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_znear(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraZNear(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraZNear(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_znear(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.getCameraZFar(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraZFar(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1000.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_zfar(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraZFar(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraZFar(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_zfar(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.getCameraYaw(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraYaw(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_yaw(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.getCameraPitch(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraPitch(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_pitch(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraYaw(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraYaw(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_yaw(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.setCameraPitch(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraPitch(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_pitch(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.getCameraSpeed(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraSpeed(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_speed(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraSpeed(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraSpeed(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_speed(world, entity.raw.toULong(), value)
 }
 
-internal actual fun Camera.getCameraSensitivity(entity: EntityId): Double {
-    TODO("Not yet implemented")
+internal actual fun Camera.getCameraSensitivity(entity: EntityId): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val out = alloc<DoubleVar>()
+    dropbear_camera_get_sensitivity(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Camera.setCameraSensitivity(entity: EntityId, value: Double) {
+internal actual fun Camera.setCameraSensitivity(entity: EntityId, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_camera_set_sensitivity(world, entity.raw.toULong(), value)
 }
 
-internal actual fun cameraExistsForEntity(entity: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun cameraExistsForEntity(entity: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_camera_exists_for_entity(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/components/CustomProperties.native.kt b/scripting/nativeMain/kotlin/com/dropbear/components/CustomProperties.native.kt
index cb666e8..0b8294a 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/components/CustomProperties.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/components/CustomProperties.native.kt
@@ -1,96 +1,104 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.components
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-actual fun CustomProperties.getStringProperty(
-    entityHandle: Long,
-    label: String
-): String? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getStringProperty(entityHandle: Long, label: String): String? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<CPointerVar<ByteVar>>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_string_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value?.toKString()
 }
 
-actual fun CustomProperties.getIntProperty(entityHandle: Long, label: String): Int? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getIntProperty(entityHandle: Long, label: String): Int? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<IntVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_int_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value
 }
 
-actual fun CustomProperties.getLongProperty(
-    entityHandle: Long,
-    label: String
-): Long? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getLongProperty(entityHandle: Long, label: String): Long? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<LongVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_long_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value
 }
 
-actual fun CustomProperties.getDoubleProperty(
-    entityHandle: Long,
-    label: String
-): Double? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getDoubleProperty(entityHandle: Long, label: String): Double? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<DoubleVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_double_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value
 }
 
-actual fun CustomProperties.getFloatProperty(
-    entityHandle: Long,
-    label: String
-): Float? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getFloatProperty(entityHandle: Long, label: String): Float? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<FloatVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_float_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value
 }
 
-actual fun CustomProperties.getBoolProperty(
-    entityHandle: Long,
-    label: String
-): Boolean? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getBoolProperty(entityHandle: Long, label: String): Boolean? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<BooleanVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_bool_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value
 }
 
-actual fun CustomProperties.getVec3Property(
-    entityHandle: Long,
-    label: String
-): Vector3d? {
-    TODO("Not yet implemented")
+actual fun CustomProperties.getVec3Property(entityHandle: Long, label: String): Vector3d? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<NVector3>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_properties_get_vec3_property(world, entityHandle.toULong(), label, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else Vector3d(out.x, out.y, out.z)
 }
 
-actual fun CustomProperties.setStringProperty(
-    entityHandle: Long,
-    label: String,
-    value: String
-) {
+actual fun CustomProperties.setStringProperty(entityHandle: Long, label: String, value: String) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_properties_set_string_property(world, entityHandle.toULong(), label, value)
 }
 
-actual fun CustomProperties.setIntProperty(
-    entityHandle: Long,
-    label: String,
-    value: Int
-) {
+actual fun CustomProperties.setIntProperty(entityHandle: Long, label: String, value: Int) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_properties_set_int_property(world, entityHandle.toULong(), label, value)
 }
 
-actual fun CustomProperties.setLongProperty(
-    entityHandle: Long,
-    label: String,
-    value: Long
-) {
+actual fun CustomProperties.setLongProperty(entityHandle: Long, label: String, value: Long) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_properties_set_long_property(world, entityHandle.toULong(), label, value)
 }
 
-actual fun CustomProperties.setFloatProperty(
-    entityHandle: Long,
-    label: String,
-    value: Double
-) {
+actual fun CustomProperties.setFloatProperty(entityHandle: Long, label: String, value: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_properties_set_float_property(world, entityHandle.toULong(), label, value)
 }
 
-actual fun CustomProperties.setBoolProperty(
-    entityHandle: Long,
-    label: String,
-    value: Boolean
-) {
+actual fun CustomProperties.setBoolProperty(entityHandle: Long, label: String, value: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_properties_set_bool_property(world, entityHandle.toULong(), label, value)
 }
 
-actual fun CustomProperties.setVec3Property(
-    entityHandle: Long,
-    label: String,
-    value: Vector3d
-) {
+actual fun CustomProperties.setVec3Property(entityHandle: Long, label: String, value: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nv = allocVec3(value)
+    dropbear_properties_set_vec3_property(world, entityHandle.toULong(), label, nv.ptr)
 }
 
-internal actual fun customPropertiesExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun customPropertiesExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_properties_custom_properties_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/components/EntityTransform.native.kt b/scripting/nativeMain/kotlin/com/dropbear/components/EntityTransform.native.kt
index 138886c..10a3f45 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/components/EntityTransform.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/components/EntityTransform.native.kt
@@ -1,32 +1,50 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.components
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Transform
+import kotlinx.cinterop.*
 
-internal actual fun EntityTransform.getLocalTransform(entityId: EntityId): Transform {
-    TODO("Not yet implemented")
+internal actual fun entityTransformExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_transform_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun EntityTransform.setLocalTransform(
-    entityId: EntityId,
-    transform: Transform
-) {
+internal actual fun EntityTransform.getLocalTransform(entityId: EntityId): Transform = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Transform.identity()
+    val out = alloc<NTransform>()
+    dropbear_transform_get_local_transform(world, entityId.raw.toULong(), out.ptr)
+    readTransform(out)
 }
 
-internal actual fun EntityTransform.getWorldTransform(entityId: EntityId): Transform {
-    TODO("Not yet implemented")
+internal actual fun EntityTransform.setLocalTransform(entityId: EntityId, transform: Transform) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nt = allocTransform(transform)
+    dropbear_transform_set_local_transform(world, entityId.raw.toULong(), nt.ptr)
 }
 
-internal actual fun EntityTransform.setWorldTransform(
-    entityId: EntityId,
-    transform: Transform
-) {
+internal actual fun EntityTransform.getWorldTransform(entityId: EntityId): Transform = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Transform.identity()
+    val out = alloc<NTransform>()
+    dropbear_transform_get_world_transform(world, entityId.raw.toULong(), out.ptr)
+    readTransform(out)
 }
 
-internal actual fun EntityTransform.propagateTransform(entityId: EntityId): Transform? {
-    TODO("Not yet implemented")
+internal actual fun EntityTransform.setWorldTransform(entityId: EntityId, transform: Transform) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nt = allocTransform(transform)
+    dropbear_transform_set_world_transform(world, entityId.raw.toULong(), nt.ptr)
 }
 
-internal actual fun entityTransformExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun EntityTransform.propagateTransform(entityId: EntityId): Transform? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<NTransform>()
+    val rc = dropbear_transform_propogate_transform(world, entityId.raw.toULong(), out.ptr)
+    if (rc != 0) null else readTransform(out)
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/components/Label.native.kt b/scripting/nativeMain/kotlin/com/dropbear/components/Label.native.kt
index 862e71b..cf5249c 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/components/Label.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/components/Label.native.kt
@@ -1,7 +1,16 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.components
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-internal actual fun labelExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not implemented yet")
+internal actual fun labelExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_entity_label_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/components/MeshRenderer.native.kt b/scripting/nativeMain/kotlin/com/dropbear/components/MeshRenderer.native.kt
index ebce5ff..17b0b8c 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/components/MeshRenderer.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/components/MeshRenderer.native.kt
@@ -1,31 +1,36 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.components
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
 import com.dropbear.asset.ModelHandle
 import com.dropbear.asset.TextureHandle
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-internal actual fun MeshRenderer.getModel(id: EntityId): ModelHandle? {
-    TODO("Not yet implemented")
-}
+internal actual fun MeshRenderer.getModel(id: EntityId): ModelHandle? = null // no C API for mesh renderer model getter
 
 internal actual fun MeshRenderer.setModel(id: EntityId, model: ModelHandle?) {
+    // no C API for mesh renderer model setter
 }
 
-internal actual fun MeshRenderer.getAllTextureIds(id: EntityId): List<TextureHandle>? {
-    TODO("Not yet implemented")
-}
+internal actual fun MeshRenderer.getAllTextureIds(id: EntityId): List<TextureHandle>? = null // no C API for bulk texture listing
 
-internal actual fun MeshRenderer.getTexture(id: EntityId, materialName: String): Long? {
-    TODO("Not yet implemented")
+internal actual fun MeshRenderer.getTexture(id: EntityId, materialName: String): Long? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_mesh_get_texture(world, assets, id.raw.toULong(), materialName, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else out.value.toLong()
 }
 
-internal actual fun MeshRenderer.setTextureOverride(
-    id: EntityId,
-    materialName: String,
-    textureHandle: Long
-) {
+internal actual fun MeshRenderer.setTextureOverride(id: EntityId, materialName: String, textureHandle: Long) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val assets = DropbearEngine.native.assetHandle ?: return@memScoped
+    dropbear_mesh_set_texture_override(world, assets, id.raw.toULong(), materialName, textureHandle.toULong())
 }
 
-internal actual fun meshRendererExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
-}
\ No newline at end of file
+internal actual fun meshRendererExistsForEntity(entityId: EntityId): Boolean = false // no dedicated exists check in C API
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt b/scripting/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
index 2663baa..9df16ba 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
@@ -13,13 +13,14 @@ import kotlinx.cinterop.interpretCPointer
 import kotlin.experimental.ExperimentalNativeApi
 
 actual class NativeEngine {
-    private var worldHandle: COpaquePointer? = null
-    private var inputHandle: COpaquePointer? = null
-    private var commandBufferHandle: COpaquePointer? = null
-    private var assetHandle: COpaquePointer? = null
-    private var sceneLoaderHandle: COpaquePointer? = null
-    private var physicsEngineHandle: COpaquePointer? = null
-    private var uiBufferHandle: COpaquePointer? = null
+    internal var worldHandle: COpaquePointer? = null
+    internal var inputHandle: COpaquePointer? = null
+    internal var commandBufferHandle: COpaquePointer? = null
+    internal var graphicsContextHandle: COpaquePointer? = null
+    internal var assetHandle: COpaquePointer? = null
+    internal var sceneLoaderHandle: COpaquePointer? = null
+    internal var physicsEngineHandle: COpaquePointer? = null
+    internal var uiBufferHandle: COpaquePointer? = null
 
     @Suppress("unused")
     fun init(
@@ -27,11 +28,12 @@ actual class NativeEngine {
     ) {
         this.worldHandle = ctx?.world?.rawValue?.let { interpretCPointer(it) }
         this.inputHandle = ctx?.input?.rawValue?.let { interpretCPointer(it) }
-        this.commandBufferHandle = ctx?.graphics?.rawValue?.let { interpretCPointer(it) }
+        this.commandBufferHandle = ctx?.commandBuffer?.rawValue?.let { interpretCPointer(it) }
+        this.graphicsContextHandle = ctx?.graphicsContext?.rawValue?.let { interpretCPointer(it) }
         this.assetHandle = ctx?.assets?.rawValue?.let { interpretCPointer(it) }
-        this.sceneLoaderHandle = ctx?.scene_loader?.rawValue?.let { interpretCPointer(it) }
-        this.physicsEngineHandle = ctx?.physics_engine?.rawValue?.let { interpretCPointer(it) }
-        this.uiBufferHandle = ctx?.graphics?.rawValue?.let { interpretCPointer(it) }
+        this.sceneLoaderHandle = ctx?.sceneLoader?.rawValue?.let { interpretCPointer(it) }
+        this.physicsEngineHandle = ctx?.physicsEngine?.rawValue?.let { interpretCPointer(it) }
+        this.uiBufferHandle = ctx?.uiBuffer?.rawValue?.let { interpretCPointer(it) }
 
         Logger.init(com.dropbear.logging.SocketWriter())
 
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/DropbearContext.kt b/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/DropbearContext.kt
index 3904dab..0b06622 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/DropbearContext.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/DropbearContext.kt
@@ -2,7 +2,6 @@
 
 package com.dropbear.ffi.generated
 
-import kotlinx.cinterop.ExperimentalForeignApi
 import kotlinx.cinterop.NativePtr
 
 data class NativeHandle(
@@ -12,10 +11,10 @@ data class NativeHandle(
 data class DropbearContext(
     val world: NativeHandle?,
     val input: NativeHandle?,
-    val graphics: NativeHandle?,
-    val graphics_context: NativeHandle?,
+    val commandBuffer: NativeHandle?,
+    val graphicsContext: NativeHandle?,
     val assets: NativeHandle?,
-    val scene_loader: NativeHandle?,
-    val physics_engine: NativeHandle?,
-    val ui_buf: NativeHandle?
+    val sceneLoader: NativeHandle?,
+    val physicsEngine: NativeHandle?,
+    val uiBuffer: NativeHandle?
 )
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/FfiConverters.kt b/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/FfiConverters.kt
new file mode 100644
index 0000000..952a520
--- /dev/null
+++ b/scripting/nativeMain/kotlin/com/dropbear/ffi/generated/FfiConverters.kt
@@ -0,0 +1,138 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
+package com.dropbear.ffi.generated
+
+import com.dropbear.EntityId
+import com.dropbear.math.Quaterniond
+import com.dropbear.math.Transform
+import com.dropbear.math.Vector3d
+import com.dropbear.physics.Collider
+import com.dropbear.physics.ColliderShape
+import com.dropbear.physics.Index
+import com.dropbear.physics.RigidBody
+import com.dropbear.physics.ShapeCastStatus
+import com.dropbear.utils.Colour
+import kotlinx.cinterop.*
+
+internal fun readTransform(nt: NTransform): Transform = Transform(
+    Vector3d(nt.position.x, nt.position.y, nt.position.z),
+    Quaterniond(nt.rotation.x, nt.rotation.y, nt.rotation.z, nt.rotation.w),
+    Vector3d(nt.scale.x, nt.scale.y, nt.scale.z),
+)
+
+internal fun MemScope.allocTransform(t: Transform): NTransform {
+    val nt = alloc<NTransform>()
+    nt.position.x = t.position.x
+    nt.position.y = t.position.y
+    nt.position.z = t.position.z
+    nt.rotation.x = t.rotation.x
+    nt.rotation.y = t.rotation.y
+    nt.rotation.z = t.rotation.z
+    nt.rotation.w = t.rotation.w
+    nt.scale.x = t.scale.x
+    nt.scale.y = t.scale.y
+    nt.scale.z = t.scale.z
+    return nt
+}
+
+internal fun MemScope.allocVec3(v: Vector3d): NVector3 {
+    val nv = alloc<NVector3>()
+    nv.x = v.x; nv.y = v.y; nv.z = v.z
+    return nv
+}
+
+internal fun MemScope.allocQuat(q: Quaterniond): NQuaternion {
+    val nq = alloc<NQuaternion>()
+    nq.x = q.x; nq.y = q.y; nq.z = q.z; nq.w = q.w
+    return nq
+}
+
+internal fun readCollider(nc: NCollider): Collider = Collider(
+    Index(nc.index.index, nc.index.generation),
+    EntityId(nc.entity_id.toLong()),
+    nc.id,
+)
+
+internal fun MemScope.allocCollider(c: Collider): NCollider {
+    val nc = alloc<NCollider>()
+    nc.index.index = c.index.index
+    nc.index.generation = c.index.generation
+    nc.entity_id = c.entity.raw.toULong()
+    nc.id = c.id
+    return nc
+}
+
+internal fun MemScope.allocRigidBodyCtx(rb: RigidBody): RigidBodyContext {
+    val ctx = alloc<RigidBodyContext>()
+    ctx.index.index = rb.index.index
+    ctx.index.generation = rb.index.generation
+    ctx.entity_id = rb.entity.raw.toULong()
+    return ctx
+}
+
+internal fun MemScope.allocIndexNative(idx: Index): IndexNative {
+    val ni = alloc<IndexNative>()
+    ni.index = idx.index
+    ni.generation = idx.generation
+    return ni
+}
+
+internal fun readColour(nc: NColour): Colour = Colour(nc.r, nc.g, nc.b, nc.a)
+
+internal fun MemScope.allocColour(c: Colour): NColour {
+    val nc = alloc<NColour>()
+    nc.r = c.r; nc.g = c.g; nc.b = c.b; nc.a = c.a
+    return nc
+}
+
+
+internal fun readShapeCastStatus(s: NShapeCastStatus): ShapeCastStatus = when (s.tag) {
+    NShapeCastStatusTag_OutOfIterations -> ShapeCastStatus.OutOfIterations
+    NShapeCastStatusTag_Converged -> ShapeCastStatus.Converged
+    NShapeCastStatusTag_Failed -> ShapeCastStatus.Failed
+    NShapeCastStatusTag_PenetratingOrWithinTargetDist -> ShapeCastStatus.PenetratingOrWithinTargetDist
+    else -> ShapeCastStatus.Failed
+}
+
+internal fun readColliderShape(ffi: ColliderShapeFfi): ColliderShape = when (ffi.tag) {
+    ColliderShapeTag_Box -> ColliderShape.Box(
+        Vector3d(ffi.data.Box.half_extents.x, ffi.data.Box.half_extents.y, ffi.data.Box.half_extents.z)
+    )
+    ColliderShapeTag_Sphere -> ColliderShape.Sphere(ffi.data.Sphere.radius)
+    ColliderShapeTag_Capsule -> ColliderShape.Capsule(ffi.data.Capsule.half_height, ffi.data.Capsule.radius)
+    ColliderShapeTag_Cylinder -> ColliderShape.Cylinder(ffi.data.Cylinder.half_height, ffi.data.Cylinder.radius)
+    ColliderShapeTag_Cone -> ColliderShape.Cone(ffi.data.Cone.half_height, ffi.data.Cone.radius)
+    else -> ColliderShape.Box(Vector3d.zero())
+}
+
+internal fun MemScope.allocColliderShape(shape: ColliderShape): ColliderShapeFfi {
+    val ffi = alloc<ColliderShapeFfi>()
+    when (shape) {
+        is ColliderShape.Box -> {
+            ffi.tag = ColliderShapeTag_Box
+            ffi.data.Box.half_extents.x = shape.halfExtents.x
+            ffi.data.Box.half_extents.y = shape.halfExtents.y
+            ffi.data.Box.half_extents.z = shape.halfExtents.z
+        }
+        is ColliderShape.Sphere -> {
+            ffi.tag = ColliderShapeTag_Sphere
+            ffi.data.Sphere.radius = shape.radius
+        }
+        is ColliderShape.Capsule -> {
+            ffi.tag = ColliderShapeTag_Capsule
+            ffi.data.Capsule.half_height = shape.halfHeight
+            ffi.data.Capsule.radius = shape.radius
+        }
+        is ColliderShape.Cylinder -> {
+            ffi.tag = ColliderShapeTag_Cylinder
+            ffi.data.Cylinder.half_height = shape.halfHeight
+            ffi.data.Cylinder.radius = shape.radius
+        }
+        is ColliderShape.Cone -> {
+            ffi.tag = ColliderShapeTag_Cone
+            ffi.data.Cone.half_height = shape.halfHeight
+            ffi.data.Cone.radius = shape.radius
+        }
+    }
+    return ffi
+}
diff --git a/scripting/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt b/scripting/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt
index 6e21850..37fb8c9 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/input/Gamepad.native.kt
@@ -1,18 +1,30 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.input
 
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Vector2d
+import kotlinx.cinterop.*
 
-internal actual fun Gamepad.isGamepadButtonPressed(
-    button: GamepadButton
-): Boolean {
-    TODO("Not yet implemented")
+internal actual fun Gamepad.isGamepadButtonPressed(button: GamepadButton): Boolean = memScoped {
+    val input = DropbearEngine.native.inputHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_gamepad_is_button_pressed(input, id.toULong(), button.ordinal, out.ptr)
+    out.value
 }
 
-internal actual fun Gamepad.getLeftStickPosition(): Vector2d {
-    TODO("Not yet implemented")
+internal actual fun Gamepad.getLeftStickPosition(): Vector2d = memScoped {
+    val input = DropbearEngine.native.inputHandle ?: return@memScoped Vector2d(0.0, 0.0)
+    val out = alloc<NVector2>()
+    dropbear_gamepad_get_left_stick_position(input, id.toULong(), out.ptr)
+    Vector2d(out.x, out.y)
 }
 
-internal actual fun Gamepad.getRightStickPosition(): Vector2d {
-    TODO("Not yet implemented")
+internal actual fun Gamepad.getRightStickPosition(): Vector2d = memScoped {
+    val input = DropbearEngine.native.inputHandle ?: return@memScoped Vector2d(0.0, 0.0)
+    val out = alloc<NVector2>()
+    dropbear_gamepad_get_right_stick_position(input, id.toULong(), out.ptr)
+    Vector2d(out.x, out.y)
 }
-
diff --git a/scripting/nativeMain/kotlin/com/dropbear/input/InputState.native.kt b/scripting/nativeMain/kotlin/com/dropbear/input/InputState.native.kt
index 2844b4d..54f2ee2 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/input/InputState.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/input/InputState.native.kt
@@ -1,46 +1,87 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.input
 
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Vector2d
+import kotlinx.cinterop.*
 
 actual class InputState actual constructor() {
     actual fun printInputState() {
+        val input = DropbearEngine.native.inputHandle ?: return
+        memScoped { dropbear_input_print_input_state(input) }
     }
 
-    actual fun isKeyPressed(key: KeyCode): Boolean {
-        TODO("Not yet implemented")
+    actual fun isKeyPressed(key: KeyCode): Boolean = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped false
+        val out = alloc<BooleanVar>()
+        dropbear_input_is_key_pressed(input, key.ordinal, out.ptr)
+        out.value
     }
 
-    actual fun getMousePosition(): Vector2d {
-        TODO("Not yet implemented")
+    actual fun getMousePosition(): Vector2d = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped Vector2d(0.0, 0.0)
+        val out = alloc<NVector2>()
+        dropbear_input_get_mouse_position(input, out.ptr)
+        Vector2d(out.x, out.y)
     }
 
-    actual fun isMouseButtonPressed(button: MouseButton): Boolean {
-        TODO("Not yet implemented")
+    actual fun isMouseButtonPressed(button: MouseButton): Boolean = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped false
+        val out = alloc<BooleanVar>()
+        dropbear_input_is_mouse_button_pressed(input, button.ordinal, out.ptr)
+        out.value
     }
 
-    actual fun getMouseDelta(): Vector2d {
-        TODO("Not yet implemented")
+    actual fun getMouseDelta(): Vector2d = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped Vector2d(0.0, 0.0)
+        val out = alloc<NVector2>()
+        dropbear_input_get_mouse_delta(input, out.ptr)
+        Vector2d(out.x, out.y)
     }
 
-    actual fun isCursorLocked(): Boolean {
-        TODO("Not yet implemented")
+    actual fun isCursorLocked(): Boolean = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped false
+        val out = alloc<BooleanVar>()
+        dropbear_input_is_cursor_locked(input, out.ptr)
+        out.value
     }
 
     actual fun setCursorLocked(locked: Boolean) {
+        val cmd = DropbearEngine.native.commandBufferHandle ?: return
+        val input = DropbearEngine.native.inputHandle ?: return
+        memScoped { dropbear_input_set_cursor_locked(cmd, input, locked) }
     }
 
-    actual fun getLastMousePos(): Vector2d {
-        TODO("Not yet implemented")
+    actual fun getLastMousePos(): Vector2d = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped Vector2d(0.0, 0.0)
+        val out = alloc<NVector2>()
+        dropbear_input_get_last_mouse_pos(input, out.ptr)
+        Vector2d(out.x, out.y)
     }
 
-    actual fun isCursorHidden(): Boolean {
-        TODO("Not yet implemented")
+    actual fun isCursorHidden(): Boolean = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped false
+        val out = alloc<BooleanVar>()
+        dropbear_input_is_cursor_hidden(input, out.ptr)
+        out.value
     }
 
     actual fun setCursorHidden(hidden: Boolean) {
+        val cmd = DropbearEngine.native.commandBufferHandle ?: return
+        val input = DropbearEngine.native.inputHandle ?: return
+        memScoped { dropbear_input_set_cursor_hidden(cmd, input, hidden) }
     }
 
-    actual fun getConnectedGamepads(): List<Gamepad> {
-        TODO("Not yet implemented")
+    actual fun getConnectedGamepads(): List<Gamepad> = memScoped {
+        val input = DropbearEngine.native.inputHandle ?: return@memScoped emptyList()
+        val out = alloc<ConnectedGamepadIds>()
+        val rc = dropbear_input_get_connected_gamepads(input, out.ptr)
+        if (rc != 0) return@memScoped emptyList()
+        val ptr = out.ids.values ?: return@memScoped emptyList()
+        val len = out.ids.length.toInt()
+        (0 until len).map { i -> Gamepad(ptr[i].toLong()) }
     }
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/lighting/Light.native.kt b/scripting/nativeMain/kotlin/com/dropbear/lighting/Light.native.kt
index 1d63e16..37ee108 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/lighting/Light.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/lighting/Light.native.kt
@@ -1,87 +1,159 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.lighting
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.math.Vector3d
 import com.dropbear.utils.Colour
 import com.dropbear.utils.Range
+import kotlinx.cinterop.*
 
-internal actual fun lightExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun lightExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_lighting_light_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.getPosition(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Light.getPosition(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_lighting_get_position(world, entity.raw.toULong(), out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Light.setPosition(position: Vector3d) {
+internal actual fun Light.setPosition(position: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nv = allocVec3(position)
+    dropbear_lighting_set_position(world, entity.raw.toULong(), nv.ptr)
 }
 
-internal actual fun Light.getDirection(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Light.getDirection(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_lighting_get_direction(world, entity.raw.toULong(), out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Light.setDirection(direction: Vector3d) {
+internal actual fun Light.setDirection(direction: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nv = allocVec3(direction)
+    dropbear_lighting_set_direction(world, entity.raw.toULong(), nv.ptr)
 }
 
-internal actual fun Light.getColour(): Colour {
-    TODO("Not yet implemented")
+internal actual fun Light.getColour(): Colour = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Colour(255u, 255u, 255u, 255u)
+    val out = alloc<NColour>()
+    dropbear_lighting_get_colour(world, entity.raw.toULong(), out.ptr)
+    readColour(out)
 }
 
-internal actual fun Light.setColour(colour: Colour) {
+internal actual fun Light.setColour(colour: Colour) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nc = allocColour(colour)
+    dropbear_lighting_set_colour(world, entity.raw.toULong(), nc.ptr)
 }
 
-internal actual fun Light.getLightType(): LightType {
-    TODO("Not yet implemented")
+internal actual fun Light.getLightType(): LightType = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped LightType.Directional
+    val out = alloc<IntVar>()
+    dropbear_lighting_get_light_type(world, entity.raw.toULong(), out.ptr)
+    LightType.entries[out.value.coerceIn(0, LightType.entries.lastIndex)]
 }
 
-internal actual fun Light.setLightType(lightType: LightType) {
+internal actual fun Light.setLightType(lightType: LightType) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_light_type(world, entity.raw.toULong(), lightType.ordinal)
 }
 
-internal actual fun Light.getIntensity(): Double {
-    TODO("Not yet implemented")
+internal actual fun Light.getIntensity(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val out = alloc<DoubleVar>()
+    dropbear_lighting_get_intensity(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.setIntensity(intensity: Double) {
+internal actual fun Light.setIntensity(intensity: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_intensity(world, entity.raw.toULong(), intensity)
 }
 
-internal actual fun Light.getAttenuation(): Attenuation {
-    TODO("Not yet implemented")
+internal actual fun Light.getAttenuation(): Attenuation = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Attenuation()
+    val out = alloc<NAttenuation>()
+    dropbear_lighting_get_attenuation(world, entity.raw.toULong(), out.ptr)
+    Attenuation(out.constant, out.linear, out.quadratic)
 }
 
-internal actual fun Light.setAttenuation(attenuation: Attenuation) {
+internal actual fun Light.setAttenuation(attenuation: Attenuation) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val na = alloc<NAttenuation>()
+    na.constant = attenuation.constant
+    na.linear = attenuation.linear
+    na.quadratic = attenuation.quadratic
+    dropbear_lighting_set_attenuation(world, entity.raw.toULong(), na.ptr)
 }
 
-internal actual fun Light.getEnabled(): Boolean {
-    TODO("Not yet implemented")
+internal actual fun Light.getEnabled(): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_lighting_get_enabled(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.setEnabled(enabled: Boolean) {
+internal actual fun Light.setEnabled(enabled: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_enabled(world, entity.raw.toULong(), enabled)
 }
 
-internal actual fun Light.getCutoffAngle(): Double {
-    TODO("Not yet implemented")
+internal actual fun Light.getCutoffAngle(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_lighting_get_cutoff_angle(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.setCutoffAngle(cutoffAngle: Double) {
+internal actual fun Light.setCutoffAngle(cutoffAngle: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_cutoff_angle(world, entity.raw.toULong(), cutoffAngle)
 }
 
-internal actual fun Light.getOuterCutoffAngle(): Double {
-    TODO("Not yet implemented")
+internal actual fun Light.getOuterCutoffAngle(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_lighting_get_outer_cutoff_angle(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.setOuterCutoffAngle(outerCutoffAngle: Double) {
+internal actual fun Light.setOuterCutoffAngle(outerCutoffAngle: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_outer_cutoff_angle(world, entity.raw.toULong(), outerCutoffAngle)
 }
 
-internal actual fun Light.getCastShadows(): Boolean {
-    TODO("Not yet implemented")
+internal actual fun Light.getCastShadows(): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_lighting_get_casts_shadows(world, entity.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun Light.setCastShadows(castShadows: Boolean) {
+internal actual fun Light.setCastShadows(castShadows: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    dropbear_lighting_set_casts_shadows(world, entity.raw.toULong(), castShadows)
 }
 
-internal actual fun Light.getDepth(): Range {
-    TODO("Not yet implemented")
+internal actual fun Light.getDepth(): Range = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Range(0.0, 100.0)
+    val out = alloc<NRange>()
+    dropbear_lighting_get_depth(world, entity.raw.toULong(), out.ptr)
+    Range(out.start.toDouble(), out.end.toDouble())
 }
 
-internal actual fun Light.setDepth(depth: Range) {
+internal actual fun Light.setDepth(depth: Range) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val nr = alloc<NRange>().also { it.start = depth.start.toFloat(); it.end = depth.end.toFloat() }
+    dropbear_lighting_set_depth(world, entity.raw.toULong(), nr.ptr)
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/CharacterCollision.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/CharacterCollision.native.kt
index c08baca..dee9baf 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/CharacterCollision.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/CharacterCollision.native.kt
@@ -1,44 +1,106 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.NCollider
+import com.dropbear.ffi.generated.NShapeCastStatus
+import com.dropbear.ffi.generated.NTransform
+import com.dropbear.ffi.generated.NVector3
+import com.dropbear.ffi.generated.allocIndexNative
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_collider
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_normal1
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_normal2
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_position
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_status
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_time_of_impact
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_translation_applied
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_translation_remaining
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_witness1
+import com.dropbear.ffi.generated.dropbear_character_collision_get_character_collision_witness2
+import com.dropbear.ffi.generated.readCollider
+import com.dropbear.ffi.generated.readShapeCastStatus
+import com.dropbear.ffi.generated.readTransform
 import com.dropbear.math.Transform
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun CharacterCollision.getCollider(): Collider {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getCollider(): Collider = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Collider(Index(0u, 0u), entity, 0u)
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NCollider>()
+    dropbear_character_collision_get_character_collision_collider(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    readCollider(out)
 }
 
-internal actual fun CharacterCollision.getCharacterPosition(): Transform {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getCharacterPosition(): Transform = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Transform.identity()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NTransform>()
+    dropbear_character_collision_get_character_collision_position(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    readTransform(out)
 }
 
-internal actual fun CharacterCollision.getTranslationApplied(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getTranslationApplied(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_translation_applied(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getTranslationRemaining(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getTranslationRemaining(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_translation_remaining(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getTimeOfImpact(): Double {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getTimeOfImpact(): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<DoubleVar>()
+    dropbear_character_collision_get_character_collision_time_of_impact(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun CharacterCollision.getWitness1(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getWitness1(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_witness1(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getWitness2(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getWitness2(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_witness2(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getNormal1(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getNormal1(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_normal1(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getNormal2(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getNormal2(): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NVector3>()
+    dropbear_character_collision_get_character_collision_normal2(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun CharacterCollision.getStatus(): ShapeCastStatus {
-    TODO("Not yet implemented")
+internal actual fun CharacterCollision.getStatus(): ShapeCastStatus = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped ShapeCastStatus.Failed
+    val ni = allocIndexNative(collisionHandle)
+    val out = alloc<NShapeCastStatus>()
+    dropbear_character_collision_get_character_collision_status(world, entity.raw.toULong(), ni.ptr, out.ptr)
+    readShapeCastStatus(out)
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt
index 808c712..70f0849 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/Collider.native.kt
@@ -1,81 +1,144 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.ColliderShapeFfi
+import com.dropbear.ffi.generated.NVector3
+import com.dropbear.ffi.generated.allocCollider
+import com.dropbear.ffi.generated.allocColliderShape
+import com.dropbear.ffi.generated.allocVec3
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_density
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_friction
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_is_sensor
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_mass
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_restitution
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_rotation
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_shape
+import com.dropbear.ffi.generated.dropbear_collider_get_collider_translation
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_density
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_friction
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_is_sensor
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_mass
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_restitution
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_rotation
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_shape
+import com.dropbear.ffi.generated.dropbear_collider_set_collider_translation
+import com.dropbear.ffi.generated.readColliderShape
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun Collider.getColliderShape(collider: Collider): ColliderShape {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderShape(collider: Collider): ColliderShape = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped ColliderShape.Box(Vector3d.zero())
+    val nc = allocCollider(collider)
+    val out = alloc<ColliderShapeFfi>()
+    dropbear_collider_get_collider_shape(physics, nc.ptr, out.ptr)
+    readColliderShape(out)
 }
 
-internal actual fun Collider.setColliderShape(
-    collider: Collider,
-    shape: ColliderShape
-) {
+internal actual fun Collider.setColliderShape(collider: Collider, shape: ColliderShape) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    val ns = allocColliderShape(shape)
+    dropbear_collider_set_collider_shape(physics, nc.ptr, ns.ptr)
 }
 
-internal actual fun Collider.setColliderDensity(
-    collider: Collider,
-    density: Double
-) {
+internal actual fun Collider.setColliderDensity(collider: Collider, density: Double) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    dropbear_collider_set_collider_density(physics, nc.ptr, density)
 }
 
-internal actual fun Collider.getColliderFriction(collider: Collider): Double {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderFriction(collider: Collider): Double = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val nc = allocCollider(collider)
+    val out = alloc<DoubleVar>()
+    dropbear_collider_get_collider_friction(physics, nc.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun Collider.setColliderFriction(
-    collider: Collider,
-    friction: Double
-) {
+internal actual fun Collider.setColliderFriction(collider: Collider, friction: Double) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    dropbear_collider_set_collider_friction(physics, nc.ptr, friction)
 }
 
-internal actual fun Collider.getColliderRestitution(collider: Collider): Double {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderRestitution(collider: Collider): Double = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val nc = allocCollider(collider)
+    val out = alloc<DoubleVar>()
+    dropbear_collider_get_collider_restitution(physics, nc.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun Collider.setColliderRestitution(
-    collider: Collider,
-    restitution: Double
-) {
+internal actual fun Collider.setColliderRestitution(collider: Collider, restitution: Double) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    dropbear_collider_set_collider_restitution(physics, nc.ptr, restitution)
 }
 
-internal actual fun Collider.getColliderIsSensor(collider: Collider): Boolean {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderIsSensor(collider: Collider): Boolean = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val nc = allocCollider(collider)
+    val out = alloc<BooleanVar>()
+    dropbear_collider_get_collider_is_sensor(physics, nc.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun Collider.setColliderIsSensor(
-    collider: Collider,
-    isSensor: Boolean
-) {
+internal actual fun Collider.setColliderIsSensor(collider: Collider, isSensor: Boolean) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    dropbear_collider_set_collider_is_sensor(physics, nc.ptr, isSensor)
 }
 
-internal actual fun Collider.getColliderTranslation(collider: Collider): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderTranslation(collider: Collider): Vector3d = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped Vector3d.zero()
+    val nc = allocCollider(collider)
+    val out = alloc<NVector3>()
+    dropbear_collider_get_collider_translation(physics, nc.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Collider.setColliderTranslation(
-    collider: Collider,
-    translation: Vector3d
-) {
+internal actual fun Collider.setColliderTranslation(collider: Collider, translation: Vector3d) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    val nv = allocVec3(translation)
+    dropbear_collider_set_collider_translation(physics, nc.ptr, nv.ptr)
 }
 
-internal actual fun Collider.getColliderRotation(collider: Collider): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderRotation(collider: Collider): Vector3d = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped Vector3d.zero()
+    val nc = allocCollider(collider)
+    val out = alloc<NVector3>()
+    dropbear_collider_get_collider_rotation(physics, nc.ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun Collider.setColliderRotation(
-    collider: Collider,
-    rotation: Vector3d
-) {
+internal actual fun Collider.setColliderRotation(collider: Collider, rotation: Vector3d) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    val nv = allocVec3(rotation)
+    dropbear_collider_set_collider_rotation(physics, nc.ptr, nv.ptr)
 }
 
-internal actual fun Collider.getColliderMass(collider: Collider): Double {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderMass(collider: Collider): Double = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val nc = allocCollider(collider)
+    val out = alloc<DoubleVar>()
+    dropbear_collider_get_collider_mass(physics, nc.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun Collider.setColliderMass(collider: Collider, mass: Double) {
+internal actual fun Collider.setColliderMass(collider: Collider, mass: Double) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nc = allocCollider(collider)
+    dropbear_collider_set_collider_mass(physics, nc.ptr, mass)
 }
 
-internal actual fun Collider.getColliderDensity(collider: Collider): Double {
-    TODO("Not yet implemented")
+internal actual fun Collider.getColliderDensity(collider: Collider): Double = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val nc = allocCollider(collider)
+    val out = alloc<DoubleVar>()
+    dropbear_collider_get_collider_density(physics, nc.ptr, out.ptr)
+    out.value
 }
-
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt
index 7b47284..2c4084c 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/ColliderGroup.native.kt
@@ -1,11 +1,27 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
 
-internal actual fun ColliderGroup.getColliderGroupColliders(colliderGroup: ColliderGroup): List<Collider> {
-    TODO("Not yet implemented")
+internal actual fun ColliderGroup.getColliderGroupColliders(colliderGroup: ColliderGroup): List<Collider> = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped emptyList()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped emptyList()
+    val out = alloc<NColliderArray>()
+    val rc = dropbear_collider_group_get_colliders(world, physics, colliderGroup.entity.raw.toULong(), out.ptr)
+    if (rc != 0) return@memScoped emptyList()
+    val ptr = out.values ?: return@memScoped emptyList()
+    val len = out.length.toInt()
+    (0 until len).map { i -> readCollider(ptr[i]) }
 }
 
-internal actual fun colliderGroupExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun colliderGroupExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_collider_group_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/KinematicCharacterController.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/KinematicCharacterController.native.kt
index 8578d5c..7f7594e 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/KinematicCharacterController.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/KinematicCharacterController.native.kt
@@ -1,24 +1,66 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.CharacterCollisionArray
+import com.dropbear.ffi.generated.CharacterMovementResult as FfiCharacterMovementResult
+import com.dropbear.ffi.generated.NQuaternion
+import com.dropbear.ffi.generated.NVector3
+import com.dropbear.ffi.generated.allocIndexNative
+import com.dropbear.ffi.generated.dropbear_kcc_get_hit
+import com.dropbear.ffi.generated.dropbear_kcc_get_movement_result
+import com.dropbear.ffi.generated.dropbear_kcc_kcc_exists_for_entity
+import com.dropbear.ffi.generated.dropbear_kcc_move_character
+import com.dropbear.ffi.generated.dropbear_kcc_set_rotation
 import com.dropbear.math.Quaterniond
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun KinematicCharacterController.moveCharacter(dt: Double, translation: Vector3d) {
+internal actual fun KinematicCharacterController.moveCharacter(dt: Double, translation: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nv = alloc<NVector3>().also { it.x = translation.x; it.y = translation.y; it.z = translation.z }
+    dropbear_kcc_move_character(world, physics, entity.raw.toULong(), nv.ptr, dt)
 }
 
-internal actual fun KinematicCharacterController.setRotationNative(rotation: Quaterniond) {
-    TODO("Not yet implemented")
+internal actual fun KinematicCharacterController.setRotationNative(rotation: Quaterniond) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nq = alloc<NQuaternion>().also { it.x = rotation.x; it.y = rotation.y; it.z = rotation.z; it.w = rotation.w }
+    dropbear_kcc_set_rotation(world, physics, entity.raw.toULong(), nq.ptr)
 }
 
-internal actual fun kccExistsForEntity(entityId: EntityId): Boolean {
-    TODO("Not yet implemented")
+internal actual fun kccExistsForEntity(entityId: EntityId): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_kcc_kcc_exists_for_entity(world, entityId.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun KinematicCharacterController.getHitsNative(): List<CharacterCollision> {
-    TODO("Not yet implemented")
+internal actual fun KinematicCharacterController.getHitsNative(): List<CharacterCollision> = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped emptyList()
+    val out = alloc<CharacterCollisionArray>()
+    val rc = dropbear_kcc_get_hit(world, entity.raw.toULong(), out.ptr)
+    if (rc != 0) return@memScoped emptyList()
+    val collisionEntityId = EntityId(out.entity_id.toLong())
+    val ptr = out.collisions.values ?: return@memScoped emptyList()
+    val len = out.collisions.length.toInt()
+    (0 until len).map { i ->
+        val idx = ptr[i]
+        CharacterCollision(collisionEntityId, Index(idx.index, idx.generation))
+    }
 }
 
-internal actual fun KinematicCharacterController.getMovementResult(): CharacterMovementResult? {
-    TODO("Not yet implemented")
+internal actual fun KinematicCharacterController.getMovementResult(): CharacterMovementResult? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val out = alloc<FfiCharacterMovementResult>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_kcc_get_movement_result(world, entity.raw.toULong(), out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else CharacterMovementResult(
+        Vector3d(out.translation.x, out.translation.y, out.translation.z),
+        out.grounded,
+        out.is_sliding_down_slope,
+    )
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/Physics.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/Physics.native.kt
index 22500c9..82ed150 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/Physics.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/Physics.native.kt
@@ -1,42 +1,90 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityRef
+import com.dropbear.ffi.generated.NShapeCastHit
+import com.dropbear.ffi.generated.NVector3
+import com.dropbear.ffi.generated.RayHit as FfiRayHit
+import com.dropbear.ffi.generated.allocCollider
+import com.dropbear.ffi.generated.allocColliderShape
+import com.dropbear.ffi.generated.allocVec3
+import com.dropbear.ffi.generated.dropbear_physics_get_gravity
+import com.dropbear.ffi.generated.dropbear_physics_is_overlapping
+import com.dropbear.ffi.generated.dropbear_physics_is_touching
+import com.dropbear.ffi.generated.dropbear_physics_is_triggering
+import com.dropbear.ffi.generated.dropbear_physics_raycast
+import com.dropbear.ffi.generated.dropbear_physics_set_gravity
+import com.dropbear.ffi.generated.dropbear_physics_shape_cast
+import com.dropbear.ffi.generated.readCollider
+import com.dropbear.ffi.generated.readShapeCastStatus
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun getGravity(): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun getGravity(): Vector3d = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_physics_get_gravity(physics, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun setGravity(gravity: Vector3d) {
+internal actual fun setGravity(gravity: Vector3d) = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nv = allocVec3(gravity)
+    dropbear_physics_set_gravity(physics, nv.ptr)
 }
 
-internal actual fun raycast(
-    origin: Vector3d,
-    direction: Vector3d,
-    toi: Double,
-    solid: Boolean
-): RayHit? {
-    TODO("Not yet implemented")
+internal actual fun raycast(origin: Vector3d, direction: Vector3d, toi: Double, solid: Boolean): RayHit? = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped null
+    val nOrigin = allocVec3(origin)
+    val nDir = allocVec3(direction)
+    val out = alloc<FfiRayHit>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_physics_raycast(physics, nOrigin.ptr, nDir.ptr, toi, solid, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else RayHit(readCollider(out.collider), out.distance)
 }
 
-internal actual fun isOverlapping(collider1: Collider, collider2: Collider): Boolean {
-    TODO("Not implemented yet")
+internal actual fun isOverlapping(collider1: Collider, collider2: Collider): Boolean = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val nc1 = allocCollider(collider1)
+    val nc2 = allocCollider(collider2)
+    val out = alloc<BooleanVar>()
+    dropbear_physics_is_overlapping(physics, nc1.ptr, nc2.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun isTriggering(collider1: Collider, collider2: Collider): Boolean {
-    TODO("Not implemented yet")
+internal actual fun isTriggering(collider1: Collider, collider2: Collider): Boolean = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val nc1 = allocCollider(collider1)
+    val nc2 = allocCollider(collider2)
+    val out = alloc<BooleanVar>()
+    dropbear_physics_is_triggering(physics, nc1.ptr, nc2.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun isTouching(entity1: EntityRef, entity2: EntityRef): Boolean {
-    TODO("Not implemented yet")
+internal actual fun isTouching(entity1: EntityRef, entity2: EntityRef): Boolean = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_physics_is_touching(physics, entity1.id.raw.toULong(), entity2.id.raw.toULong(), out.ptr)
+    out.value
 }
 
-internal actual fun shapeCast(
-    origin: Vector3d,
-    direction: Vector3d,
-    shape: ColliderShape,
-    toi: Double,
-    solid: Boolean
-): ShapeCastHit? {
-    TODO("Not yet implemented")
+internal actual fun shapeCast(origin: Vector3d, direction: Vector3d, shape: ColliderShape, toi: Double, solid: Boolean): ShapeCastHit? = memScoped {
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped null
+    val nOrigin = allocVec3(origin)
+    val nDir = allocVec3(direction)
+    val nShape = allocColliderShape(shape)
+    val out = alloc<NShapeCastHit>()
+    val present = alloc<BooleanVar>()
+    val rc = dropbear_physics_shape_cast(physics, nOrigin.ptr, nDir.ptr, nShape.ptr, toi, solid, out.ptr, present.ptr)
+    if (rc != 0 || !present.value) null else ShapeCastHit(
+        readCollider(out.collider),
+        out.distance,
+        Vector3d(out.witness1.x, out.witness1.y, out.witness1.z),
+        Vector3d(out.witness2.x, out.witness2.y, out.witness2.z),
+        Vector3d(out.normal1.x, out.normal1.y, out.normal1.z),
+        Vector3d(out.normal2.x, out.normal2.y, out.normal2.z),
+        readShapeCastStatus(out.status),
+    )
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt b/scripting/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt
index e202276..9fb2227 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/physics/RigidBody.native.kt
@@ -1,128 +1,227 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.physics
 
+import com.dropbear.DropbearEngine
 import com.dropbear.EntityId
+import com.dropbear.ffi.generated.AxisLock as FfiAxisLock
+import com.dropbear.ffi.generated.NColliderArray
+import com.dropbear.ffi.generated.NVector3
+import com.dropbear.ffi.generated.RigidBodyContext
+import com.dropbear.ffi.generated.allocCollider
+import com.dropbear.ffi.generated.allocRigidBodyCtx
+import com.dropbear.ffi.generated.dropbear_rigidbody_apply_impulse
+import com.dropbear.ffi.generated.dropbear_rigidbody_apply_torque_impulse
+import com.dropbear.ffi.generated.dropbear_rigidbody_exists_for_entity
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_angular_damping
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_angular_velocity
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_ccd_enabled
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_children
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_gravity_scale
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_linear_damping
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_linear_velocity
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_lock_rotation
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_lock_translation
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_mode
+import com.dropbear.ffi.generated.dropbear_rigidbody_get_rigidbody_sleep
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_angular_damping
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_angular_velocity
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_ccd_enabled
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_gravity_scale
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_linear_damping
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_linear_velocity
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_lock_rotation
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_lock_translation
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_mode
+import com.dropbear.ffi.generated.dropbear_rigidbody_set_rigidbody_sleep
+import com.dropbear.ffi.generated.IndexNative
+import com.dropbear.ffi.generated.readCollider
 import com.dropbear.math.Vector3d
+import kotlinx.cinterop.*
 
-internal actual fun RigidBody.setRigidbodyMode(
-    rigidBody: RigidBody,
-    mode: RigidBodyMode
-) {
-}
+private fun MemScope.rbCtx(rb: RigidBody): RigidBodyContext = allocRigidBodyCtx(rb)
 
-internal actual fun RigidBody.getRigidbodyMode(rigidBody: RigidBody): RigidBodyMode {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.getRigidbodyMode(rigidBody: RigidBody): RigidBodyMode = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped RigidBodyMode.Dynamic
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped RigidBodyMode.Dynamic
+    val ctx = rbCtx(rigidBody)
+    val out = alloc<IntVar>()
+    dropbear_rigidbody_get_rigidbody_mode(world, physics, ctx.ptr, out.ptr)
+    RigidBodyMode.entries[out.value.coerceIn(0, RigidBodyMode.entries.lastIndex)]
 }
 
-internal actual fun RigidBody.getRigidbodyGravityScale(rigidBody: RigidBody): Double {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyMode(rigidBody: RigidBody, mode: RigidBodyMode) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val ctx = rbCtx(rigidBody)
+    dropbear_rigidbody_set_rigidbody_mode(world, physics, ctx.ptr, mode.ordinal)
 }
 
-internal actual fun RigidBody.setRigidbodyGravityScale(
-    rigidBody: RigidBody,
-    gravityScale: Double
-) {
+internal actual fun RigidBody.getRigidbodyGravityScale(rigidBody: RigidBody): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 1.0
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 1.0
+    val ctx = rbCtx(rigidBody)
+    val out = alloc<DoubleVar>()
+    dropbear_rigidbody_get_rigidbody_gravity_scale(world, physics, ctx.ptr, out.ptr)
+    out.value
 }
 
-internal actual fun RigidBody.getRigidBodySleep(rigidBody: RigidBody): Boolean {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyGravityScale(rigidBody: RigidBody, gravityScale: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    dropbear_rigidbody_set_rigidbody_gravity_scale(world, physics, rbCtx(rigidBody).ptr, gravityScale)
 }
 
-internal actual fun RigidBody.setRigidBodySleep(
-    rigidBody: RigidBody,
-    canSleep: Boolean
-) {
+internal actual fun RigidBody.getRigidBodySleep(rigidBody: RigidBody): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_rigidbody_get_rigidbody_sleep(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    out.value
 }
 
-internal actual fun RigidBody.getRigidbodyCcdEnabled(rigidBody: RigidBody): Boolean {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidBodySleep(rigidBody: RigidBody, canSleep: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    dropbear_rigidbody_set_rigidbody_sleep(world, physics, rbCtx(rigidBody).ptr, canSleep)
 }
 
-internal actual fun RigidBody.setRigidbodyCcdEnabled(
-    rigidBody: RigidBody,
-    ccdEnabled: Boolean
-) {
+internal actual fun RigidBody.getRigidbodyCcdEnabled(rigidBody: RigidBody): Boolean = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped false
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped false
+    val out = alloc<BooleanVar>()
+    dropbear_rigidbody_get_rigidbody_ccd_enabled(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    out.value
 }
 
-internal actual fun RigidBody.getRigidbodyLinearVelocity(rigidBody: RigidBody): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyCcdEnabled(rigidBody: RigidBody, ccdEnabled: Boolean) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    dropbear_rigidbody_set_rigidbody_ccd_enabled(world, physics, rbCtx(rigidBody).ptr, ccdEnabled)
 }
 
-internal actual fun RigidBody.setRigidbodyLinearDamping(
-    rigidBody: RigidBody,
-    linearDamping: Double
-) {
+internal actual fun RigidBody.getRigidbodyLinearVelocity(rigidBody: RigidBody): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_rigidbody_get_rigidbody_linear_velocity(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun RigidBody.setRigidbodyLinearVelocity(
-    rigidBody: RigidBody,
-    linearVelocity: Vector3d
-) {
+internal actual fun RigidBody.setRigidbodyLinearVelocity(rigidBody: RigidBody, linearVelocity: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nv = alloc<NVector3>().also { it.x = linearVelocity.x; it.y = linearVelocity.y; it.z = linearVelocity.z }
+    dropbear_rigidbody_set_rigidbody_linear_velocity(world, physics, rbCtx(rigidBody).ptr, nv.ptr)
 }
 
-internal actual fun RigidBody.getRigidbodyAngularVelocity(rigidBody: RigidBody): Vector3d {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.getRigidbodyLinearDamping(rigidBody: RigidBody): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_rigidbody_get_rigidbody_linear_damping(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    out.value
 }
 
-internal actual fun RigidBody.setRigidbodyAngularVelocity(
-    rigidBody: RigidBody,
-    angularVelocity: Vector3d
-) {
+internal actual fun RigidBody.setRigidbodyLinearDamping(rigidBody: RigidBody, linearDamping: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    dropbear_rigidbody_set_rigidbody_linear_damping(world, physics, rbCtx(rigidBody).ptr, linearDamping)
 }
 
-internal actual fun RigidBody.getRigidbodyLinearDamping(rigidBody: RigidBody): Double {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.getRigidbodyAngularVelocity(rigidBody: RigidBody): Vector3d = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped Vector3d.zero()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped Vector3d.zero()
+    val out = alloc<NVector3>()
+    dropbear_rigidbody_get_rigidbody_angular_velocity(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    Vector3d(out.x, out.y, out.z)
 }
 
-internal actual fun RigidBody.getRigidbodyAngularDamping(rigidBody: RigidBody): Double {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyAngularVelocity(rigidBody: RigidBody, angularVelocity: Vector3d) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val nv = alloc<NVector3>().also { it.x = angularVelocity.x; it.y = angularVelocity.y; it.z = angularVelocity.z }
+    dropbear_rigidbody_set_rigidbody_angular_velocity(world, physics, rbCtx(rigidBody).ptr, nv.ptr)
 }
 
-internal actual fun RigidBody.setRigidbodyAngularDamping(
-    rigidBody: RigidBody,
-    angularDamping: Double
-) {
+internal actual fun RigidBody.getRigidbodyAngularDamping(rigidBody: RigidBody): Double = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped 0.0
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped 0.0
+    val out = alloc<DoubleVar>()
+    dropbear_rigidbody_get_rigidbody_angular_damping(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    out.value
 }
 
-internal actual fun RigidBody.getRigidbodyLockTranslation(rigidBody: RigidBody): AxisLock {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyAngularDamping(rigidBody: RigidBody, angularDamping: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    dropbear_rigidbody_set_rigidbody_angular_damping(world, physics, rbCtx(rigidBody).ptr, angularDamping)
 }
 
-internal actual fun RigidBody.setRigidbodyLockTranslation(
-    rigidBody: RigidBody,
-    lockTranslation: AxisLock
-) {
+internal actual fun RigidBody.getRigidbodyLockTranslation(rigidBody: RigidBody): AxisLock = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped AxisLock()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped AxisLock()
+    val out = alloc<FfiAxisLock>()
+    dropbear_rigidbody_get_rigidbody_lock_translation(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    AxisLock(out.x, out.y, out.z)
 }
 
-internal actual fun RigidBody.getRigidbodyLockRotation(rigidBody: RigidBody): AxisLock {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyLockTranslation(rigidBody: RigidBody, lockTranslation: AxisLock) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val al = alloc<FfiAxisLock>().also { it.x = lockTranslation.x; it.y = lockTranslation.y; it.z = lockTranslation.z }
+    dropbear_rigidbody_set_rigidbody_lock_translation(world, physics, rbCtx(rigidBody).ptr, al.ptr)
 }
 
-internal actual fun RigidBody.setRigidbodyLockRotation(
-    rigidBody: RigidBody,
-    lockRotation: AxisLock
-) {
+internal actual fun RigidBody.getRigidbodyLockRotation(rigidBody: RigidBody): AxisLock = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped AxisLock()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped AxisLock()
+    val out = alloc<FfiAxisLock>()
+    dropbear_rigidbody_get_rigidbody_lock_rotation(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    AxisLock(out.x, out.y, out.z)
 }
 
-internal actual fun RigidBody.getRigidbodyChildren(rigidBody: RigidBody): List<Collider> {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.setRigidbodyLockRotation(rigidBody: RigidBody, lockRotation: AxisLock) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val al = alloc<FfiAxisLock>().also { it.x = lockRotation.x; it.y = lockRotation.y; it.z = lockRotation.z }
+    dropbear_rigidbody_set_rigidbody_lock_rotation(world, physics, rbCtx(rigidBody).ptr, al.ptr)
 }
 
-internal actual fun RigidBody.applyImpulse(
-    index: Index,
-    x: Double,
-    y: Double,
-    z: Double
-) {
+internal actual fun RigidBody.getRigidbodyChildren(rigidBody: RigidBody): List<Collider> = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped emptyList()
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped emptyList()
+    val out = alloc<NColliderArray>()
+    val rc = dropbear_rigidbody_get_rigidbody_children(world, physics, rbCtx(rigidBody).ptr, out.ptr)
+    if (rc != 0) return@memScoped emptyList()
+    val ptr = out.values ?: return@memScoped emptyList()
+    val len = out.length.toInt()
+    (0 until len).map { i -> readCollider(ptr[i]) }
 }
 
-internal actual fun RigidBody.applyTorqueImpulse(
-    index: Index,
-    x: Double,
-    y: Double,
-    z: Double
-) {
+internal actual fun RigidBody.applyImpulse(index: Index, x: Double, y: Double, z: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val ctx = alloc<RigidBodyContext>()
+    ctx.index.index = index.index; ctx.index.generation = index.generation
+    ctx.entity_id = this@applyImpulse.entity.raw.toULong()
+    dropbear_rigidbody_apply_impulse(world, physics, ctx.ptr, x, y, z)
 }
 
-internal actual fun rigidBodyExistsForEntity(entityId: EntityId): Index? {
-    TODO("Not yet implemented")
+internal actual fun RigidBody.applyTorqueImpulse(index: Index, x: Double, y: Double, z: Double) = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped
+    val ctx = alloc<RigidBodyContext>()
+    ctx.index.index = index.index; ctx.index.generation = index.generation
+    ctx.entity_id = this@applyTorqueImpulse.entity.raw.toULong()
+    dropbear_rigidbody_apply_torque_impulse(world, physics, ctx.ptr, x, y, z)
+}
+
+internal actual fun rigidBodyExistsForEntity(entityId: EntityId): Index? = memScoped {
+    val world = DropbearEngine.native.worldHandle ?: return@memScoped null
+    val physics = DropbearEngine.native.physicsEngineHandle ?: return@memScoped null
+    val out = alloc<IndexNative>()
+    val present = alloc<BooleanVar>()
+    dropbear_rigidbody_exists_for_entity(world, physics, entityId.raw.toULong(), out.ptr, present.ptr)
+    if (!present.value) null else Index(out.index, out.generation)
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt b/scripting/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt
index 5e49c4f..a88836b 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/scene/SceneLoadHandle.native.kt
@@ -1,19 +1,44 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.scene
 
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.*
+import kotlin.String
 import com.dropbear.utils.Progress
+import kotlinx.cinterop.*
 
 internal actual fun SceneLoadHandle.switchToSceneAsync() {
-    TODO("Not yet implemented")
+    val cmd = DropbearEngine.native.commandBufferHandle ?: return
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return
+    memScoped { dropbear_scripting_switch_to_scene_async(cmd, sceneLoader, id.toULong()) }
 }
 
-internal actual fun SceneLoadHandle.getSceneLoadProgress(): Progress {
-    TODO("Not yet implemented")
+internal actual fun SceneLoadHandle.getSceneLoadProgress(): Progress = memScoped {
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return@memScoped Progress.nothing()
+    val out = alloc<com.dropbear.ffi.generated.Progress>()
+    val rc = dropbear_scripting_get_scene_load_progress(sceneLoader, id.toULong(), out.ptr)
+    if (rc != 0) Progress.nothing() else Progress(
+        out.current.toDouble(),
+        out.total.toDouble(),
+        out.message?.toKString()
+    )
 }
 
-internal actual fun SceneLoadHandle.getSceneLoadStatus(): SceneLoadStatus {
-    TODO("Not yet implemented")
+internal actual fun SceneLoadHandle.getSceneLoadStatus(): SceneLoadStatus = memScoped {
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return@memScoped SceneLoadStatus.FAILED
+    val out = alloc<UIntVar>()
+    val rc = dropbear_scripting_get_scene_load_status(sceneLoader, id.toULong(), out.ptr)
+    if (rc != 0) SceneLoadStatus.FAILED else when (out.value.toInt()) {
+        0 -> SceneLoadStatus.PENDING
+        1 -> SceneLoadStatus.READY
+        else -> SceneLoadStatus.FAILED
+    }
 }
 
-internal actual fun SceneLoadHandle.getSceneLoadHandleSceneName(id: Long): String {
-    TODO("Not yet implemented")
+internal actual fun SceneLoadHandle.getSceneLoadHandleSceneName(id: Long): String = memScoped {
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return@memScoped ""
+    val out = alloc<CPointerVar<ByteVar>>()
+    val rc = dropbear_scripting_get_scene_load_handle_scene_name(sceneLoader, id.toULong(), out.ptr)
+    if (rc != 0) "" else out.value?.toKString() ?: ""
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt b/scripting/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt
index fd77cbb..d1d353f 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/scene/SceneManager.native.kt
@@ -1,15 +1,29 @@
+@file:OptIn(ExperimentalForeignApi::class)
+
 package com.dropbear.scene
 
-internal actual fun SceneManager.loadSceneAsyncNative(sceneName: String): SceneLoadHandle? {
-    TODO("Not yet implemented")
+import com.dropbear.DropbearEngine
+import com.dropbear.ffi.generated.*
+import kotlin.String
+import kotlinx.cinterop.*
+
+internal actual fun SceneManager.loadSceneAsyncNative(sceneName: String): SceneLoadHandle? = memScoped {
+    val cmd = DropbearEngine.native.commandBufferHandle ?: return@memScoped null
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val rc = dropbear_scripting_load_scene_async(cmd, sceneLoader, sceneName, out.ptr)
+    if (rc != 0) null else SceneLoadHandle(out.value.toLong())
 }
 
-internal actual fun SceneManager.loadSceneAsyncNative(
-    sceneName: String,
-    loadingScene: String
-): SceneLoadHandle? {
-    TODO("Not yet implemented")
+internal actual fun SceneManager.loadSceneAsyncNative(sceneName: String, loadingScene: String): SceneLoadHandle? = memScoped {
+    val cmd = DropbearEngine.native.commandBufferHandle ?: return@memScoped null
+    val sceneLoader = DropbearEngine.native.sceneLoaderHandle ?: return@memScoped null
+    val out = alloc<ULongVar>()
+    val rc = dropbear_scripting_load_scene_async_with_loading(cmd, sceneLoader, sceneName, loadingScene, out.ptr)
+    if (rc != 0) null else SceneLoadHandle(out.value.toLong())
 }
 
 internal actual fun SceneManager.switchToSceneImmediateNative(sceneName: String) {
+    val cmd = DropbearEngine.native.commandBufferHandle ?: return
+    memScoped { dropbear_scripting_switch_to_scene_immediate(cmd, sceneName) }
 }
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ui/Response.native.kt b/scripting/nativeMain/kotlin/com/dropbear/ui/Response.native.kt
index 5c78860..be3dfa3 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/ui/Response.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/ui/Response.native.kt
@@ -2,10 +2,6 @@ package com.dropbear.ui
 
 import com.dropbear.ui.Response
 
-actual fun Response.getClicked(): Boolean {
-    TODO("Not yet implemented")
-}
-
-actual fun Response.getHovering(): Boolean {
-    TODO("Not yet implemented")
-}
\ No newline at end of file
+// UI response queries have no C API yet; always return non-interacted state
+actual fun Response.getClicked(): Boolean = false
+actual fun Response.getHovering(): Boolean = false
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Rectangle.native.kt b/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Rectangle.native.kt
index bb7a043..a74e945 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Rectangle.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Rectangle.native.kt
@@ -1,8 +1,5 @@
 package com.dropbear.ui.widgets
 
 import com.dropbear.ui.Response
-import com.dropbear.ui.widgets.Rectangle
 
-actual fun Rectangle.getResponse(): Response {
-    TODO("Not yet implemented")
-}
\ No newline at end of file
+actual fun Rectangle.getResponse(): Response = Response(id)
\ No newline at end of file
diff --git a/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Text.native.kt b/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Text.native.kt
index 86f4d31..4b79f2c 100644
--- a/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Text.native.kt
+++ b/scripting/nativeMain/kotlin/com/dropbear/ui/widgets/Text.native.kt
@@ -2,6 +2,4 @@ package com.dropbear.ui.widgets
 
 import com.dropbear.ui.Response
 
-actual fun Text.getResponse(): Response {
-    TODO("Not yet implemented")
-}
\ No newline at end of file
+actual fun Text.getResponse(): Response = Response(id)
\ No newline at end of file