kitgit

tirbofish/dropbear · diff

8a42193 · tk

completed the Kotlin/Native part of the three functions, hopefully it works (haven't tested it yet). todo: gotta work on the library loading of the project and work on more API's.

Unverified

diff --git a/eucalyptus-core/src/scripting/kmp.rs b/eucalyptus-core/src/scripting/kmp.rs
index 789d05f..40ee728 100644
--- a/eucalyptus-core/src/scripting/kmp.rs
+++ b/eucalyptus-core/src/scripting/kmp.rs
@@ -1,17 +1,27 @@
 //! Deals with Kotlin/Native library loading for different platforms.
+#![allow(clippy::missing_safety_doc)]
 
-use dropbear_engine::entity::AdoptedEntity;
+use dropbear_engine::entity::{AdoptedEntity, Transform};
 use std::ffi::{CStr, c_char};
 
-/// Looks up an entity by its string label in the given world and writes the result to `out_entity`.
-///
-/// # Safety
-///
-/// - `label` must be a valid null-terminated C string.
-/// - `world_ptr` must be a non-null pointer to a valid, initialized `hecs::World`
-///   that is not being mutably aliased (i.e., no concurrent mutable access).
-/// - `out_entity` must be a non-null pointer to a `uint64_t` (`u64`) that the caller owns.
-/// - The `hecs::World` must outlive the duration of this call.
+/// Displays the types of errors that can be returned by the native library.
+pub enum DropbearNativeError {
+    Success = 0,
+    NullPointer = -1,
+    QueryFailed = -2,
+    EntityNotFound = -3,
+    NoSuchComponent = -4,
+    NoSuchEntity = -5,
+    WorldInsertError = -6,
+
+    InvalidUTF8 = -108,
+    /// A generic error when the library doesn't know what happened or cannot find a
+    /// suitable error code.
+    ///
+    /// The number `1274` comes from the total sum of the word "UnknownError" into decimal
+    UnknownError = -1274,
+}
+
 #[unsafe(no_mangle)]
 pub unsafe extern "C" fn dropbear_get_entity(
     label: *const c_char,
@@ -20,7 +30,7 @@ pub unsafe extern "C" fn dropbear_get_entity(
 ) -> i32 {
     unsafe {
         if label.is_null() || world_ptr.is_null() || out_entity.is_null() {
-            log::warn!("dropbear_get_entity: received null pointer");
+            println!("[dropbear_get_entity] [ERROR] received null pointer");
             return -1;
         }
 
@@ -29,20 +39,91 @@ pub unsafe extern "C" fn dropbear_get_entity(
         let label_str = match CStr::from_ptr(label).to_str() {
             Ok(s) => s,
             Err(_) => {
-                log::warn!("dropbear_get_entity: invalid UTF-8 in label");
-                return -1;
+                println!("[dropbear_get_entity] [ERROR] invalid UTF-8 in label");
+                return -108;
             }
         };
 
+        let mut hit: bool = false;
+
         for (id, entity) in world.query::<&AdoptedEntity>().iter() {
             if entity.model.label == label_str {
+                #[allow(unused_assignments)]
+                { hit = true; }
                 *out_entity = id.id() as i64;
                 log::debug!("Found entity with label: {:?}", label_str);
                 return 0;
             }
         }
 
-        log::warn!("Entity with label '{:?}' not found", label_str);
-        -1
+        if !hit {
+            println!("[dropbear_get_entity] [ERROR] Entity with label '{:?}' not found", label_str);
+            -3
+        } else {
+            DropbearNativeError::UnknownError as i32
+        }
+    }
+}
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn dropbear_get_transform(
+    world_ptr: *const hecs::World,
+    entity_id: i64,
+    out_transform: *mut Transform,
+) -> i32 {
+    if world_ptr.is_null() {
+        eprintln!("[dropbear_get_transform] [ERROR] World pointer is null");
+        return -1;
+    }
+
+    if out_transform.is_null() {
+        eprintln!("[dropbear_get_transform] [ERROR] Output transform pointer is null");
+        return -1;
+    }
+
+    let world = unsafe { &*world_ptr };
+
+    let entity = unsafe { world.find_entity_from_id(entity_id as u32) };
+
+    match world.query_one::<&Transform>(entity) {
+        Ok(mut q) => {
+            if let Some(transform) = q.get() {
+                unsafe { *out_transform = *transform };
+                0
+            } else {
+                eprintln!("[dropbear_get_transform] [ERROR] Entity has no Transform component");
+                -4
+            }
+        }
+        Err(_) => {
+            eprintln!("[dropbear_get_transform] [ERROR] Failed to query entity for Transform component");
+            -2
+        }
+    }
+}
+
+pub unsafe extern "C" fn dropbear_set_transform(
+    world_ptr: *mut hecs::World,
+    entity_id: i64,
+    transform: Transform,
+) -> i32 {
+    if world_ptr.is_null() {
+        eprintln!("[dropbear_get_transform] [ERROR] World pointer is null");
+        return -1;
+    }
+
+    let world = unsafe { &mut *world_ptr };
+
+    let entity = unsafe { world.find_entity_from_id(entity_id as u32) };
+
+    let result = world.insert_one(entity, transform);
+
+    match result {
+        Ok(_) => 0,
+        Err(_) => {
+            eprintln!("[dropbear_set_transform] [ERROR] Failed to insert transform component");
+            -6
+        },
     }
 }
+
diff --git a/headers/dropbear.h b/headers/dropbear.h
index a74a05d..14fadb9 100644
--- a/headers/dropbear.h
+++ b/headers/dropbear.h
@@ -12,9 +12,35 @@ extern "C" {
 
 // ===========================================
 
-// returns 0 on success, non-zero on failure
+typedef struct {
+    double position_x;
+    double position_y;
+    double position_z;
+    double rotation_x;
+    double rotation_y;
+    double rotation_z;
+    double rotation_w;
+    double scale_x;
+    double scale_y;
+    double scale_z;
+} NativeTransform;
+
+// ===========================================
+
 int dropbear_get_entity(const char* label, const World* world_ptr, int64_t* out_entity);
 
+int dropbear_get_transform(
+    const World* world_ptr,
+    int64_t entity_id,
+    NativeTransform* out_transform
+);
+
+int dropbear_set_transform(
+    const World* world_ptr,
+    int64_t entity_id,
+    const NativeTransform transform
+);
+
 // ===========================================
 
 #ifdef __cplusplus
diff --git a/settings.gradle.kts b/settings.gradle.kts
index bb7d28e..6c22cfe 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -6,4 +6,7 @@ pluginManagement {
         gradlePluginPortal()
     }
 }
+plugins {
+    id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
+}
 include("magna-carta-plugin")
\ No newline at end of file
diff --git a/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt b/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
index 61f55a9..58c2dec 100644
--- a/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
+++ b/src/nativeMain/kotlin/com/dropbear/ffi/NativeEngine.native.kt
@@ -4,7 +4,7 @@
 package com.dropbear.ffi
 
 import com.dropbear.EntityId
-import com.dropbear.ffi.generated.dropbear_get_entity
+import com.dropbear.ffi.generated.*
 import com.dropbear.logging.Logger
 import com.dropbear.math.Transform
 import kotlinx.cinterop.*
@@ -35,9 +35,62 @@ actual class NativeEngine {
     }
 
     actual fun getTransform(entityId: EntityId): Transform? {
-        TODO("Not yet implemented")
+        val world = worldHandle ?: return null
+        memScoped {
+            val outTransform = alloc<NativeTransform>()
+            val result = dropbear_get_transform(
+                world_ptr = world.reinterpret(),
+                entity_id = entityId.id,
+                out_transform = outTransform.ptr
+            )
+            if (result == 0) {
+                return Transform(
+                    position = com.dropbear.math.Vector3D(
+                        outTransform.position_x,
+                        outTransform.position_y,
+                        outTransform.position_z
+                    ),
+                    rotation = com.dropbear.math.QuaternionD(
+                        outTransform.rotation_x,
+                        outTransform.rotation_y,
+                        outTransform.rotation_z,
+                        outTransform.rotation_w
+                    ),
+                    scale = com.dropbear.math.Vector3D(
+                        outTransform.scale_x,
+                        outTransform.scale_y,
+                        outTransform.scale_z
+                    )
+                )
+            } else {
+                return null
+            }
+        }
     }
 
     actual fun setTransform(entityId: EntityId, transform: Transform) {
+        val world = worldHandle ?: return
+        memScoped {
+            val nativeTransform = cValue<NativeTransform> {
+                position_x = transform.position.x
+                position_y = transform.position.y
+                position_z = transform.position.z
+
+                rotation_w = transform.rotation.w
+                rotation_x = transform.rotation.x
+                rotation_y = transform.rotation.y
+                rotation_z = transform.rotation.z
+
+                scale_x = transform.scale.x
+                scale_y = transform.scale.y
+                scale_z = transform.scale.z
+            }
+
+            dropbear_set_transform(
+                world_ptr = world.reinterpret(),
+                entity_id = entityId.id,
+                transform = nativeTransform
+            )
+        }
     }
 }
\ No newline at end of file