tirbofish/dropbear · diff
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.
Signature present but could not be verified.
Unverified
@@ -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 + }, } } + @@ -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 @@ -6,4 +6,7 @@ pluginManagement { gradlePluginPortal() } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} include("magna-carta-plugin") @@ -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 + ) + } } }