tirbofish/dropbear · commit
160b23ff5cec41fd4777aee71023784eb0b3d625
wip: got asset working (sorta), everything else is broken
Signature present but could not be verified.
Unverified
@@ -12,12 +12,23 @@ use crate::model::Model; pub static ASSET_REGISTRY: LazyLock<Arc<RwLock<AssetRegistry>>> = LazyLock::new(|| Arc::new(RwLock::new(AssetRegistry::new()))); /// A handle with type [`T`] that provides an index to the [AssetRegistry] contents. -#[derive(Hash, Eq, PartialEq, Debug)] +#[derive(Hash, Eq, Debug)] pub struct Handle<T> { pub id: u64, _phantom: PhantomData<T> } +impl<T> PartialEq for Handle<T> { + fn eq(&self, other: &Self) -> bool { + if self.is_null() && other.is_null() { + return false; + } + self.id == other.id + } + + +} + impl<T> Copy for Handle<T> {} impl<T> Clone for Handle<T> { @@ -30,7 +41,7 @@ impl<T> Handle<T> { /// Creates a null handle, for when there is no way to uniquely identify a hash (such as a viewport texture). /// /// # Safety - /// You will want to watch out, as adding this onto the asset_old registry with a type + /// You will want to watch out, as adding this onto the asset registry with a type /// where there already is a null handle item, it will be overwritten and data /// will not be saved. It is the reason why you will want to consider using the [Self::is_null] /// function to verify if the storage of the type has gone through correctly. @@ -54,6 +65,14 @@ pub struct AssetRegistry { models: HashMap<u64, Model>, model_labels: HashMap<String, Handle<Model>>, } + +#[derive(Debug, Clone)] +#[dropbear_macro::repr_c_enum] +pub enum AssetKind { + Texture, + Model, +} + /// Common impl AssetRegistry { pub fn new() -> Self { @@ -79,14 +98,14 @@ impl AssetRegistry { hasher.finish() } - /// Checks if the asset_old registry contains a handle with the given hash. + /// Checks if the asset registry contains a handle with the given hash. /// /// It will check all different types, so it does not point out specifically where. pub fn contains_hash(&self, hash: u64) -> bool { self.textures.contains_key(&hash) || self.models.contains_key(&hash) } - /// Checks if the asset_old registry contains a handle with the given string label. + /// Checks if the asset registry contains a handle with the given string label. /// /// It will check all different types, so it does not point out specifically where. pub fn contains_label(&self, label: &str) -> bool { @@ -126,7 +145,7 @@ impl AssetRegistry { self.texture_labels.remove(label); } - /// Updates the asset_old server by inserting the texture provided at the location of the handle, + /// Updates the asset server by inserting the texture provided at the location of the handle, /// and removing the old texture (by returning it back to you). pub fn update_texture(&mut self, handle: Handle<Texture>, texture: Texture) -> Option<Texture> { self.textures.insert(handle.id, texture) @@ -225,6 +244,10 @@ impl AssetRegistry { pub fn model_handle_by_hash(&self, hash: u64) -> Option<Handle<Model>> { self.models.contains_key(&hash).then(|| Handle::new(hash)) } + + pub fn get_label_from_model_handle(&self, handle: Handle<Model>) -> Option<String> { + self.model_labels.iter().find_map(|(label, h)| if *h == handle { Some(label.clone()) } else { None }) + } } impl Default for AssetRegistry { @@ -68,7 +68,7 @@ pub struct Texture { pub sampler: wgpu::Sampler, pub size: wgpu::Extent3d, pub view: wgpu::TextureView, - pub(crate) hash: Option<u64>, + pub hash: Option<u64>, } impl Texture { @@ -181,7 +181,7 @@ impl ResourceReference { }) } - /// Returns the canonical euca URI for this reference if it points to a file asset_old. + /// Returns the canonical euca URI for this reference if it points to a file asset. pub fn as_uri(&self) -> Option<&str> { match &self.ref_type { ResourceReferenceType::File(reference) => Some(reference.as_str()), @@ -4,7 +4,7 @@ use syn::{ parse::{Parse, ParseStream}, parse_macro_input, parse_quote, spanned::Spanned, - DeriveInput, FnArg, GenericArgument, Ident, Item, ItemFn, ItemMod, LitStr, PathArguments, + DeriveInput, FnArg, GenericArgument, Ident, Item, ItemFn, ItemMod, ItemEnum, LitStr, PathArguments, ReturnType, Token, Type, }; @@ -270,6 +270,210 @@ pub fn export(attr: TokenStream, item: TokenStream) -> TokenStream { expanded.into() } +#[proc_macro_attribute] +pub fn repr_c_enum(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemEnum); + let enum_ident = input.ident.clone(); + let enum_name = enum_ident.to_string(); + let mod_ident = Ident::new(&format!("{}_ffi", to_snake_case(&enum_name)), enum_ident.span()); + let tag_ident = Ident::new(&format!("{}Tag", enum_name), enum_ident.span()); + let data_ident = Ident::new(&format!("{}Data", enum_name), enum_ident.span()); + let ffi_ident = Ident::new(&format!("{}Ffi", enum_name), enum_ident.span()); + + let mut tag_variants = Vec::new(); + let mut variant_structs = Vec::new(); + let mut data_union_fields = Vec::new(); + let mut match_arms = Vec::new(); + let mut array_structs = std::collections::BTreeMap::new(); + + for (index, variant) in input.variants.iter().enumerate() { + let variant_ident = &variant.ident; + let variant_name = variant_ident.to_string(); + let variant_struct_ident = Ident::new(&format!("{}{}", enum_name, variant_name), variant_ident.span()); + + let index = index as u32; + tag_variants.push(quote! { #variant_ident = #index }); + data_union_fields.push(quote! { + pub #variant_ident: ::std::mem::ManuallyDrop<#variant_struct_ident> + }); + + let (fields, field_inits, match_pattern) = build_variant_fields( + &enum_ident, + variant, + &mut array_structs, + ); + + variant_structs.push(quote! { + #[repr(C)] + #[derive(Clone, Debug)] + pub struct #variant_struct_ident { + #(#fields)* + } + }); + + match_arms.push(quote! { + #match_pattern => { + let data = #data_ident { + #variant_ident: ::std::mem::ManuallyDrop::new(#variant_struct_ident { #(#field_inits)* }) + }; + #ffi_ident { tag: #tag_ident::#variant_ident, data } + } + }); + } + + let array_struct_defs = array_structs.values().cloned().collect::<Vec<_>>(); + + let expanded = quote! { + #input + + #[allow(non_snake_case)] + pub mod #mod_ident { + use super::*; + + #(#array_struct_defs)* + + #[repr(u32)] + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub enum #tag_ident { + #(#tag_variants,)* + } + + #(#variant_structs)* + + #[repr(C)] + #[allow(non_snake_case)] + pub union #data_ident { + #(#data_union_fields,)* + } + + #[repr(C)] + pub struct #ffi_ident { + pub tag: #tag_ident, + pub data: #data_ident, + } + + impl From<&#enum_ident> for #ffi_ident { + fn from(value: &#enum_ident) -> Self { + match value { + #(#match_arms)* + } + } + } + } + }; + + expanded.into() +} + +fn build_variant_fields( + enum_ident: &Ident, + variant: &syn::Variant, + array_structs: &mut std::collections::BTreeMap<String, proc_macro2::TokenStream>, +) -> (Vec<proc_macro2::TokenStream>, Vec<proc_macro2::TokenStream>, proc_macro2::TokenStream) { + let mut fields = Vec::new(); + let mut field_inits = Vec::new(); + + match &variant.fields { + syn::Fields::Named(named) => { + let mut pat_fields = Vec::new(); + for field in &named.named { + let field_ident = field.ident.as_ref().expect("named field"); + let (field_ty, init_expr) = map_field_type(enum_ident, &field.ty, field_ident, array_structs); + fields.push(quote! { pub #field_ident: #field_ty, }); + field_inits.push(quote! { #field_ident: #init_expr, }); + pat_fields.push(quote! { #field_ident }); + } + let variant_ident = &variant.ident; + let match_pattern = quote! { #enum_ident::#variant_ident { #(#pat_fields),* } }; + (fields, field_inits, match_pattern) + } + syn::Fields::Unnamed(unnamed) => { + let mut pat_fields = Vec::new(); + for (idx, field) in unnamed.unnamed.iter().enumerate() { + let field_ident = Ident::new(&format!("_{}", idx), field.span()); + let (field_ty, init_expr) = map_field_type(enum_ident, &field.ty, &field_ident, array_structs); + fields.push(quote! { pub #field_ident: #field_ty, }); + field_inits.push(quote! { #field_ident: #init_expr, }); + pat_fields.push(quote! { #field_ident }); + } + let variant_ident = &variant.ident; + let match_pattern = quote! { #enum_ident::#variant_ident( #(#pat_fields),* ) }; + (fields, field_inits, match_pattern) + } + syn::Fields::Unit => { + let variant_ident = &variant.ident; + let match_pattern = quote! { #enum_ident::#variant_ident }; + (fields, field_inits, match_pattern) + } + } +} + +fn map_field_type( + _enum_ident: &Ident, + ty: &Type, + field_ident: &Ident, + array_structs: &mut std::collections::BTreeMap<String, proc_macro2::TokenStream>, +) -> (Type, proc_macro2::TokenStream) { + if let Some(inner) = vec_inner_type(ty) { + let inner_ident = type_ident_name(&inner).unwrap_or_else(|| "Unknown".to_string()); + let array_ident = Ident::new(&format!("{}ArrayFfi", inner_ident), field_ident.span()); + let array_struct = quote! { + #[repr(C)] + #[derive(Clone, Debug)] + pub struct #array_ident { + pub ptr: *const #inner, + pub len: usize, + } + }; + array_structs.entry(array_ident.to_string()).or_insert(array_struct); + let array_ty: Type = parse_quote!(#array_ident); + let init_expr = quote! { #array_ident { ptr: #field_ident.as_ptr(), len: #field_ident.len() } }; + return (array_ty, init_expr); + } + + let init_expr = quote! { #field_ident.clone() }; + (ty.clone(), init_expr) +} + +fn vec_inner_type(ty: &Type) -> Option<Type> { + if let Type::Path(path) = ty { + let last = path.path.segments.last()?; + if last.ident != "Vec" { + return None; + } + if let PathArguments::AngleBracketed(args) = &last.arguments { + if let Some(GenericArgument::Type(inner)) = args.args.first() { + return Some(inner.clone()); + } + } + } + None +} + +fn type_ident_name(ty: &Type) -> Option<String> { + if let Type::Path(path) = ty { + return path.path.segments.last().map(|s| s.ident.to_string()); + } + None +} + +fn to_snake_case(input: &str) -> String { + let mut out = String::new(); + for (i, ch) in input.chars().enumerate() { + if ch.is_uppercase() { + if i != 0 { + out.push('_'); + } + for lc in ch.to_lowercase() { + out.push(lc); + } + } else { + out.push(ch); + } + } + out +} + struct ArgSpec { name: Ident, ty: Type, @@ -409,6 +613,36 @@ fn build_c_wrapper( .to_compile_error(); } + if !is_primitive_type(&arg.ty) { + let (target_ty, is_mut_ref) = match &arg.ty { + Type::Reference(reference) => (&*reference.elem, reference.mutability.is_some()), + _ => { + return syn::Error::new(arg.ty.span(), "Object inputs must be references") + .to_compile_error(); + } + }; + + let ptr_ty = if is_mut_ref { + quote! { *mut #target_ty } + } else { + quote! { *const #target_ty } + }; + + wrapper_inputs.push(quote! { #name: #ptr_ty }); + conversions.push(quote! { + if #name.is_null() { + return crate::scripting::native::DropbearNativeError::NullPointer.code(); + } + }); + if is_mut_ref { + conversions.push(quote! { let #name = unsafe { &mut *#name }; }); + } else { + conversions.push(quote! { let #name = unsafe { &*#name }; }); + } + call_args.push(quote! { #name }); + continue; + } + let ty = &arg.ty; wrapper_inputs.push(quote! { #name: #ty }); call_args.push(quote! { #name }); @@ -577,8 +811,35 @@ fn build_kotlin_wrapper( } if !is_primitive_type(&arg.ty) { - return syn::Error::new(arg.ty.span(), "JNI export only supports primitive arguments, String, entities, or define(...) pointers") - .to_compile_error(); + wrapper_inputs.push(quote! { #name: #jni_path::objects::JObject }); + let (target_ty, is_mut_ref) = match &arg.ty { + Type::Reference(reference) => (&*reference.elem, reference.mutability.is_some()), + _ => (&arg.ty, false), + }; + + let value_name = Ident::new(&format!("{}_value", name), name.span()); + conversions.push(quote! { + let #value_name = match crate::scripting::jni::utils::FromJObject::from_jobject(&mut env, &#name) { + Ok(v) => v, + Err(e) => { + let _ = env.throw_new("java/lang/RuntimeException", format!("Failed to convert object: {:?}", e)); + return crate::ffi_error_return!(); + } + }; + }); + + if matches!(&arg.ty, Type::Reference(_)) { + if is_mut_ref { + conversions.push(quote! { let #name = &mut #value_name; }); + } else { + conversions.push(quote! { let #name = &#value_name; }); + } + call_args.push(quote! { #name }); + } else { + conversions.push(quote! { let #name: #target_ty = #value_name; }); + call_args.push(quote! { #name }); + } + continue; } let jni_ty = jni_param_type(&arg.ty, &jni_path); @@ -29,9 +29,10 @@ fn generate_c_header() -> anyhow::Result<()> { let src_dir = manifest_dir.join("src"); let mut functions = Vec::new(); let mut structs = std::collections::HashMap::new(); - collect_exported_functions(&src_dir, &mut functions, &mut structs)?; + let mut enums = Vec::new(); + collect_exported_functions(&src_dir, &mut functions, &mut structs, &mut enums)?; - let header = render_header(&functions, &structs); + let header = render_header(&functions, &structs, &enums); std::fs::write(&output_path, header)?; Ok(()) @@ -54,18 +55,20 @@ fn collect_exported_functions( dir: &std::path::Path, out: &mut Vec<ExportedFunction>, structs: &mut std::collections::HashMap<String, StructDef>, + enums: &mut Vec<EnumDef>, ) -> anyhow::Result<()> { if dir.is_dir() { for entry in std::fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { - collect_exported_functions(&path, out, structs)?; + collect_exported_functions(&path, out, structs, enums)?; } else if path.extension().and_then(|s| s.to_str()) == Some("rs") { let content = std::fs::read_to_string(&path)?; let file = syn::parse_file(&content)?; extract_exports_from_file(&file, out, structs)?; extract_structs_from_file(&file, structs)?; + extract_repr_c_enums_from_file(&file, enums)?; } } } @@ -102,6 +105,8 @@ fn extract_exports_from_file( "uint64_t".to_string() } else if let Some(define_ty) = define_ty { type_to_c(&define_ty, true) + } else if is_object_input(&pat_ty.ty) { + object_input_to_c(&pat_ty.ty) } else { type_to_c(&pat_ty.ty, false) }; @@ -136,6 +141,59 @@ struct StructDef { is_repr_c: bool, } +#[derive(Debug)] +struct EnumDef { + name: String, + variants: Vec<EnumVariantDef>, +} + +#[derive(Debug)] +struct EnumVariantDef { + name: String, + fields: Vec<ExportParam>, +} + +fn extract_repr_c_enums_from_file( + file: &syn::File, + enums: &mut Vec<EnumDef>, +) -> anyhow::Result<()> { + for item in &file.items { + if let syn::Item::Enum(enm) = item { + if !has_repr_c_enum_attr(&enm.attrs) { + continue; + } + let mut variants = Vec::new(); + for variant in &enm.variants { + let mut fields = Vec::new(); + match &variant.fields { + syn::Fields::Named(named) => { + for field in &named.named { + let name = field + .ident + .as_ref() + .map(|i| i.to_string()) + .unwrap_or_else(|| "field".to_string()); + let ty = type_to_c(&field.ty, false); + fields.push(ExportParam { name, ty }); + } + } + syn::Fields::Unnamed(unnamed) => { + for (idx, field) in unnamed.unnamed.iter().enumerate() { + let name = format!("_{}", idx); + let ty = type_to_c(&field.ty, false); + fields.push(ExportParam { name, ty }); + } + } + syn::Fields::Unit => {} + } + variants.push(EnumVariantDef { name: variant.ident.to_string(), fields }); + } + enums.push(EnumDef { name: enm.ident.to_string(), variants }); + } + } + Ok(()) +} + fn extract_structs_from_file( file: &syn::File, structs: &mut std::collections::HashMap<String, StructDef>, @@ -338,6 +396,10 @@ fn type_to_c(ty: &syn::Type, for_output: bool) -> String { let mutability = if reference.mutability.is_some() { "" } else { "const " }; return format!("{}{}*", mutability, inner); } + if let Some(inner) = vec_inner_type(ty) { + return array_struct_name_from_type(&inner); + } + if let syn::Type::Path(path) = ty { let ident = path.path.segments.last().map(|s| s.ident.to_string()).unwrap_or_else(|| "void".to_string()); return match ident.as_str() { @@ -350,7 +412,7 @@ fn type_to_c(ty: &syn::Type, for_output: bool) -> String { "i64" => "int64_t".to_string(), "u64" => "uint64_t".to_string(), "isize" => "intptr_t".to_string(), - "usize" => "uintptr_t".to_string(), + "usize" => "size_t".to_string(), "f32" => "float".to_string(), "f64" => "double".to_string(), "bool" => "bool".to_string(), @@ -368,21 +430,74 @@ fn type_to_c(ty: &syn::Type, for_output: bool) -> String { "void".to_string() } +fn vec_inner_type(ty: &syn::Type) -> Option<syn::Type> { + if let syn::Type::Path(path) = ty { + let last = path.path.segments.last()?; + if last.ident != "Vec" { + return None; + } + if let syn::PathArguments::AngleBracketed(args) = &last.arguments { + if let Some(syn::GenericArgument::Type(inner)) = args.args.first() { + return Some(inner.clone()); + } + } + } + None +} + +fn type_name_from_type(ty: &syn::Type) -> Option<String> { + if let syn::Type::Path(path) = ty { + return path.path.segments.last().map(|s| s.ident.to_string()); + } + None +} + +fn array_struct_name_from_type(ty: &syn::Type) -> String { + if let Some(inner) = vec_inner_type(ty) { + let inner_name = array_struct_name_from_type(&inner); + return format!("{}ArrayFfi", inner_name); + } + + let name = type_name_from_type(ty).unwrap_or_else(|| "Unknown".to_string()); + format!("{}ArrayFfi", name) +} + fn render_header( funcs: &[ExportedFunction], structs: &std::collections::HashMap<String, StructDef>, + enums: &[EnumDef], ) -> String { let mut out = String::new(); out.push_str("#ifndef DROPBEAR_H\n"); out.push_str("#define DROPBEAR_H\n\n"); out.push_str("#include <stdbool.h>\n"); out.push_str("#include <stdint.h>\n\n"); + out.push_str("#include <stddef.h>\n\n"); + + let mut emitted_arrays = std::collections::HashSet::new(); + for enm in enums { + emit_repr_c_enum(enm, &mut emitted_arrays, &mut out); + } let mut needed = std::collections::HashSet::new(); for func in funcs { if let Some(out_ty) = &func.out_type { if is_custom_type(out_ty) { needed.insert(out_ty.clone()); + } else if is_opaque_ptr_name(out_ty) { + needed.insert(out_ty.clone()); + } + } + for param in &func.params { + if is_opaque_ptr_name(¶m.ty) { + needed.insert(param.ty.clone()); + } + if let Some(base) = base_type_name(¶m.ty) { + if is_custom_type(&base) { + needed.insert(base); + } else if is_opaque_ptr_name(&base) { + needed.insert(base); + } } } } @@ -408,6 +523,66 @@ fn render_header( out } +fn emit_repr_c_enum( + enm: &EnumDef, + emitted_arrays: &mut std::collections::HashSet<String>, + out: &mut String, +) { + let tag_name = format!("{}Tag", enm.name); + let data_name = format!("{}Data", enm.name); + let ffi_name = format!("{}Ffi", enm.name); + + for var in &enm.variants { + for field in &var.fields { + if is_array_type(&field.ty) { + emit_array_struct(&field.ty, &std::collections::HashMap::new(), emitted_arrays, out); + } + } + } + + out.push_str(&format!("typedef enum {} {{\n", tag_name)); + for (idx, var) in enm.variants.iter().enumerate() { + out.push_str(&format!(" {}_{} = {},\n", tag_name, var.name, idx)); + } + out.push_str(&format!("}} {};\n\n", tag_name)); + + for var in &enm.variants { + let struct_name = format!("{}{}", enm.name, var.name); + out.push_str(&format!("typedef struct {} {{\n", struct_name)); + for field in &var.fields { + out.push_str(&format!(" {} {};\n", field.ty, field.name)); + } + out.push_str(&format!("}} {};\n\n", struct_name)); + } + + out.push_str(&format!("typedef union {} {{\n", data_name)); + for var in &enm.variants { + let struct_name = format!("{}{}", enm.name, var.name); + out.push_str(&format!(" {} {};\n", struct_name, var.name)); + } + out.push_str(&format!("}} {};\n\n", data_name)); + + out.push_str(&format!("typedef struct {} {{\n", ffi_name)); + out.push_str(&format!(" {} tag;\n", tag_name)); + out.push_str(&format!(" {} data;\n", data_name)); + out.push_str(&format!("}} {};\n\n", ffi_name)); +} + +fn has_repr_c_enum_attr(attrs: &[syn::Attribute]) -> bool { + for attr in attrs { + let path = attr.path(); + if path.segments.last().map(|s| s.ident == "repr_c_enum").unwrap_or(false) { + return true; + } + if path.segments.iter().any(|s| s.ident == "dropbear_macro") + && path.segments.last().map(|s| s.ident == "repr_c_enum").unwrap_or(false) + { + return true; + } + } + false +} + fn has_repr_c(attrs: &[syn::Attribute]) -> bool { for attr in attrs { if !attr.path().is_ident("repr") { @@ -427,18 +602,83 @@ fn is_custom_type(ty: &str) -> bool { if ty.ends_with('*') { return false; } + if is_opaque_ptr_name(ty) { + return false; + } !is_builtin_c_type(ty) } +fn base_type_name(ty: &str) -> Option<String> { + let mut t = ty.trim().to_string(); + if t.starts_with("const ") { + t = t.trim_start_matches("const ").trim().to_string(); + } + if t.ends_with('*') { + t = t.trim_end_matches('*').trim().to_string(); + return Some(t); + } + None +} + +fn is_object_input(ty: &syn::Type) -> bool { + let inner = peel_reference(ty); + if is_string_type(inner) || is_primitive_type(inner) { + return false; + } + !is_define_or_entity_like(inner) +} + +fn object_input_to_c(ty: &syn::Type) -> String { + match ty { + syn::Type::Reference(reference) => { + let inner = type_to_c(&reference.elem, false); + let mutability = if reference.mutability.is_some() { "" } else { "const " }; + format!("{}{}*", mutability, inner) + } + _ => type_to_c(ty, false), + } +} + +fn is_define_or_entity_like(_ty: &syn::Type) -> bool { + false +} + +fn is_string_type(ty: &syn::Type) -> bool { + matches!(ty, syn::Type::Path(path) if path.path.segments.last().map(|s| s.ident == "String").unwrap_or(false)) +} + +fn is_primitive_type(ty: &syn::Type) -> bool { + matches!(ty, syn::Type::Path(path) if { + let ident = path.path.segments.last().map(|s| s.ident.to_string()).unwrap_or_default(); + matches!( + ident.as_str(), + "i8" | "u8" | "i16" | "u16" | "i32" | "u32" | "i64" | "u64" | + "isize" | "usize" | "f32" | "f64" | "bool" + ) + }) +} + +fn peel_reference<'a>(ty: &'a syn::Type) -> &'a syn::Type { + if let syn::Type::Reference(reference) = ty { + &reference.elem + } else { + ty + } +} + fn is_builtin_c_type(ty: &str) -> bool { matches!( ty, "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" | "uint32_t" | "int64_t" | "uint64_t" | "intptr_t" | "uintptr_t" | "bool" | "float" | - "double" | "char" | "char*" | "const char*" + "double" | "char" | "char*" | "const char*" | "void*" ) } +fn is_opaque_ptr_name(name: &str) -> bool { + name.ends_with("Ptr") +} + fn emit_structs_recursive( name: &str, structs: &std::collections::HashMap<String, StructDef>, @@ -449,8 +689,23 @@ fn emit_structs_recursive( return; } + if is_array_type(name) { + emit_array_struct(name, structs, emitted, out); + return; + } + + if is_opaque_ptr_name(name) { + out.push_str(&format!("typedef void* {};\n\n", name)); + emitted.insert(name.to_string()); + return; + } + if let Some(def) = structs.get(name) { for field in &def.fields { + if is_array_type(&field.ty) { + emit_array_struct(&field.ty, structs, emitted, out); + continue; + } if is_custom_type(&field.ty) { emit_structs_recursive(&field.ty, structs, emitted, out); } @@ -471,3 +726,78 @@ fn emit_structs_recursive( emitted.insert(name.to_string()); } } + +fn is_array_type(ty: &str) -> bool { + ty.ends_with("ArrayFfi") +} + +fn emit_array_struct( + name: &str, + structs: &std::collections::HashMap<String, StructDef>, + emitted: &mut std::collections::HashSet<String>, + out: &mut String, +) { + if emitted.contains(name) { + return; + } + let elem = name.trim_end_matches("ArrayFfi"); + + if is_array_type(elem) { + emit_array_struct(elem, structs, emitted, out); + } + + if is_builtin_rust_primitive(elem) { + let c_elem = map_primitive_name(elem); + if !emitted.contains(elem) { + emitted.insert(elem.to_string()); + } + out.push_str(&format!("typedef struct {} {{\n", name)); + out.push_str(&format!(" const {}* ptr;\n", c_elem)); + out.push_str(" size_t len;\n"); + out.push_str(&format!("}} {};\n\n", name)); + emitted.insert(name.to_string()); + return; + } + + if !emitted.contains(elem) { + if structs.contains_key(elem) { + emit_structs_recursive(elem, structs, emitted, out); + } else { + out.push_str(&format!("typedef struct {} {};// opaque\n\n", elem, elem)); + emitted.insert(elem.to_string()); + } + } + + out.push_str(&format!("typedef struct {} {{\n", name)); + out.push_str(&format!(" const {}* ptr;\n", elem)); + out.push_str(" size_t len;\n"); + out.push_str(&format!("}} {};\n\n", name)); + emitted.insert(name.to_string()); +} + +fn is_builtin_rust_primitive(name: &str) -> bool { + matches!( + name, + "i8" | "u8" | "i16" | "u16" | "i32" | "u32" | "i64" | "u64" | + "isize" | "usize" | "f32" | "f64" | "bool" + ) +} + +fn map_primitive_name(name: &str) -> &'static str { + match name { + "i8" => "int8_t", + "u8" => "uint8_t", + "i16" => "int16_t", + "u16" => "uint16_t", + "i32" => "int32_t", + "u32" => "uint32_t", + "i64" => "int64_t", + "u64" => "uint64_t", + "isize" => "intptr_t", + "usize" => "size_t", + "f32" => "float", + "f64" => "double", + "bool" => "bool", + _ => "void", + } +} @@ -1,91 +0,0 @@ -pub mod shared { - use dropbear_engine::asset::{AssetHandle, AssetRegistry}; - use crate::scripting::result::DropbearNativeResult; - - pub fn is_model_handle( - registry: &AssetRegistry, - handle: u64, - ) -> DropbearNativeResult<bool> { - let handle = AssetHandle::new(handle); - let result = registry.is_model(handle); - Ok(result) - } - - pub fn is_texture_handle( - registry: &AssetRegistry, - handle: u64, - ) -> DropbearNativeResult<bool> { - let handle = AssetHandle::new(handle); - let result = registry.is_material(handle); - Ok(result) - } -} - -pub mod jni { - #![allow(non_snake_case)] - use jni::sys::{jboolean, jlong}; - use jni::objects::JClass; - use dropbear_engine::asset::AssetRegistry; - use jni::JNIEnv; - use crate::asset::shared::{is_model_handle, is_texture_handle}; - use crate::convert_ptr; - - #[unsafe(no_mangle)] - pub extern "system" fn Java_com_dropbear_asset_AssetHandleNative_isModelHandle( - _env: JNIEnv, - _class: JClass, - asset_registry_ptr: jlong, - handle: jlong, - ) -> jboolean { - let asset = convert_ptr!(asset_registry_ptr => AssetRegistry); - let result = is_model_handle(asset, handle as u64); - match result { - Ok(val) => val as jboolean, - Err(e) => { - crate::ffi_error_return!("[ERROR] {}", e) - } - } - } - - #[unsafe(no_mangle)] - pub extern "system" fn Java_com_dropbear_asset_AssetHandleNative_isTextureHandle( - _env: JNIEnv, - _class: JClass, - asset_registry_ptr: jlong, - handle: jlong, - ) -> jboolean { - let asset = convert_ptr!(asset_registry_ptr => AssetRegistry); - let result = is_texture_handle(asset, handle as u64); - match result { - Ok(val) => val as jboolean, - Err(e) => { - crate::ffi_error_return!("[ERROR] {}", e) - } - } - } -} - -#[dropbear_macro::impl_c_api] -pub mod native { - use dropbear_engine::asset::AssetRegistry; - use crate::asset::shared::{is_model_handle, is_texture_handle}; - use crate::convert_ptr; - use crate::ptr::AssetRegistryPtr; - use crate::scripting::result::DropbearNativeResult; - - pub fn dropbear_is_model_handle( - asset_registry_ptr: AssetRegistryPtr, - handle: u64, - ) -> DropbearNativeResult<bool> { - let asset = convert_ptr!(asset_registry_ptr => AssetRegistry); - is_model_handle(asset, handle) - } - - pub fn dropbear_is_texture_handle( - asset_registry_ptr: AssetRegistryPtr, - handle: u64, - ) -> DropbearNativeResult<bool> { - let asset = convert_ptr!(asset_registry_ptr => AssetRegistry); - is_texture_handle(asset, handle) - } -} @@ -0,0 +1,37 @@ +pub mod texture; +pub mod model; + +use dropbear_engine::asset::AssetKind; +use crate::ptr::{AssetRegistryPtr, AssetRegistryUnwrapped}; +use crate::scripting::result::DropbearNativeResult; + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.DropbearEngineNative", func = "getAsset"), + c(name = "dropbear_engine_get_asset") +)] +fn dropbear_asset_get_asset( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + label: String, + kind: &AssetKind, +) -> DropbearNativeResult<Option<u64>> { + let reader = asset.read(); + match kind { + AssetKind::Texture => { + let result = reader.get_texture_handle_from_label(&label); + if let Some(handle) = result { + Ok(Some(handle.id)) + } else { + Ok(None) + } + } + AssetKind::Model => { + let result = reader.get_model_handle_from_label(&label); + if let Some(handle) = result { + Ok(Some(handle.id)) + } else { + Ok(None) + } + } + } +} @@ -0,0 +1,351 @@ +use crate::scripting::native::DropbearNativeError; +use crate::scripting::result::DropbearNativeResult; +use crate::types::{NQuaternion, NVector2, NVector3, NVector4}; +use dropbear_engine::asset::Handle; +use dropbear_engine::model::{Animation, AnimationChannel, AnimationInterpolation, ChannelValues, Material, Mesh, ModelVertex, Node, NodeTransform, Skin}; +use dropbear_engine::texture::Texture; +use crate::ptr::{AssetRegistryPtr, AssetRegistryUnwrapped}; + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NModelVertex { + pub position: NVector3, + pub normal: NVector3, + pub tangent: NVector4, + pub tex_coords0: NVector2, + pub tex_coords1: NVector2, + pub colour0: NVector4, + pub joints0: Vec<i32>, + pub weights0: NVector4, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NMesh { + pub name: String, + pub num_elements: i32, + pub material_index: i32, + pub vertices: Vec<NModelVertex>, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NMaterial { + pub name: String, + pub diffuse_texture: u64, + pub normal_texture: u64, + pub tint: NVector4, + pub emissive_factor: NVector3, + pub metallic_factor: f32, + pub roughness_factor: f32, + pub alpha_cutoff: Option<f32>, + pub double_sided: bool, + pub occlusion_strength: f32, + pub normal_scale: f32, + pub uv_tiling: NVector2, + pub emissive_texture: Option<u64>, + pub metallic_roughness_texture: Option<u64>, + pub occlusion_texture: Option<u64>, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NNodeTransform { + pub translation: NVector3, + pub rotation: NQuaternion, + pub scale: NVector3, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NNode { + pub name: String, + pub parent: Option<i32>, + pub children: Vec<i32>, + pub transform: NNodeTransform, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NSkin { + pub name: String, + pub joints: Vec<i32>, + pub inverse_bind_matrices: Vec<Vec<f64>>, + pub skeleton_root: Option<i32>, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NAnimation { + pub name: String, + pub channels: Vec<NAnimationChannel>, + pub duration: f32, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct NAnimationChannel { + pub target_node: i32, + pub times: Vec<f64>, + pub values: NChannelValues, + pub interpolation: NAnimationInterpolation, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub enum NAnimationInterpolation { + Linear, + Step, + CubicSpline, +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub enum NChannelValues { + Translations { values: Vec<NVector3> }, + Rotations { values: Vec<NQuaternion> }, + Scales { values: Vec<NVector3> }, +} + +fn texture_handle_id( + registry: &dropbear_engine::asset::AssetRegistry, + texture: &Texture, +) -> u64 { + texture + .hash + .and_then(|hash| registry.texture_handle_by_hash(hash).map(|h| h.id)) + .unwrap_or(0) +} + +fn map_vertex(vertex: &ModelVertex) -> NModelVertex { + NModelVertex { + position: NVector3::from(vertex.position), + normal: NVector3::from(vertex.normal), + tangent: NVector4::from(vertex.tangent), + tex_coords0: NVector2::from(vertex.tex_coords0), + tex_coords1: NVector2::from(vertex.tex_coords1), + colour0: NVector4::from(vertex.colour0), + joints0: vertex.joints0.iter().map(|v| *v as i32).collect(), + weights0: NVector4::from(vertex.weights0), + } +} + +fn map_mesh(mesh: &Mesh) -> NMesh { + NMesh { + name: mesh.name.clone(), + num_elements: mesh.num_elements as i32, + material_index: mesh.material as i32, + vertices: mesh.vertices.iter().map(map_vertex).collect(), + } +} + +fn map_material( + registry: &dropbear_engine::asset::AssetRegistry, + material: &Material, +) -> NMaterial { + NMaterial { + name: material.name.clone(), + diffuse_texture: texture_handle_id(registry, &material.diffuse_texture), + normal_texture: texture_handle_id(registry, &material.normal_texture), + tint: NVector4::from(material.tint), + emissive_factor: NVector3::from(material.emissive_factor), + metallic_factor: material.metallic_factor, + roughness_factor: material.roughness_factor, + alpha_cutoff: material.alpha_cutoff, + double_sided: material.double_sided, + occlusion_strength: material.occlusion_strength, + normal_scale: material.normal_scale, + uv_tiling: NVector2::from(material.uv_tiling), + emissive_texture: material + .emissive_texture + .as_ref() + .map(|tex| texture_handle_id(registry, tex)) + .filter(|id| *id != 0), + metallic_roughness_texture: material + .metallic_roughness_texture + .as_ref() + .map(|tex| texture_handle_id(registry, tex)) + .filter(|id| *id != 0), + occlusion_texture: material + .occlusion_texture + .as_ref() + .map(|tex| texture_handle_id(registry, tex)) + .filter(|id| *id != 0), + } +} + +fn map_node_transform(transform: &NodeTransform) -> NNodeTransform { + NNodeTransform { + translation: NVector3::from(transform.translation), + rotation: NQuaternion::from(transform.rotation), + scale: NVector3::from(transform.scale), + } +} + +fn map_node(node: &Node) -> NNode { + NNode { + name: node.name.clone(), + parent: node.parent.map(|v| v as i32), + children: node.children.iter().map(|v| *v as i32).collect(), + transform: map_node_transform(&node.transform), + } +} + +fn map_skin(skin: &Skin) -> NSkin { + let inverse_bind_matrices = skin + .inverse_bind_matrices + .iter() + .map(|matrix| matrix.to_cols_array().iter().map(|v| *v as f64).collect()) + .collect(); + + NSkin { + name: skin.name.clone(), + joints: skin.joints.iter().map(|v| *v as i32).collect(), + inverse_bind_matrices, + skeleton_root: skin.skeleton_root.map(|v| v as i32), + } +} + +fn map_interpolation(value: &AnimationInterpolation) -> NAnimationInterpolation { + match value { + AnimationInterpolation::Linear => NAnimationInterpolation::Linear, + AnimationInterpolation::Step => NAnimationInterpolation::Step, + AnimationInterpolation::CubicSpline => NAnimationInterpolation::CubicSpline, + } +} + +fn map_channel_values(values: &ChannelValues) -> NChannelValues { + match values { + ChannelValues::Translations(list) => NChannelValues::Translations { + values: list.iter().map(|v| NVector3::from(*v)).collect(), + }, + ChannelValues::Rotations(list) => NChannelValues::Rotations { + values: list.iter().map(|v| NQuaternion::from(*v)).collect(), + }, + ChannelValues::Scales(list) => NChannelValues::Scales { + values: list.iter().map(|v| NVector3::from(*v)).collect(), + }, + } +} + +fn map_animation_channel(channel: &AnimationChannel) -> NAnimationChannel { + NAnimationChannel { + target_node: channel.target_node as i32, + times: channel.times.iter().map(|v| *v as f64).collect(), + values: map_channel_values(&channel.values), + interpolation: map_interpolation(&channel.interpolation), + } +} + +fn map_animation(animation: &Animation) -> NAnimation { + NAnimation { + name: animation.name.clone(), + channels: animation.channels.iter().map(map_animation_channel).collect(), + duration: animation.duration, + } +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getLabel"), + c(name = "dropbear_asset_model_get_label") +)] +fn dropbear_asset_model_get_label( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<String> { + let label = asset + .read() + .get_label_from_model_handle(Handle::new(model_handle)) + .ok_or_else(|| DropbearNativeError::InvalidHandle)?; + Ok(label) +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getMeshes"), + c(name = "dropbear_asset_model_get_meshes") +)] +fn dropbear_asset_model_get_meshes( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<Vec<NMesh>> { + let reader = asset.read(); + let model = reader + .get_model(Handle::new(model_handle)) + .ok_or(DropbearNativeError::InvalidHandle)?; + + Ok(model.meshes.iter().map(map_mesh).collect()) +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getMaterials"), + c(name = "dropbear_asset_model_get_materials") +)] +fn dropbear_asset_model_get_materials( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<Vec<NMaterial>> { + let reader = asset.read(); + let model = reader + .get_model(Handle::new(model_handle)) + .ok_or(DropbearNativeError::InvalidHandle)?; + + Ok(model + .materials + .iter() + .map(|mat| map_material(&reader, mat)) + .collect()) +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getSkins"), + c(name = "dropbear_asset_model_get_skins") +)] +pub fn dropbear_asset_model_get_skins( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<Vec<NSkin>> { + let reader = asset.read(); + let model = reader + .get_model(Handle::new(model_handle)) + .ok_or(DropbearNativeError::InvalidHandle)?; + + Ok(model.skins.iter().map(map_skin).collect()) +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getAnimations"), + c(name = "dropbear_asset_model_get_animations") +)] +pub fn dropbear_asset_model_get_animations( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<Vec<NAnimation>> { + let reader = asset.read(); + let model = reader + .get_model(Handle::new(model_handle)) + .ok_or(DropbearNativeError::InvalidHandle)?; + + Ok(model.animations.iter().map(map_animation).collect()) +} + +#[dropbear_macro::export( + kotlin(class = "com.dropbear.asset.ModelNative", func = "getNodes"), + c(name = "dropbear_asset_model_get_nodes") +)] +pub fn dropbear_asset_model_get_nodes( + #[dropbear_macro::define(AssetRegistryPtr)] + asset: &AssetRegistryUnwrapped, + model_handle: u64, +) -> DropbearNativeResult<Vec<NNode>> { + let reader = asset.read(); + let model = reader + .get_model(Handle::new(model_handle)) + .ok_or(DropbearNativeError::InvalidHandle)?; + + Ok(model.nodes.iter().map(map_node).collect()) +} @@ -0,0 +1,83 @@ +pub mod shared { + use dropbear_engine::asset::{AssetHandle, AssetRegistry}; + use crate::scripting::native::DropbearNativeError; + use crate::scripting::result::DropbearNativeResult; + + pub fn get_texture_name( + asset_registry: &AssetRegistry, + handle: u64, + ) -> DropbearNativeResult<String> { + let texture = asset_registry + .get_material(AssetHandle::new(handle)) + .ok_or_else(|| DropbearNativeError::NoSuchHandle)?; + + Ok(texture.name.clone()) + } +} + +pub mod jni { + #![allow(non_snake_case)] + use jni::JNIEnv; + use jni::sys::{jlong, jstring}; + use dropbear_engine::asset::AssetRegistry; + use jni::objects::JClass; + use crate::asset::texture::shared::get_texture_name; + use crate::scripting::native::DropbearNativeError; + + #[unsafe(no_mangle)] + pub extern "system" fn Java_com_dropbear_asset_TextureHandleNative_getTextureName( + env: JNIEnv, + _class: JClass, + asset_registry_ptr: jlong, + handle: jlong, + ) -> jstring { + let asset_registry = crate::convert_ptr!(asset_registry_ptr => AssetRegistry); + let result = get_texture_name(asset_registry, handle as u64); + match result { + Ok(name) => { + let output = env.new_string(name).map_err(|_| DropbearNativeError::JNIFailedToCreateObject); + match output { + Ok(jstr) => jstr.into_raw(), + Err(e) => { + crate::ffi_error_return!("[ERROR] Failed to create Java string: {}", e) + } + } + } + Err(e) => { + crate::ffi_error_return!("[ERROR] {}", e) + } + } + } +} + +#[dropbear_macro::impl_c_api] +pub mod native { + use std::ffi::CString; + use crate::ptr::AssetRegistryPtr; + use crate::scripting::native::DropbearNativeError; + use crate::scripting::result::DropbearNativeResult; + use std::ffi::c_char; + use dropbear_engine::asset::AssetRegistry; + use crate::asset::texture::shared::get_texture_name; + + pub fn dropbear_get_texture_name( + asset_registry_ptr: AssetRegistryPtr, + handle: u64, + ) -> DropbearNativeResult<*mut c_char> { + let asset_registry = crate::convert_ptr!(asset_registry_ptr => AssetRegistry); + + let result = get_texture_name(asset_registry, handle) + .map(|name| { + match CString::new(name) { + Ok(c_str) => { + Ok(c_str.into_raw()) + }, + Err(_) => { + Err(DropbearNativeError::CStringError) + } + } + })?; + + result + } +} @@ -1,38 +0,0 @@ -pub mod texture; -pub mod model; - -use dropbear_engine::asset::AssetKind; -use crate::pointer_convert; -use crate::ptr::AssetRegistryUnwrapped; -use crate::scripting::result::DropbearNativeResult; - -/** - * Fetches the asset_old information from the internal AssetRegistry (located in - * `dropbear_engine::asset_old::AssetRegistry`) from the provided label. - */ -pub fn dropbear_asset_get_asset( - asset_ptr: u64, - label: String, - kind: AssetKind, -) -> DropbearNativeResult<Option<u64>> { - let asset = pointer_convert!(asset_ptr => AssetRegistryUnwrapped); - let reader = asset.read(); - match kind { - AssetKind::Texture => { - let result = reader.get_texture_handle_from_label(&label); - if let Some(handle) = result { - Ok(Some(handle.id)) - } else { - Ok(None) - } - } - AssetKind::Model => { - let result = reader.get_model_handle_from_label(&label); - if let Some(handle) = result { - Ok(Some(handle.id)) - } else { - Ok(None) - } - } - } -} @@ -1,345 +0,0 @@ -use crate::pointer_convert; -use crate::ptr::AssetRegistryUnwrapped; -use crate::scripting::native::DropbearNativeError; -use crate::scripting::result::DropbearNativeResult; -use crate::types::{NQuaternion, NVector2, NVector3, NVector4}; -use dropbear_engine::asset::Handle; -use dropbear_engine::model::{Animation, AnimationChannel, AnimationInterpolation, ChannelValues, Material, Mesh, ModelVertex, Node, NodeTransform, Skin}; -use dropbear_engine::texture::Texture; - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NModelVertex { - pub position: NVector3, - pub normal: NVector3, - pub tangent: NVector4, - pub tex_coords0: NVector2, - pub tex_coords1: NVector2, - pub colour0: NVector4, - pub joints0: Vec<i32>, - pub weights0: NVector4, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NMesh { - pub name: String, - pub num_elements: i32, - pub material_index: i32, - pub vertices: Vec<NModelVertex>, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NMaterial { - pub name: String, - pub diffuse_texture: u64, - pub normal_texture: u64, - pub tint: NVector4, - pub emissive_factor: NVector3, - pub metallic_factor: f32, - pub roughness_factor: f32, - pub alpha_cutoff: Option<f32>, - pub double_sided: bool, - pub occlusion_strength: f32, - pub normal_scale: f32, - pub uv_tiling: NVector2, - pub emissive_texture: Option<u64>, - pub metallic_roughness_texture: Option<u64>, - pub occlusion_texture: Option<u64>, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NNodeTransform { - pub translation: NVector3, - pub rotation: NQuaternion, - pub scale: NVector3, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NNode { - pub name: String, - pub parent: Option<i32>, - pub children: Vec<i32>, - pub transform: NNodeTransform, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NSkin { - pub name: String, - pub joints: Vec<i32>, - pub inverse_bind_matrices: Vec<Vec<f64>>, - pub skeleton_root: Option<i32>, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NAnimation { - pub name: String, - pub channels: Vec<NAnimationChannel>, - pub duration: f32, -} - -#[derive(Clone, Debug, uniffi::Record)] -pub struct NAnimationChannel { - pub target_node: i32, - pub times: Vec<f64>, - pub values: NChannelValues, - pub interpolation: NAnimationInterpolation, -} - -#[derive(Clone, Debug, uniffi::Enum)] -pub enum NAnimationInterpolation { - Linear, - Step, - CubicSpline, -} - -#[derive(Clone, Debug, uniffi::Enum)] -pub enum NChannelValues { - Translations { values: Vec<NVector3> }, - Rotations { values: Vec<NQuaternion> }, - Scales { values: Vec<NVector3> }, -} - -fn texture_handle_id( - registry: &dropbear_engine::asset::AssetRegistry, - texture: &Texture, -) -> u64 { - texture - .hash() - .and_then(|hash| registry.texture_handle_by_hash(hash).map(|h| h.id)) - .unwrap_or(0) -} - -fn to_nvector3(v: glam::Vec3) -> NVector3 { - NVector3::from([v.x, v.y, v.z]) -} - -fn to_nvector2(v: [f32; 2]) -> NVector2 { - NVector2::from(v) -} - -fn to_nvector4(v: [f32; 4]) -> NVector4 { - NVector4::from(v) -} - -fn to_nquaternion(q: glam::Quat) -> NQuaternion { - NQuaternion { - x: q.x as f64, - y: q.y as f64, - z: q.z as f64, - w: q.w as f64, - } -} - -fn map_vertex(vertex: &ModelVertex) -> NModelVertex { - NModelVertex { - position: NVector3::from(vertex.position), - normal: NVector3::from(vertex.normal), - tangent: to_nvector4(vertex.tangent), - tex_coords0: to_nvector2(vertex.tex_coords0), - tex_coords1: to_nvector2(vertex.tex_coords1), - colour0: to_nvector4(vertex.colour0), - joints0: vertex.joints0.iter().map(|v| *v as i32).collect(), - weights0: to_nvector4(vertex.weights0), - } -} - -fn map_mesh(mesh: &Mesh) -> NMesh { - NMesh { - name: mesh.name.clone(), - num_elements: mesh.num_elements as i32, - material_index: mesh.material as i32, - vertices: mesh.vertices.iter().map(map_vertex).collect(), - } -} - -fn map_material( - registry: &dropbear_engine::asset::AssetRegistry, - material: &Material, -) -> NMaterial { - NMaterial { - name: material.name.clone(), - diffuse_texture: texture_handle_id(registry, &material.diffuse_texture), - normal_texture: texture_handle_id(registry, &material.normal_texture), - tint: to_nvector4(material.tint), - emissive_factor: NVector3::from(material.emissive_factor), - metallic_factor: material.metallic_factor, - roughness_factor: material.roughness_factor, - alpha_cutoff: material.alpha_cutoff, - double_sided: material.double_sided, - occlusion_strength: material.occlusion_strength, - normal_scale: material.normal_scale, - uv_tiling: to_nvector2(material.uv_tiling), - emissive_texture: material - .emissive_texture - .as_ref() - .map(|tex| texture_handle_id(registry, tex)) - .filter(|id| *id != 0), - metallic_roughness_texture: material - .metallic_roughness_texture - .as_ref() - .map(|tex| texture_handle_id(registry, tex)) - .filter(|id| *id != 0), - occlusion_texture: material - .occlusion_texture - .as_ref() - .map(|tex| texture_handle_id(registry, tex)) - .filter(|id| *id != 0), - } -} - -fn map_node_transform(transform: &NodeTransform) -> NNodeTransform { - NNodeTransform { - translation: to_nvector3(transform.translation), - rotation: to_nquaternion(transform.rotation), - scale: to_nvector3(transform.scale), - } -} - -fn map_node(node: &Node) -> NNode { - NNode { - name: node.name.clone(), - parent: node.parent.map(|v| v as i32), - children: node.children.iter().map(|v| *v as i32).collect(), - transform: map_node_transform(&node.transform), - } -} - -fn map_skin(skin: &Skin) -> NSkin { - let inverse_bind_matrices = skin - .inverse_bind_matrices - .iter() - .map(|matrix| matrix.to_cols_array().iter().map(|v| *v as f64).collect()) - .collect(); - - NSkin { - name: skin.name.clone(), - joints: skin.joints.iter().map(|v| *v as i32).collect(), - inverse_bind_matrices, - skeleton_root: skin.skeleton_root.map(|v| v as i32), - } -} - -fn map_interpolation(value: &AnimationInterpolation) -> NAnimationInterpolation { - match value { - AnimationInterpolation::Linear => NAnimationInterpolation::Linear, - AnimationInterpolation::Step => NAnimationInterpolation::Step, - AnimationInterpolation::CubicSpline => NAnimationInterpolation::CubicSpline, - } -} - -fn map_channel_values(values: &ChannelValues) -> NChannelValues { - match values { - ChannelValues::Translations(list) => NChannelValues::Translations { - values: list.iter().map(|v| to_nvector3(*v)).collect(), - }, - ChannelValues::Rotations(list) => NChannelValues::Rotations { - values: list.iter().map(|v| to_nquaternion(*v)).collect(), - }, - ChannelValues::Scales(list) => NChannelValues::Scales { - values: list.iter().map(|v| to_nvector3(*v)).collect(), - }, - } -} - -fn map_animation_channel(channel: &AnimationChannel) -> NAnimationChannel { - NAnimationChannel { - target_node: channel.target_node as i32, - times: channel.times.iter().map(|v| *v as f64).collect(), - values: map_channel_values(&channel.values), - interpolation: map_interpolation(&channel.interpolation), - } -} - -fn map_animation(animation: &Animation) -> NAnimation { - NAnimation { - name: animation.name.clone(), - channels: animation.channels.iter().map(map_animation_channel).collect(), - duration: animation.duration, - } -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_label( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<String> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let label = asset - .read() - .get_label_from_model_handle(Handle::new(model_handle)) - .ok_or_else(|| DropbearNativeError::InvalidHandle)?; - Ok(label) -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_meshes( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<Vec<NMesh>> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let reader = asset.read(); - let model = reader - .get_model(Handle::new(model_handle)) - .ok_or(DropbearNativeError::InvalidHandle)?; - - Ok(model.meshes.iter().map(map_mesh).collect()) -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_materials( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<Vec<NMaterial>> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let reader = asset.read(); - let model = reader - .get_model(Handle::new(model_handle)) - .ok_or(DropbearNativeError::InvalidHandle)?; - - Ok(model - .materials - .iter() - .map(|mat| map_material(&reader, mat)) - .collect()) -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_skins( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<Vec<NSkin>> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let reader = asset.read(); - let model = reader - .get_model(Handle::new(model_handle)) - .ok_or(DropbearNativeError::InvalidHandle)?; - - Ok(model.skins.iter().map(map_skin).collect()) -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_animations( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<Vec<NAnimation>> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let reader = asset.read(); - let model = reader - .get_model(Handle::new(model_handle)) - .ok_or(DropbearNativeError::InvalidHandle)?; - - Ok(model.animations.iter().map(map_animation).collect()) -} - -#[uniffi::export] -pub fn dropbear_asset_model_get_nodes( - asset_registry: u64, - model_handle: u64, -) -> DropbearNativeResult<Vec<NNode>> { - let asset = pointer_convert!(asset_registry => AssetRegistryUnwrapped); - let reader = asset.read(); - let model = reader - .get_model(Handle::new(model_handle)) - .ok_or(DropbearNativeError::InvalidHandle)?; - - Ok(model.nodes.iter().map(map_node).collect()) -} @@ -1,83 +0,0 @@ -pub mod shared { - use dropbear_engine::asset::{AssetHandle, AssetRegistry}; - use crate::scripting::native::DropbearNativeError; - use crate::scripting::result::DropbearNativeResult; - - pub fn get_texture_name( - asset_registry: &AssetRegistry, - handle: u64, - ) -> DropbearNativeResult<String> { - let texture = asset_registry - .get_material(AssetHandle::new(handle)) - .ok_or_else(|| DropbearNativeError::NoSuchHandle)?; - - Ok(texture.name.clone()) - } -} - -pub mod jni { - #![allow(non_snake_case)] - use jni::JNIEnv; - use jni::sys::{jlong, jstring}; - use dropbear_engine::asset::AssetRegistry; - use jni::objects::JClass; - use crate::asset::texture::shared::get_texture_name; - use crate::scripting::native::DropbearNativeError; - - #[unsafe(no_mangle)] - pub extern "system" fn Java_com_dropbear_asset_TextureHandleNative_getTextureName( - env: JNIEnv, - _class: JClass, - asset_registry_ptr: jlong, - handle: jlong, - ) -> jstring { - let asset_registry = crate::convert_ptr!(asset_registry_ptr => AssetRegistry); - let result = get_texture_name(asset_registry, handle as u64); - match result { - Ok(name) => { - let output = env.new_string(name).map_err(|_| DropbearNativeError::JNIFailedToCreateObject); - match output { - Ok(jstr) => jstr.into_raw(), - Err(e) => { - crate::ffi_error_return!("[ERROR] Failed to create Java string: {}", e) - } - } - } - Err(e) => { - crate::ffi_error_return!("[ERROR] {}", e) - } - } - } -} - -#[dropbear_macro::impl_c_api] -pub mod native { - use std::ffi::CString; - use crate::ptr::AssetRegistryPtr; - use crate::scripting::native::DropbearNativeError; - use crate::scripting::result::DropbearNativeResult; - use std::ffi::c_char; - use dropbear_engine::asset::AssetRegistry; - use crate::asset::texture::shared::get_texture_name; - - pub fn dropbear_get_texture_name( - asset_registry_ptr: AssetRegistryPtr, - handle: u64, - ) -> DropbearNativeResult<*mut c_char> { - let asset_registry = crate::convert_ptr!(asset_registry_ptr => AssetRegistry); - - let result = get_texture_name(asset_registry, handle) - .map(|name| { - match CString::new(name) { - Ok(c_str) => { - Ok(c_str.into_raw()) - }, - Err(_) => { - Err(DropbearNativeError::CStringError) - } - } - })?; - - result - } -} @@ -135,7 +135,7 @@ pub mod jni { use dropbear_engine::camera::Camera; use crate::convert_jlong_to_entity; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::Vector3; + use crate::types::NVector3; #[unsafe(no_mangle)] pub extern "system" fn Java_com_dropbear_components_CameraNative_cameraExistsForEntity( @@ -163,7 +163,7 @@ pub mod jni { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); if let Ok(camera) = world.get::<&Camera>(entity) { - let eye: Vector3 = Vector3::from(camera.eye); + let eye: NVector3 = NVector3::from(camera.eye); return match eye.to_jobject(&mut env) { Ok(val) => val.into_raw(), Err(_) => std::ptr::null_mut() @@ -184,7 +184,7 @@ pub mod jni { ) { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); - let new_eye = match Vector3::from_jobject(&mut env, &eye_obj) { + let new_eye = match NVector3::from_jobject(&mut env, &eye_obj) { Ok(v) => v, Err(e) => { let _ = env.throw_new("java/lang/IllegalArgumentException", format!("Invalid Vector3d: {:?}", e)); @@ -209,7 +209,7 @@ pub mod jni { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); if let Ok(camera) = world.get::<&Camera>(entity) { - let target: Vector3 = Vector3::from(camera.target); + let target: NVector3 = NVector3::from(camera.target); return match target.to_jobject(&mut env) { Ok(val) => val.into_raw(), Err(_) => std::ptr::null_mut() @@ -230,7 +230,7 @@ pub mod jni { ) { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); - let new_target = match Vector3::from_jobject(&mut env, &target_obj) { + let new_target = match NVector3::from_jobject(&mut env, &target_obj) { Ok(v) => v, Err(_) => return, }; @@ -249,7 +249,7 @@ pub mod jni { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); if let Ok(camera) = world.get::<&Camera>(entity) { - let up = Vector3::from(camera.up); + let up = NVector3::from(camera.up); return match up.to_jobject(&mut env) { Ok(val) => val.into_raw(), Err(_) => std::ptr::null_mut() @@ -270,7 +270,7 @@ pub mod jni { ) { let world = crate::convert_ptr!(world_ptr => hecs::World); let entity = convert_jlong_to_entity!(entity_id); - let new_up = match Vector3::from_jobject(&mut env, &up_obj) { + let new_up = match NVector3::from_jobject(&mut env, &up_obj) { Ok(v) => v, Err(_) => return, }; @@ -522,7 +522,7 @@ pub mod native { use glam::DVec3; use dropbear_engine::camera::Camera; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector3; + use crate::types::NVector3; pub fn dropbear_camera_exists_for_entity( world_ptr: WorldPtr, @@ -541,12 +541,12 @@ pub mod native { pub fn dropbear_get_camera_eye( world_ptr: WorldPtr, entity_id: u64, - ) -> DropbearNativeResult<Vector3> { + ) -> DropbearNativeResult<NVector3> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; if let Ok(camera) = world.get::<&Camera>(entity) { - DropbearNativeResult::Ok(Vector3::from(camera.eye)) + DropbearNativeResult::Ok(NVector3::from(camera.eye)) } else { DropbearNativeResult::Err(DropbearNativeError::NoSuchComponent) } @@ -555,7 +555,7 @@ pub mod native { pub fn dropbear_set_camera_eye( world_ptr: WorldPtr, entity_id: u64, - value: Vector3, + value: NVector3, ) -> DropbearNativeResult<()> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; @@ -571,12 +571,12 @@ pub mod native { pub fn dropbear_get_camera_target( world_ptr: WorldPtr, entity_id: u64, - ) -> DropbearNativeResult<Vector3> { + ) -> DropbearNativeResult<NVector3> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; if let Ok(camera) = world.get::<&Camera>(entity) { - DropbearNativeResult::Ok(Vector3::from(camera.target)) + DropbearNativeResult::Ok(NVector3::from(camera.target)) } else { DropbearNativeResult::Err(DropbearNativeError::NoSuchComponent) } @@ -585,7 +585,7 @@ pub mod native { pub fn dropbear_set_camera_target( world_ptr: WorldPtr, entity_id: u64, - value: Vector3, + value: NVector3, ) -> DropbearNativeResult<()> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; @@ -601,12 +601,12 @@ pub mod native { pub fn dropbear_get_camera_up( world_ptr: WorldPtr, entity_id: u64, - ) -> DropbearNativeResult<Vector3> { + ) -> DropbearNativeResult<NVector3> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; if let Ok(camera) = world.get::<&Camera>(entity) { - DropbearNativeResult::Ok(Vector3::from(camera.up)) + DropbearNativeResult::Ok(NVector3::from(camera.up)) } else { DropbearNativeResult::Err(DropbearNativeError::NoSuchComponent) } @@ -615,7 +615,7 @@ pub mod native { pub fn dropbear_set_camera_up( world_ptr: WorldPtr, entity_id: u64, - value: Vector3, + value: NVector3, ) -> DropbearNativeResult<()> { let world = convert_ptr!(world_ptr => hecs::World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; @@ -114,7 +114,7 @@ pub mod shared { use crate::command::{CommandBuffer, WindowCommand}; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector2; + use crate::types::NVector2; use super::*; pub fn map_ordinal_to_mouse_button(ordinal: i32) -> Option<MouseButton> { @@ -145,19 +145,19 @@ pub mod shared { } } - pub fn get_mouse_position(input: &InputState) -> Vector2 { - Vector2 { + pub fn get_mouse_position(input: &InputState) -> NVector2 { + NVector2 { x: input.mouse_pos.0, y: input.mouse_pos.1, } } - pub fn get_mouse_delta(input: &InputState) -> Vector2 { - input.mouse_delta.map(Vector2::from).unwrap_or(Vector2 { x: 0.0, y: 0.0 }) + pub fn get_mouse_delta(input: &InputState) -> NVector2 { + input.mouse_delta.map(NVector2::from).unwrap_or(NVector2 { x: 0.0, y: 0.0 }) } - pub fn get_last_mouse_pos(input: &InputState) -> Vector2 { - input.last_mouse_pos.map(Vector2::from).unwrap_or(Vector2 { x: 0.0, y: 0.0 }) + pub fn get_last_mouse_pos(input: &InputState) -> NVector2 { + input.last_mouse_pos.map(NVector2::from).unwrap_or(NVector2 { x: 0.0, y: 0.0 }) } pub fn set_cursor_locked( @@ -369,7 +369,7 @@ pub mod native { use crate::convert_ptr; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector2; + use crate::types::NVector2; pub fn dropbear_print_input_state(input_ptr: InputStatePtr) -> DropbearNativeResult<()> { let input = convert_ptr!(input_ptr => InputState); @@ -382,7 +382,7 @@ pub mod native { DropbearNativeResult::Ok(super::shared::is_key_pressed(input, key_ordinal)) } - pub fn dropbear_get_mouse_position(input_ptr: InputStatePtr) -> DropbearNativeResult<Vector2> { + pub fn dropbear_get_mouse_position(input_ptr: InputStatePtr) -> DropbearNativeResult<NVector2> { let input = convert_ptr!(input_ptr => InputState); DropbearNativeResult::Ok(super::shared::get_mouse_position(input)) } @@ -392,7 +392,7 @@ pub mod native { DropbearNativeResult::Ok(super::shared::is_mouse_button_pressed(input, btn_ordinal)) } - pub fn dropbear_get_mouse_delta(input_ptr: InputStatePtr) -> DropbearNativeResult<Vector2> { + pub fn dropbear_get_mouse_delta(input_ptr: InputStatePtr) -> DropbearNativeResult<NVector2> { let input = convert_ptr!(input_ptr => InputState); DropbearNativeResult::Ok(super::shared::get_mouse_delta(input)) } @@ -412,7 +412,7 @@ pub mod native { super::shared::set_cursor_locked(input, sender, locked) } - pub fn dropbear_get_last_mouse_pos(input_ptr: InputStatePtr) -> DropbearNativeResult<Vector2> { + pub fn dropbear_get_last_mouse_pos(input_ptr: InputStatePtr) -> DropbearNativeResult<NVector2> { let input = convert_ptr!(input_ptr => InputState); DropbearNativeResult::Ok(super::shared::get_last_mouse_pos(input)) } @@ -7,7 +7,7 @@ pub mod shared { use crate::scripting::jni::utils::{FromJObject, ToJObject}; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector2; + use crate::types::NVector2; fn map_int_to_gamepad_button(ordinal: i32) -> Option<Button> { match ordinal { @@ -51,29 +51,29 @@ pub mod shared { } } - pub fn get_left_stick(input: &InputState, gamepad_id: u64) -> Vector2 { + pub fn get_left_stick(input: &InputState, gamepad_id: u64) -> NVector2 { let Some(id) = get_gamepad_id(input, gamepad_id as usize) else { - return Vector2 { + return NVector2 { x: 0.0, y: 0.0 } }; let (x, y) = input.get_left_stick(id); - Vector2 { x: x as f64, y: y as f64 } + NVector2 { x: x as f64, y: y as f64 } } - pub fn get_right_stick(input: &InputState, gamepad_id: u64) -> Vector2 { + pub fn get_right_stick(input: &InputState, gamepad_id: u64) -> NVector2 { let Some(id) = get_gamepad_id(input, gamepad_id as usize) else { - return Vector2 { + return NVector2 { x: 0.0, y: 0.0 } }; let (x, y) = input.get_right_stick(id); - Vector2 { x: x as f64, y: y as f64 } + NVector2 { x: x as f64, y: y as f64 } } - impl ToJObject for Vector2 { + impl ToJObject for NVector2 { fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>> { let cls = env.find_class("com/dropbear/math/Vector2d") .map_err(|e| { @@ -97,7 +97,7 @@ pub mod shared { } } - impl FromJObject for Vector2 { + impl FromJObject for NVector2 { fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> where Self: Sized @@ -114,7 +114,7 @@ pub mod shared { .d() .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; - Ok(Vector2 { + Ok(NVector2 { x: x_val, y: y_val, }) @@ -186,7 +186,7 @@ pub mod native { use crate::input::{InputState}; use crate::convert_ptr; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector2; + use crate::types::NVector2; pub fn dropbear_is_gamepad_button_pressed( input_ptr: InputStatePtr, @@ -201,7 +201,7 @@ pub mod native { pub fn dropbear_get_left_stick_position( input_ptr: InputStatePtr, gamepad_id: u64 - ) -> DropbearNativeResult<Vector2> { + ) -> DropbearNativeResult<NVector2> { let input = convert_ptr!(input_ptr => InputState); let vec = super::shared::get_left_stick(input, gamepad_id); DropbearNativeResult::Ok(vec) @@ -210,7 +210,7 @@ pub mod native { pub fn dropbear_get_right_stick_position( input_ptr: InputStatePtr, gamepad_id: u64 - ) -> DropbearNativeResult<Vector2> { + ) -> DropbearNativeResult<NVector2> { let input = convert_ptr!(input_ptr => InputState); let vec = super::shared::get_right_stick(input, gamepad_id); DropbearNativeResult::Ok(vec) @@ -214,7 +214,7 @@ pub mod jni { use super::{JvmAttenuation, JvmColour, JvmRange}; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::Vector3; + use crate::types::NVector3; use crate::{convert_jlong_to_entity, convert_ptr}; use dropbear_engine::entity::{EntityTransform, Transform}; use dropbear_engine::lighting::{LightComponent, LightType}; @@ -289,7 +289,7 @@ pub mod jni { return std::ptr::null_mut(); }; - match Vector3::from(t.position).to_jobject(&mut env) { + match NVector3::from(t.position).to_jobject(&mut env) { Ok(obj) => obj.into_raw(), Err(_) => std::ptr::null_mut(), } @@ -306,7 +306,7 @@ pub mod jni { let world = convert_ptr!(mut world_ptr => World); let entity = convert_jlong_to_entity!(entity_id); - let position: DVec3 = match Vector3::from_jobject(&mut env, &position) { + let position: DVec3 = match NVector3::from_jobject(&mut env, &position) { Ok(v) => v.into(), Err(e) => { let _ = env.throw_new( @@ -340,7 +340,7 @@ pub mod jni { let forward = DVec3::new(0.0, 0.0, -1.0); let dir = (t.rotation * forward).normalize_or_zero(); - match Vector3::from(dir).to_jobject(&mut env) { + match NVector3::from(dir).to_jobject(&mut env) { Ok(obj) => obj.into_raw(), Err(_) => std::ptr::null_mut(), } @@ -357,7 +357,7 @@ pub mod jni { let world = convert_ptr!(mut world_ptr => World); let entity = convert_jlong_to_entity!(entity_id); - let dir: DVec3 = match Vector3::from_jobject(&mut env, &direction) { + let dir: DVec3 = match NVector3::from_jobject(&mut env, &direction) { Ok(v) => DVec3::from(v), Err(e) => { let _ = env.throw_new( @@ -212,7 +212,7 @@ pub mod jni { }; let Some(model_cache) = asset.get_pointer(Const("model_cache")) else { - let _ = env.throw_new("java/lang/IllegalArgumentException", "Unable to locate model_cache pointer within the asset_old registry"); + let _ = env.throw_new("java/lang/IllegalArgumentException", "Unable to locate model_cache pointer within the asset registry"); return; }; @@ -250,24 +250,24 @@ impl Default for PhysicsState { pub mod shared { use crate::physics::PhysicsState; - use crate::types::ColliderFFI; - use crate::types::Vector3; + use crate::types::NCollider; + use crate::types::NVector3; use hecs::Entity; use rapier3d::prelude::ColliderHandle; - pub fn get_gravity(physics: &PhysicsState) -> Vector3 { - Vector3::from(physics.gravity) + pub fn get_gravity(physics: &PhysicsState) -> NVector3 { + NVector3::from(physics.gravity) } - pub fn set_gravity(physics: &mut PhysicsState, new: Vector3) { + pub fn set_gravity(physics: &mut PhysicsState, new: NVector3) { physics.gravity = new.to_float_array(); } - fn collider_handle_from_ffi(collider: &ColliderFFI) -> ColliderHandle { + fn collider_handle_from_ffi(collider: &NCollider) -> ColliderHandle { ColliderHandle::from_raw_parts(collider.index.index, collider.index.generation) } - pub fn overlapping(physics: &PhysicsState, collider1: &ColliderFFI, collider2: &ColliderFFI) -> bool { + pub fn overlapping(physics: &PhysicsState, collider1: &NCollider, collider2: &NCollider) -> bool { let h1 = collider_handle_from_ffi(collider1); let h2 = collider_handle_from_ffi(collider2); @@ -281,7 +281,7 @@ pub mod shared { .unwrap_or(false) } - pub fn triggering(physics: &PhysicsState, collider1: &ColliderFFI, collider2: &ColliderFFI) -> bool { + pub fn triggering(physics: &PhysicsState, collider1: &NCollider, collider2: &NCollider) -> bool { let h1 = collider_handle_from_ffi(collider1); let h2 = collider_handle_from_ffi(collider2); @@ -334,7 +334,7 @@ pub mod jni { use crate::physics::nalgebra; use crate::physics::PhysicsState; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::{ColliderFFI, IndexNative, RayHit, ShapeCastHitFFI, Vector3}; + use crate::types::{NCollider, IndexNative, RayHit, ShapeCastHitFFI, NVector3}; use hecs::Entity; use jni::objects::{JClass, JObject}; use jni::sys::{jboolean, jdouble, jlong, jobject}; @@ -372,7 +372,7 @@ pub mod jni { new_gravity: JObject, ) { let mut physics = crate::convert_ptr!(mut physics_handle => PhysicsState); - let vec3 = match Vector3::from_jobject(&mut env, &new_gravity) { + let vec3 = match NVector3::from_jobject(&mut env, &new_gravity) { Ok(v) => v, Err(e) => { let _ = env.throw_new("java/lang/RuntimeException", format!("Unable to create new Vector3d object for gravity: {}", e)); @@ -397,7 +397,7 @@ pub mod jni { let qp = physics.broad_phase.as_query_pipeline(&DefaultQueryDispatcher, &physics.bodies, &physics.colliders, QueryFilter::new()); - let origin = match Vector3::from_jobject(&mut env, &origin) { + let origin = match NVector3::from_jobject(&mut env, &origin) { Ok(v) => v, Err(e) => { let _ = env.throw_new("java/lang/RuntimeException", format!("Unable to create a new rust Vector3 object: {}", e)); @@ -405,7 +405,7 @@ pub mod jni { } }; - let dir = match Vector3::from_jobject(&mut env, &direction) { + let dir = match NVector3::from_jobject(&mut env, &direction) { Ok(v) => v, Err(e) => { let _ = env.throw_new("java/lang/RuntimeException", format!("Unable to create a new rust Vector3 object: {}", e)); @@ -435,7 +435,7 @@ pub mod jni { let entity = physics.entity_label_map.iter().find(|(_, l)| *l == label); if let Some((e, _)) = entity { let rayhit = RayHit { - collider: crate::types::ColliderFFI { + collider: crate::types::NCollider { index: IndexNative::from(raw), entity_id: e.to_bits().get(), id: raw.into_raw_parts().0, @@ -457,7 +457,7 @@ pub mod jni { eprintln!("Unknown collider, still returning value without entity_id"); let rayhit = RayHit { - collider: crate::types::ColliderFFI { + collider: crate::types::NCollider { index: IndexNative::from(raw), entity_id: Entity::DANGLING.to_bits().get(), id: raw.into_raw_parts().0, @@ -478,7 +478,7 @@ pub mod jni { } } - fn collider_ffi_from_handle(physics: &PhysicsState, handle: rapier3d::prelude::ColliderHandle) -> ColliderFFI { + fn collider_ffi_from_handle(physics: &PhysicsState, handle: rapier3d::prelude::ColliderHandle) -> NCollider { let (idx, generation) = handle.into_raw_parts(); let mut found_label = None; @@ -505,7 +505,7 @@ pub mod jni { Entity::DANGLING.to_bits().get() }; - ColliderFFI { + NCollider { index: IndexNative { index: idx, generation }, entity_id, id: idx, @@ -550,7 +550,7 @@ pub mod jni { QueryFilter::new(), ); - let origin = match Vector3::from_jobject(&mut env, &origin) { + let origin = match NVector3::from_jobject(&mut env, &origin) { Ok(v) => v, Err(e) => { let _ = env.throw_new( @@ -561,7 +561,7 @@ pub mod jni { } }; - let direction = match Vector3::from_jobject(&mut env, &direction) { + let direction = match NVector3::from_jobject(&mut env, &direction) { Ok(v) => v, Err(e) => { let _ = env.throw_new( @@ -588,7 +588,7 @@ pub mod jni { return std::ptr::null_mut(); } - let dir_unit = Vector3 { + let dir_unit = NVector3 { x: direction.x / dir_len, y: direction.y / dir_len, z: direction.z / dir_len, @@ -614,10 +614,10 @@ pub mod jni { let hit = ShapeCastHitFFI { collider, distance: toi.time_of_impact as f64, - witness1: Vector3::from([toi.witness1.x, toi.witness1.y, toi.witness1.z]), - witness2: Vector3::from([toi.witness2.x, toi.witness2.y, toi.witness2.z]), - normal1: Vector3::from([toi.normal1.x, toi.normal1.y, toi.normal1.z]), - normal2: Vector3::from([toi.normal2.x, toi.normal2.y, toi.normal2.z]), + witness1: NVector3::from([toi.witness1.x, toi.witness1.y, toi.witness1.z]), + witness2: NVector3::from([toi.witness2.x, toi.witness2.y, toi.witness2.z]), + normal1: NVector3::from([toi.normal1.x, toi.normal1.y, toi.normal1.z]), + normal2: NVector3::from([toi.normal2.x, toi.normal2.y, toi.normal2.z]), status: toi.status, }; @@ -642,7 +642,7 @@ pub mod jni { collider2: JObject, ) -> jboolean { let physics = crate::convert_ptr!(physics_handle => PhysicsState); - let Ok(collider1) = ColliderFFI::from_jobject(&mut env, &collider1) else { + let Ok(collider1) = NCollider::from_jobject(&mut env, &collider1) else { let _ = env.throw_new( "java/lang/RuntimeException", "Unable to convert a Collider object [collider1] to a rust ColliderFFI" @@ -650,7 +650,7 @@ pub mod jni { return false.into(); }; - let Ok(collider2) = ColliderFFI::from_jobject(&mut env, &collider2) else { + let Ok(collider2) = NCollider::from_jobject(&mut env, &collider2) else { let _ = env.throw_new( "java/lang/RuntimeException", "Unable to convert a Collider object [collider2] to a rust ColliderFFI" @@ -670,7 +670,7 @@ pub mod jni { collider2: JObject, ) -> jboolean { let physics = crate::convert_ptr!(physics_handle => PhysicsState); - let Ok(collider1) = ColliderFFI::from_jobject(&mut env, &collider1) else { + let Ok(collider1) = NCollider::from_jobject(&mut env, &collider1) else { let _ = env.throw_new( "java/lang/RuntimeException", "Unable to convert a Collider object [collider1] to a rust ColliderFFI" @@ -678,7 +678,7 @@ pub mod jni { return false.into(); }; - let Ok(collider2) = ColliderFFI::from_jobject(&mut env, &collider2) else { + let Ok(collider2) = NCollider::from_jobject(&mut env, &collider2) else { let _ = env.throw_new( "java/lang/RuntimeException", "Unable to convert a Collider object [collider2] to a rust ColliderFFI" @@ -612,12 +612,12 @@ impl WireframeGeometry { pub mod shared { use crate::physics::PhysicsState; - use crate::types::ColliderFFI; + use crate::types::NCollider; use rapier3d::prelude::ColliderHandle; pub fn get_collider_mut<'a>( physics: &'a mut PhysicsState, - ffi: &ColliderFFI + ffi: &NCollider ) -> Option<&'a mut rapier3d::prelude::Collider> { let handle = ColliderHandle::from_raw_parts(ffi.index.index, ffi.index.generation); physics.colliders.get_mut(handle) @@ -625,7 +625,7 @@ pub mod shared { pub fn get_collider<'a>( physics: &'a PhysicsState, - ffi: &ColliderFFI + ffi: &NCollider ) -> Option<&'a rapier3d::prelude::Collider> { let handle = ColliderHandle::from_raw_parts(ffi.index.index, ffi.index.generation); physics.colliders.get(handle) @@ -638,7 +638,7 @@ pub mod jni { use crate::physics::collider::ColliderShape; use crate::physics::PhysicsState; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::ColliderFFI; + use crate::types::NCollider; use glam::DQuat; use jni::objects::{JClass, JObject}; use jni::sys::{jboolean, jdouble, jlong, jobject}; @@ -655,7 +655,7 @@ pub mod jni { ) -> jobject { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = match ColliderFFI::from_jobject(&mut env, &collider_obj) { + let ffi = match NCollider::from_jobject(&mut env, &collider_obj) { Ok(v) => v, Err(_) => return std::ptr::null_mut(), }; @@ -721,7 +721,7 @@ pub mod jni { ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - let ffi = match ColliderFFI::from_jobject(&mut env, &collider_obj) { + let ffi = match NCollider::from_jobject(&mut env, &collider_obj) { Ok(v) => v, Err(_) => return, }; @@ -767,7 +767,7 @@ pub mod jni { collider_obj: JObject, ) -> jdouble { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = ColliderFFI::from_jobject(&mut env, &collider_obj).ok().unwrap(); + let ffi = NCollider::from_jobject(&mut env, &collider_obj).ok().unwrap(); if let Some(col) = get_collider(&physics, &ffi) { col.density() as jdouble @@ -785,7 +785,7 @@ pub mod jni { density: jdouble, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { col.set_density(density as f32); } @@ -800,7 +800,7 @@ pub mod jni { collider_obj: JObject, ) -> jdouble { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = ColliderFFI::from_jobject(&mut env, &collider_obj).ok().unwrap(); + let ffi = NCollider::from_jobject(&mut env, &collider_obj).ok().unwrap(); if let Some(col) = get_collider(&physics, &ffi) { col.friction() as jdouble } else { 0.0 } @@ -815,7 +815,7 @@ pub mod jni { friction: jdouble, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { col.set_friction(friction as f32); } @@ -830,7 +830,7 @@ pub mod jni { collider_obj: JObject, ) -> jdouble { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = ColliderFFI::from_jobject(&mut env, &collider_obj).ok().unwrap(); + let ffi = NCollider::from_jobject(&mut env, &collider_obj).ok().unwrap(); if let Some(col) = get_collider(&physics, &ffi) { col.restitution() as jdouble } else { 0.0 } @@ -845,7 +845,7 @@ pub mod jni { restitution: jdouble, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { col.set_restitution(restitution as f32); } @@ -860,7 +860,7 @@ pub mod jni { collider_obj: JObject, ) -> jdouble { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = ColliderFFI::from_jobject(&mut env, &collider_obj).ok().unwrap(); + let ffi = NCollider::from_jobject(&mut env, &collider_obj).ok().unwrap(); if let Some(col) = get_collider(&physics, &ffi) { col.mass() as jdouble } else { 0.0 } @@ -875,7 +875,7 @@ pub mod jni { mass: jdouble, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { col.set_mass(mass as f32); } @@ -890,7 +890,7 @@ pub mod jni { collider_obj: JObject, ) -> jboolean { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = ColliderFFI::from_jobject(&mut env, &collider_obj).ok().unwrap(); + let ffi = NCollider::from_jobject(&mut env, &collider_obj).ok().unwrap(); if let Some(col) = get_collider(&physics, &ffi) { if col.is_sensor() { 1 } else { 0 } } else { 0 } @@ -905,7 +905,7 @@ pub mod jni { is_sensor: jboolean, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { col.set_sensor(is_sensor != 0); } @@ -920,14 +920,14 @@ pub mod jni { collider_obj: JObject, ) -> jobject { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = match ColliderFFI::from_jobject(&mut env, &collider_obj) { + let ffi = match NCollider::from_jobject(&mut env, &collider_obj) { Ok(v) => v, Err(_) => return std::ptr::null_mut(), }; if let Some(col) = get_collider(&physics, &ffi) { let t: Vector = col.translation(); - let vec = crate::types::Vector3::new(t.x as f64, t.y as f64, t.z as f64); + let vec = crate::types::NVector3::new(t.x as f64, t.y as f64, t.z as f64); match vec.to_jobject(&mut env) { Ok(o) => o.into_raw(), Err(_) => std::ptr::null_mut(), @@ -946,8 +946,8 @@ pub mod jni { vec_obj: JObject, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { - if let Ok(vec) = crate::types::Vector3::from_jobject(&mut env, &vec_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { + if let Ok(vec) = crate::types::NVector3::from_jobject(&mut env, &vec_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { let t = Vector::new(vec.x as f32, vec.y as f32, vec.z as f32); col.set_translation(t); @@ -964,7 +964,7 @@ pub mod jni { collider_obj: JObject, ) -> jobject { let physics = crate::convert_ptr!(physics_ptr => PhysicsState); - let ffi = match ColliderFFI::from_jobject(&mut env, &collider_obj) { + let ffi = match NCollider::from_jobject(&mut env, &collider_obj) { Ok(v) => v, Err(_) => return std::ptr::null_mut(), }; @@ -973,7 +973,7 @@ pub mod jni { let r: Rotation = col.rotation(); let q = DQuat::from_xyzw(r.x as f64, r.y as f64, r.z as f64, r.w as f64); let euler = q.to_euler(glam::EulerRot::XYZ); - let vec = crate::types::Vector3::new(euler.0, euler.1, euler.2); + let vec = crate::types::NVector3::new(euler.0, euler.1, euler.2); match vec.to_jobject(&mut env) { Ok(o) => o.into_raw(), @@ -993,8 +993,8 @@ pub mod jni { vec_obj: JObject, ) { let physics = crate::convert_ptr!(mut physics_ptr => PhysicsState); - if let Ok(ffi) = ColliderFFI::from_jobject(&mut env, &collider_obj) { - if let Ok(vec) = crate::types::Vector3::from_jobject(&mut env, &vec_obj) { + if let Ok(ffi) = NCollider::from_jobject(&mut env, &collider_obj) { + if let Ok(vec) = crate::types::NVector3::from_jobject(&mut env, &vec_obj) { if let Some(col) = get_collider_mut(physics, &ffi) { let q = DQuat::from_euler(glam::EulerRot::XYZ, vec.x, vec.y, vec.z); let r = Rotation::from_array([q.w as f32, q.x as f32, q.y as f32, q.z as f32]); @@ -1012,23 +1012,23 @@ pub mod native { use crate::physics::collider::shared::{get_collider, get_collider_mut}; use crate::physics::PhysicsState; use crate::ptr::PhysicsStatePtr; - use crate::types::Vector3; + use crate::types::NVector3; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::{ColliderFFI, ColliderShapeFFI, ColliderShapeType}; + use crate::types::{NCollider, NColliderShape, ColliderShapeType}; use glam::DQuat; use rapier3d::prelude::{SharedShape, TypedShape, Vector}; pub fn dropbear_get_collider_shape( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - ) -> DropbearNativeResult<ColliderShapeFFI> { + ffi: NCollider, + ) -> DropbearNativeResult<NColliderShape> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(collider) = get_collider(physics, &ffi) { let rapier_shape = collider.shape(); - let mut result = ColliderShapeFFI { + let mut result = NColliderShape { shape_type: ColliderShapeType::Box, radius: 0.0, half_height: 0.0, half_extents_x: 0.0, half_extents_y: 0.0, half_extents_z: 0.0, @@ -1070,8 +1070,8 @@ pub mod native { pub fn dropbear_set_collider_shape( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - shape: ColliderShapeFFI, + ffi: NCollider, + shape: NColliderShape, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1092,7 +1092,7 @@ pub mod native { pub fn dropbear_get_collider_density( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, ) -> DropbearNativeResult<f64> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { @@ -1104,7 +1104,7 @@ pub mod native { pub fn dropbear_set_collider_density( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, density: f64, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1118,7 +1118,7 @@ pub mod native { pub fn dropbear_get_collider_friction( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, ) -> DropbearNativeResult<f64> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { @@ -1130,7 +1130,7 @@ pub mod native { pub fn dropbear_set_collider_friction( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, friction: f64, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1144,7 +1144,7 @@ pub mod native { pub fn dropbear_get_collider_restitution( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, ) -> DropbearNativeResult<f64> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { @@ -1156,7 +1156,7 @@ pub mod native { pub fn dropbear_set_collider_restitution( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, restitution: f64, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1170,7 +1170,7 @@ pub mod native { pub fn dropbear_get_collider_mass( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, ) -> DropbearNativeResult<f64> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { @@ -1182,7 +1182,7 @@ pub mod native { pub fn dropbear_set_collider_mass( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, mass: f64, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1196,7 +1196,7 @@ pub mod native { pub fn dropbear_get_collider_is_sensor( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, ) -> DropbearNativeResult<bool> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { @@ -1208,7 +1208,7 @@ pub mod native { pub fn dropbear_set_collider_is_sensor( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, + ffi: NCollider, is_sensor: bool, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); @@ -1222,12 +1222,12 @@ pub mod native { pub fn dropbear_get_collider_translation( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - ) -> DropbearNativeResult<Vector3> { + ffi: NCollider, + ) -> DropbearNativeResult<NVector3> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { let t = col.translation(); - DropbearNativeResult::Ok(Vector3 { x: t.x as f64, y: t.y as f64, z: t.z as f64 }) + DropbearNativeResult::Ok(NVector3 { x: t.x as f64, y: t.y as f64, z: t.z as f64 }) } else { DropbearNativeResult::Err(DropbearNativeError::InvalidHandle) } @@ -1235,8 +1235,8 @@ pub mod native { pub fn dropbear_set_collider_translation( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - translation: Vector3, + ffi: NCollider, + translation: NVector3, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); if let Some(col) = get_collider_mut(physics, &ffi) { @@ -1250,14 +1250,14 @@ pub mod native { pub fn dropbear_get_collider_rotation( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - ) -> DropbearNativeResult<Vector3> { + ffi: NCollider, + ) -> DropbearNativeResult<NVector3> { let physics = convert_ptr!(physics_ptr => PhysicsState); if let Some(col) = get_collider(physics, &ffi) { let r = col.rotation(); let q: DQuat = DQuat::from_xyzw(r.x as f64, r.y as f64, r.z as f64, r.w as f64); let (x, y, z) = q.to_euler(glam::EulerRot::XYZ); - DropbearNativeResult::Ok(Vector3 { x, y, z }) + DropbearNativeResult::Ok(NVector3 { x, y, z }) } else { DropbearNativeResult::Err(DropbearNativeError::InvalidHandle) } @@ -1265,8 +1265,8 @@ pub mod native { pub fn dropbear_set_collider_rotation( physics_ptr: PhysicsStatePtr, - ffi: ColliderFFI, - rotation: Vector3, + ffi: NCollider, + rotation: NVector3, ) -> DropbearNativeResult<()> { let physics = convert_ptr!(mut physics_ptr => PhysicsState); if let Some(col) = get_collider_mut(physics, &ffi) { @@ -65,7 +65,7 @@ pub mod shared { pub mod jni { #![allow(non_snake_case)] use crate::physics::collider::ColliderGroup; - use crate::types::{ColliderFFI, IndexNative}; + use crate::types::{NCollider, IndexNative}; use hecs::World; use jni::objects::{JClass, JObject}; use jni::sys::{jboolean, jlong, jobjectArray}; @@ -106,13 +106,13 @@ pub mod jni { .get(&entity) .and_then(|label| physics.colliders_entity_map.get(label)); - let mut colliders: Vec<ColliderFFI> = Vec::new(); + let mut colliders: Vec<NCollider> = Vec::new(); if let Some(handles) = handles_opt { for (_, handle) in handles { let (idx, generation) = handle.into_raw_parts(); - let col = ColliderFFI { + let col = NCollider { index: IndexNative { index: idx, generation, @@ -172,7 +172,7 @@ pub mod native { use crate::ptr::{PhysicsStatePtr, WorldPtr}; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::{ColliderFFI, IndexNative}; + use crate::types::{NCollider, IndexNative}; use hecs::Entity; pub fn dropbear_collider_group_exists_for_entity( @@ -190,7 +190,7 @@ pub mod native { physics_ptr: PhysicsStatePtr, entity_id: u64, out_count: *mut usize, - ) -> DropbearNativeResult<*mut ColliderFFI> { + ) -> DropbearNativeResult<*mut NCollider> { let world = convert_ptr!(world_ptr => hecs::World); let physics = convert_ptr!(physics_ptr => PhysicsState); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; @@ -208,13 +208,13 @@ pub mod native { .get(&entity) .and_then(|label| physics.colliders_entity_map.get(label)); - let mut colliders: Vec<ColliderFFI> = Vec::new(); + let mut colliders: Vec<NCollider> = Vec::new(); if let Some(handles) = handles_opt { for (_, handle) in handles { let (idx, generation) = handle.into_raw_parts(); - let col = ColliderFFI { + let col = NCollider { index: IndexNative { index: idx, generation, @@ -236,7 +236,7 @@ pub mod native { } pub fn dropbear_free_collider_array( - ptr: *mut ColliderFFI, + ptr: *mut NCollider, count: usize, ) -> DropbearNativeResult<()> { if ptr.is_null() { @@ -47,7 +47,7 @@ pub mod jni { use crate::physics::PhysicsState; use crate::scripting::jni::utils::FromJObject; use crate::states::Label; - use crate::types::Vector3; + use crate::types::NVector3; use jni::objects::JValue; use jni::sys::{jint, jobjectArray}; use crate::types::IndexNative; @@ -81,7 +81,7 @@ pub mod jni { let physics_state = convert_ptr!(mut physics_handle => PhysicsState); let entity = convert_jlong_to_entity!(entity); - let movement = match Vector3::from_jobject(&mut env, &translation) { + let movement = match NVector3::from_jobject(&mut env, &translation) { Ok(v) => v, Err(e) => { let _ = env.throw_new("java/lang/RuntimeException", format!("Unable to convert JObject to Vector3: {}", e)); @@ -3,7 +3,7 @@ use ::jni::objects::{JObject, JValue}; use crate::scripting::jni::utils::ToJObject; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; -use crate::types::{ColliderFFI, IndexNative, Vector3}; +use crate::types::{NCollider, IndexNative, NVector3}; use dropbear_engine::entity::Transform as DbTransform; use hecs::{Entity, World}; use rapier3d::control::CharacterCollision; @@ -27,12 +27,12 @@ fn get_collision_from_world(world: &World, entity: Entity, collision_handle: Ind .ok_or(DropbearNativeError::NoSuchHandle) } -fn collider_ffi_from_handle(world: &World, handle: rapier3d::prelude::ColliderHandle) -> Option<ColliderFFI> { +fn collider_ffi_from_handle(world: &World, handle: rapier3d::prelude::ColliderHandle) -> Option<NCollider> { let (idx, generation) = handle.into_raw_parts(); for (entity, group) in world.query::<(Entity, &ColliderGroup)>().iter() { if group.colliders.iter().any(|c| c.id == idx) { - return Some(ColliderFFI { + return Some(NCollider { index: IndexNative { index: idx, generation }, entity_id: entity.to_bits().get(), id: idx, @@ -80,7 +80,7 @@ pub mod shared { use glam::{DQuat, DVec3}; use rapier3d::na::Quaternion; - pub fn get_collider(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<ColliderFFI> { + pub fn get_collider(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NCollider> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; collider_ffi_from_handle(world, collision.handle) .ok_or(DropbearNativeError::PhysicsObjectNotFound) @@ -101,16 +101,16 @@ pub mod shared { }) } - pub fn get_translation_applied(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_translation_applied(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let v = collision.translation_applied; - Ok(Vector3 { x: v.x as f64, y: v.y as f64, z: v.z as f64 }) + Ok(NVector3 { x: v.x as f64, y: v.y as f64, z: v.z as f64 }) } - pub fn get_translation_remaining(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_translation_remaining(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let v = collision.translation_remaining; - Ok(Vector3 { x: v.x as f64, y: v.y as f64, z: v.z as f64 }) + Ok(NVector3 { x: v.x as f64, y: v.y as f64, z: v.z as f64 }) } pub fn get_time_of_impact(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<f64> { @@ -118,28 +118,28 @@ pub mod shared { Ok(collision.hit.time_of_impact as f64) } - pub fn get_witness1(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_witness1(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let p = collision.hit.witness1; - Ok(Vector3 { x: p.x as f64, y: p.y as f64, z: p.z as f64 }) + Ok(NVector3 { x: p.x as f64, y: p.y as f64, z: p.z as f64 }) } - pub fn get_witness2(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_witness2(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let p = collision.hit.witness2; - Ok(Vector3 { x: p.x as f64, y: p.y as f64, z: p.z as f64 }) + Ok(NVector3 { x: p.x as f64, y: p.y as f64, z: p.z as f64 }) } - pub fn get_normal1(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_normal1(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let n = collision.hit.normal1; - Ok(Vector3 { x: n.x as f64, y: n.y as f64, z: n.z as f64 }) + Ok(NVector3 { x: n.x as f64, y: n.y as f64, z: n.z as f64 }) } - pub fn get_normal2(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<Vector3> { + pub fn get_normal2(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<NVector3> { let collision = super::get_collision_from_world(world, entity, collision_handle)?; let n = collision.hit.normal2; - Ok(Vector3 { x: n.x as f64, y: n.y as f64, z: n.z as f64 }) + Ok(NVector3 { x: n.x as f64, y: n.y as f64, z: n.z as f64 }) } pub fn get_status(world: &World, entity: Entity, collision_handle: IndexNative) -> DropbearNativeResult<ShapeCastStatus> { @@ -203,7 +203,7 @@ pub mod shared { use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; use crate::states::Label; - use crate::types::{IndexNative, RigidBodyContext, Vector3}; + use crate::types::{IndexNative, RigidBodyContext, NVector3}; use hecs::{Entity, World}; use rapier3d::dynamics::{RigidBodyHandle, RigidBodyType}; use rapier3d::prelude::Vector; @@ -394,17 +394,17 @@ pub mod shared { } } - pub fn get_rigidbody_linvel(physics: &PhysicsState, rb_context: RigidBodyContext) -> DropbearNativeResult<Vector3> { + pub fn get_rigidbody_linvel(physics: &PhysicsState, rb_context: RigidBodyContext) -> DropbearNativeResult<NVector3> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get(handle) { let linvel = rb.linvel().clone(); - Ok(Vector3::new(linvel.x as f64, linvel.y as f64, linvel.z as f64)) + Ok(NVector3::new(linvel.x as f64, linvel.y as f64, linvel.z as f64)) } else { Err(DropbearNativeError::PhysicsObjectNotFound) } } - pub fn set_rigidbody_linvel(physics: &mut PhysicsState, world: &World, rb_context: RigidBodyContext, new: Vector3) -> DropbearNativeResult<()> { + pub fn set_rigidbody_linvel(physics: &mut PhysicsState, world: &World, rb_context: RigidBodyContext, new: NVector3) -> DropbearNativeResult<()> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get_mut(handle) { rb.set_linvel(Vector::new(new.x as f32, new.y as f32, new.z as f32), true); @@ -421,17 +421,17 @@ pub mod shared { } } - pub fn get_rigidbody_angvel(physics: &PhysicsState, rb_context: RigidBodyContext) -> DropbearNativeResult<Vector3> { + pub fn get_rigidbody_angvel(physics: &PhysicsState, rb_context: RigidBodyContext) -> DropbearNativeResult<NVector3> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get(handle) { let angvel = rb.angvel().clone(); - Ok(Vector3::new(angvel.x as f64, angvel.y as f64, angvel.z as f64)) + Ok(NVector3::new(angvel.x as f64, angvel.y as f64, angvel.z as f64)) } else { Err(DropbearNativeError::PhysicsObjectNotFound) } } - pub fn set_rigidbody_angvel(physics: &mut PhysicsState, world: &World, rb_context: RigidBodyContext, new: Vector3) -> DropbearNativeResult<()> { + pub fn set_rigidbody_angvel(physics: &mut PhysicsState, world: &World, rb_context: RigidBodyContext, new: NVector3) -> DropbearNativeResult<()> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get_mut(handle) { rb.set_angvel(Vector::new(new.x as f32, new.y as f32, new.z as f32), true); @@ -554,7 +554,7 @@ pub mod shared { } } - pub fn apply_impulse(physics: &mut PhysicsState, _world: &World, rb_context: RigidBodyContext, new: Vector3) -> DropbearNativeResult<()> { + pub fn apply_impulse(physics: &mut PhysicsState, _world: &World, rb_context: RigidBodyContext, new: NVector3) -> DropbearNativeResult<()> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get_mut(handle) { rb.apply_impulse(Vector::new(new.x as f32, new.y as f32, new.z as f32), true); @@ -565,7 +565,7 @@ pub mod shared { } } - pub fn apply_torque_impulse(physics: &mut PhysicsState, _world: &World, rb_context: RigidBodyContext, new: Vector3) -> DropbearNativeResult<()> { + pub fn apply_torque_impulse(physics: &mut PhysicsState, _world: &World, rb_context: RigidBodyContext, new: NVector3) -> DropbearNativeResult<()> { let handle = RigidBodyHandle::from_raw_parts(rb_context.index.index, rb_context.index.generation); if let Some(rb) = physics.bodies.get_mut(handle) { rb.apply_torque_impulse(Vector::new(new.x as f32, new.y as f32, new.z as f32), true); @@ -582,7 +582,7 @@ pub mod jni { use crate::physics::rigidbody::AxisLock; use crate::physics::PhysicsState; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::{IndexNative, RigidBodyContext, Vector3}; + use crate::types::{IndexNative, RigidBodyContext, NVector3}; use crate::{convert_jlong_to_entity, convert_ptr}; use hecs::World; use jni::objects::{JClass, JObject}; @@ -968,7 +968,7 @@ pub mod jni { return; }; - let Ok(velocity) = Vector3::from_jobject(&mut env, &linear_velocity) else { + let Ok(velocity) = NVector3::from_jobject(&mut env, &linear_velocity) else { let _ = env.throw_new("java/lang/RuntimeException", "Unable to convert com/dropbear/math/Vector3d to rust Vector3"); return; @@ -1032,7 +1032,7 @@ pub mod jni { return; }; - let Ok(velocity) = Vector3::from_jobject(&mut env, &angular_velocity) else { + let Ok(velocity) = NVector3::from_jobject(&mut env, &angular_velocity) else { let _ = env.throw_new("java/lang/RuntimeException", "Unable to convert com/dropbear/math/Vector3d to rust Vector3"); return; @@ -1244,7 +1244,7 @@ pub mod jni { return; }; - let impulse = Vector3::new(x as f64, y as f64, z as f64); + let impulse = NVector3::new(x as f64, y as f64, z as f64); if let Err(e) = super::shared::apply_impulse(&mut physics, world, rb_context, impulse) { eprintln!("Failed to apply impulse: {}", e); let _ = env.throw_new("java/lang/IllegalArgumentException", format!("Failed to apply impulse: {}", e)); @@ -1271,7 +1271,7 @@ pub mod jni { return; }; - let torque = Vector3::new(x as f64, y as f64, z as f64); + let torque = NVector3::new(x as f64, y as f64, z as f64); if let Err(e) = super::shared::apply_torque_impulse(&mut physics, world, rb_context, torque) { eprintln!("Failed to apply torque impulse: {}", e); let _ = env.throw_new("java/lang/IllegalArgumentException", format!("Failed to apply torque impulse: {}", e)); @@ -218,7 +218,7 @@ pub mod jni { use crate::properties::{CustomProperties, Value}; use crate::scripting::jni::utils::{FromJObject, ToJObject}; - use crate::types::Vector3; + use crate::types::NVector3; /// Returns a primitive that is boxed (long => java.lang.Long) /// @@ -411,7 +411,7 @@ pub mod jni { if let Ok(props) = world.get::<&CustomProperties>(entity) { if let Some(Value::Vec3(v)) = props.get_property(&key_str) { - return match Vector3::from(*v).to_jobject(&mut env) { + return match NVector3::from(*v).to_jobject(&mut env) { Ok(obj) => obj.into_raw(), Err(_) => std::ptr::null_mut() }; @@ -542,7 +542,7 @@ pub mod jni { let entity = crate::convert_jlong_to_entity!(entity_id); let key_str = crate::convert_jstring!(env, key); - let vec_val = match Vector3::from_jobject(&mut env, &value) { + let vec_val = match NVector3::from_jobject(&mut env, &value) { Ok(v) => v, Err(_) => return, }; @@ -565,7 +565,7 @@ pub mod native { use crate::ptr::WorldPtr; use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; - use crate::types::Vector3; + use crate::types::NVector3; pub fn dropbear_custom_properties_exists_for_entity( world_ptr: WorldPtr, @@ -687,14 +687,14 @@ pub mod native { world_ptr: WorldPtr, entity_id: u64, key: *const c_char - ) -> DropbearNativeResult<Vector3> { + ) -> DropbearNativeResult<NVector3> { let world = convert_ptr!(world_ptr => World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; let key_str = unsafe { read_key(key)? }; if let Ok(props) = world.get::<&CustomProperties>(entity) { if let Some(Value::Vec3(v)) = props.get_property(&key_str) { - return DropbearNativeResult::Ok(Vector3::from(*v)); + return DropbearNativeResult::Ok(NVector3::from(*v)); } } DropbearNativeResult::Err(DropbearNativeError::InvalidArgument) @@ -813,7 +813,7 @@ pub mod native { world_ptr: WorldPtr, entity_id: u64, key: *const c_char, - value: Vector3 + value: NVector3 ) -> DropbearNativeResult<()> { let world = convert_ptr!(world_ptr => World); let entity = Entity::from_bits(entity_id).ok_or(DropbearNativeError::InvalidEntity)?; @@ -1,10 +1,12 @@ //! Helper pointers and typedef definitions. + +use std::sync::Arc; use crate::input::InputState; use crate::command::CommandBuffer; use crossbeam_channel::Sender; use dropbear_engine::asset::AssetRegistry; use hecs::World; -use parking_lot::Mutex; +use parking_lot::{Mutex, RwLock}; use crate::physics::PhysicsState; use crate::scene::loading::SceneLoader; use crate::ui::{UiContext}; @@ -28,7 +30,8 @@ pub type CommandBufferPtr = *const Sender<CommandBuffer>; /// A non-mutable pointer to the [`AssetRegistry`]. /// /// Defined in `dropbear_common.h` as `AssetRegistry` -pub type AssetRegistryPtr = *const AssetRegistry; +pub type AssetRegistryPtr = *const AssetRegistryUnwrapped; +pub type AssetRegistryUnwrapped = Arc<RwLock<AssetRegistry>>; /// A mutable pointer to a [`parking_lot::Mutex<SceneLoader>`] /// @@ -1,7 +1,7 @@ //! Utilities for JNI and JVM based code. use crate::scripting::result::DropbearNativeResult; -use jni::objects::JObject; +use jni::objects::{JObject, JValue}; use jni::sys::jint; use jni::JNIEnv; @@ -34,4 +34,42 @@ pub trait FromJObject { /// Converts a Rust object (struct or enum) into a java [JObject] pub trait ToJObject { fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>>; +} + +impl<T> ToJObject for Vec<T> +where + T: ToJObject, +{ + fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>> { + let list_class = env.find_class("java/util/ArrayList")?; + let list_obj = env.new_object(&list_class, "()V", &[])?; + + for item in self { + let obj = item.to_jobject(env)?; + let _ = env.call_method(&list_obj, "add", "(Ljava/lang/Object;)Z", &[JValue::Object(&obj)])?; + } + + Ok(list_obj) + } +} + +impl<T> FromJObject for Vec<T> +where + T: FromJObject, +{ + fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> + where + Self: Sized, + { + let size = env.call_method(obj, "size", "()I", &[])?.i()? as jint; + let mut out = Vec::with_capacity(size as usize); + + for i in 0..size { + let item = env.call_method(obj, "get", "(I)Ljava/lang/Object;", &[JValue::Int(i)])?.l()?; + let value = T::from_jobject(env, &item)?; + out.push(value); + } + + Ok(out) + } } @@ -493,7 +493,7 @@ pub enum DropbearNativeError { /// When the argument is invalid #[error("Invalid argument")] InvalidArgument, - /// The handle provided does not exist. Could be for an asset_old, entity, or other handle type. + /// The handle provided does not exist. Could be for an asset, entity, or other handle type. #[error("No such handle")] NoSuchHandle, /// Failed to create a Java object via JNI. @@ -511,13 +511,13 @@ pub enum DropbearNativeError { /// Failed to unwrap a Java object via JNI. #[error("JNI unwrap failed")] JNIUnwrapFailed, - /// Generic asset_old error. There was an error thrown, however there is no context attached. - #[error("Generic asset_old error")] + /// Generic asset error. There was an error thrown, however there is no context attached. + #[error("Generic asset error")] GenericAssetError, /// The provided uri (either euca:// or https) was invalid and formatted wrong. #[error("Invalid URI")] InvalidURI, - /// The asset_old provided by the handle is wrong. + /// The asset provided by the handle is wrong. #[error("Asset not found")] AssetNotFound, /// When a handle has been inputted wrongly. @@ -5,7 +5,7 @@ use dropbear_engine::entity::{EntityTransform, Transform}; use glam::{DQuat, DVec3}; use ::jni::objects::{JObject, JValue}; use ::jni::JNIEnv; -use crate::types::Vector3; +use crate::types::NVector3; impl FromJObject for Transform { fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> { @@ -27,8 +27,8 @@ impl FromJObject for Transform { let scale_obj = scale_val.l() .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; - let position: DVec3 = Vector3::from_jobject(env, &pos_obj)?.into(); - let scale: DVec3 = Vector3::from_jobject(env, &scale_obj)?.into(); + let position: DVec3 = NVector3::from_jobject(env, &pos_obj)?.into(); + let scale: DVec3 = NVector3::from_jobject(env, &scale_obj)?.into(); let mut get_double = |field: &str| -> DropbearNativeResult<f64> { env.get_field(&rot_obj, field, "D") @@ -281,7 +281,7 @@ pub mod jni { #[dropbear_macro::impl_c_api] pub mod native { use crate::hierarchy::EntityTransformExt; - use crate::types::{TransformNative as Transform}; + use crate::types::{NTransform as Transform}; use dropbear_engine::entity::EntityTransform; use hecs::{Entity, World}; @@ -1,5 +1,5 @@ //! FFI and C types of other library types, as used in the scripting module. -use glam::{DQuat, DVec3}; +use glam::{DQuat, DVec3, Vec3}; use hecs::Entity; use jni::JNIEnv; use jni::objects::{JObject, JValue}; @@ -13,16 +13,68 @@ use crate::scripting::native::DropbearNativeError; use crate::scripting::result::DropbearNativeResult; #[repr(C)] -#[derive(Clone, Copy)] -pub struct Vector3 { +#[derive(Clone, Copy, Debug)] +pub struct NVector2 { + pub x: f64, + pub y: f64, +} + +impl NVector2 { + pub fn to_array(&self) -> [f64; 2] { + [self.x, self.y] + } +} + +impl From<glam::DVec2> for NVector2 { + fn from(v: glam::DVec2) -> Self { + Self { x: v.x, y: v.y } + } +} + +impl From<[f64; 2]> for NVector2 { + fn from(value: [f64; 2]) -> Self { + NVector2 { + x: value[0], + y: value[1], + } + } +} + +impl From<[f32; 2]> for NVector2 { + fn from(value: [f32; 2]) -> Self { + NVector2 { + x: value[0] as f64, + y: value[1] as f64, + } + } +} + +impl From<NVector2> for glam::DVec2 { + fn from(v: NVector2) -> Self { + Self::new(v.x, v.y) + } +} + +impl From<(f64, f64)> for NVector2 { + fn from(value: (f64, f64)) -> Self { + Self { + x: value.0, + y: value.1, + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct NVector3 { pub x: f64, pub y: f64, pub z: f64, } -impl Vector3 { - pub fn new(x: f64, y: f64, z: f64) -> Vector3 { - Vector3 { +impl NVector3 { + pub fn new(x: f64, y: f64, z: f64) -> NVector3 { + NVector3 { x, y, z } } @@ -35,15 +87,15 @@ impl Vector3 { } } -impl From<glam::DVec3> for Vector3 { +impl From<glam::DVec3> for NVector3 { fn from(v: glam::DVec3) -> Self { Self { x: v.x, y: v.y, z: v.z } } } -impl From<[f64; 3]> for Vector3 { +impl From<[f64; 3]> for NVector3 { fn from(value: [f64; 3]) -> Self { - Vector3 { + NVector3 { x: value[0], y: value[1], z: value[2], @@ -51,9 +103,9 @@ impl From<[f64; 3]> for Vector3 { } } -impl From<[f32; 3]> for Vector3 { +impl From<[f32; 3]> for NVector3 { fn from(value: [f32; 3]) -> Self { - Vector3 { + NVector3 { x: value[0] as f64, y: value[1] as f64, z: value[2] as f64, @@ -61,13 +113,23 @@ impl From<[f32; 3]> for Vector3 { } } -impl From<Vector3> for glam::DVec3 { - fn from(v: Vector3) -> Self { +impl From<glam::Vec3> for NVector3 { + fn from(value: Vec3) -> Self { + Self { + x: value.x as f64, + y: value.y as f64, + z: value.z as f64, + } + } +} + +impl From<NVector3> for glam::DVec3 { + fn from(v: NVector3) -> Self { Self::new(v.x, v.y, v.z) } } -impl FromJObject for Vector3 { +impl FromJObject for NVector3 { fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> where Self: Sized @@ -96,11 +158,11 @@ impl FromJObject for Vector3 { .d() .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; - Ok(Vector3::new(x, y, z)) + Ok(NVector3::new(x, y, z)) } } -impl ToJObject for Vector3 { +impl ToJObject for NVector3 { fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>> { let class = env.find_class("com/dropbear/math/Vector3d") .map_err(|_| DropbearNativeError::JNIClassNotFound)?; @@ -120,16 +182,145 @@ impl ToJObject for Vector3 { } } + #[repr(C)] -#[derive(Clone, Copy)] -pub struct Quaternion { +#[derive(Clone, Copy, Debug)] +pub struct NVector4 { + pub x: f64, + pub y: f64, + pub z: f64, + pub w: f64, +} + +impl NVector4 { + pub fn new(x: f64, y: f64, z: f64, w: f64) -> NVector4 { + NVector4 { + x, y, z, w + } + } + + pub fn to_array(&self) -> [f64; 3] { + [self.x, self.y, self.z] + } + pub fn to_float_array(&self) -> [f32; 3] { + [self.x as f32, self.y as f32, self.z as f32] + } +} + +impl From<glam::DVec4> for NVector4 { + fn from(v: glam::DVec4) -> Self { + Self { x: v.x, y: v.y, z: v.z, w: v.w } + } +} + +impl From<[f64; 4]> for NVector4 { + fn from(value: [f64; 4]) -> Self { + NVector4 { + x: value[0], + y: value[1], + z: value[2], + w: value[3], + } + } +} + +impl From<[f32; 4]> for NVector4 { + fn from(value: [f32; 4]) -> Self { + NVector4 { + x: value[0] as f64, + y: value[1] as f64, + z: value[2] as f64, + w: value[3] as f64, + } + } +} + +impl From<NVector4> for glam::DVec4 { + fn from(v: NVector4) -> Self { + Self::new(v.x, v.y, v.z, v.w) + } +} + +impl FromJObject for NVector4 { + fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> + where + Self: Sized + { + let class = env.find_class("com/dropbear/math/Vector4d") + .map_err(|_| DropbearNativeError::JNIClassNotFound)?; + + if !env.is_instance_of(obj, &class) + .map_err(|_| DropbearNativeError::JNIUnwrapFailed)? + { + return Err(DropbearNativeError::InvalidArgument); + } + + let x = env.get_field(obj, "x", "D") + .map_err(|_| DropbearNativeError::JNIFailedToGetField)? + .d() + .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; + + let y = env.get_field(obj, "y", "D") + .map_err(|_| DropbearNativeError::JNIFailedToGetField)? + .d() + .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; + + let z = env.get_field(obj, "z", "D") + .map_err(|_| DropbearNativeError::JNIFailedToGetField)? + .d() + .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; + + let w = env.get_field(obj, "w", "D") + .map_err(|_| DropbearNativeError::JNIFailedToGetField)? + .d() + .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; + + Ok(NVector4::new(x, y, z, w)) + } +} + +impl ToJObject for NVector4 { + fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>> { + let class = env.find_class("com/dropbear/math/Vector3d") + .map_err(|_| DropbearNativeError::JNIClassNotFound)?; + + let constructor_sig = "(DDD)V"; + + let args = [ + jni::objects::JValue::Double(self.x), + jni::objects::JValue::Double(self.y), + jni::objects::JValue::Double(self.z), + jni::objects::JValue::Double(self.w), + ]; + + let obj = env.new_object(&class, constructor_sig, &args) + .map_err(|_| DropbearNativeError::JNIFailedToCreateObject)?; + + Ok(obj) + } +} + +impl From<NQuaternion> for NVector4 { + fn from(value: NQuaternion) -> Self { + Self { + x: value.x, + y: value.y, + z: value.z, + w: value.w, + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct NQuaternion { pub x: f64, pub y: f64, pub z: f64, pub w: f64, } -impl From<DQuat> for Quaternion { +impl From<DQuat> for NQuaternion { fn from(value: DQuat) -> Self { Self { x: value.x, @@ -140,8 +331,8 @@ impl From<DQuat> for Quaternion { } } -impl From<Quaternion> for glam::DQuat { - fn from(value: Quaternion) -> Self { +impl From<NQuaternion> for glam::DQuat { + fn from(value: NQuaternion) -> Self { Self { x: value.x, y: value.y, @@ -151,7 +342,7 @@ impl From<Quaternion> for glam::DQuat { } } -impl From<[f64; 4]> for Quaternion { +impl From<[f64; 4]> for NQuaternion { fn from(value: [f64; 4]) -> Self { Self { x: value[0], @@ -162,86 +353,66 @@ impl From<[f64; 4]> for Quaternion { } } -#[repr(C)] -#[derive(Clone, Copy)] -pub struct TransformNative { - position: Vector3, - rotation: Quaternion, - scale: Vector3, -} - -impl From<Transform> for TransformNative { - fn from(value: Transform) -> Self { +impl From<glam::Quat> for NQuaternion { + fn from(value: glam::Quat) -> Self { Self { - position: Vector3::from(value.position), - rotation: Quaternion::from(value.rotation), - scale: Vector3::from(value.scale), + x: value.x as f64, + y: value.y as f64, + z: value.z as f64, + w: value.w as f64, + } } } -impl From<TransformNative> for Transform { - fn from(value: TransformNative) -> Self { +impl From<NVector4> for NQuaternion { + fn from(value: NVector4) -> Self { Self { - position: DVec3::from(value.position), - rotation: DQuat::from(value.rotation), - scale: DVec3::from(value.scale), + x: value.x, + y: value.y, + z: value.z, + w: value.w, } } } #[repr(C)] #[derive(Clone, Copy)] -pub struct Vector2 { - pub(crate) x: f64, - pub(crate) y: f64, +pub struct NTransform { + position: NVector3, + rotation: NQuaternion, + scale: NVector3, } -impl Vector2 { - pub fn to_array(&self) -> [f64; 2] { - [self.x, self.y] - } -} - -impl From<glam::DVec2> for Vector2 { - fn from(v: glam::DVec2) -> Self { - Self { x: v.x, y: v.y } - } -} - -impl From<[f64; 2]> for Vector2 { - fn from(value: [f64; 2]) -> Self { - Vector2 { - x: value[0], - y: value[1], +impl From<Transform> for NTransform { + fn from(value: Transform) -> Self { + Self { + position: NVector3::from(value.position), + rotation: NQuaternion::from(value.rotation), + scale: NVector3::from(value.scale), } } } -impl From<Vector2> for glam::DVec2 { - fn from(v: Vector2) -> Self { - Self::new(v.x, v.y) - } -} - -impl From<(f64, f64)> for Vector2 { - fn from(value: (f64, f64)) -> Self { +impl From<NTransform> for Transform { + fn from(value: NTransform) -> Self { Self { - x: value.0, - y: value.1, + position: DVec3::from(value.position), + rotation: DQuat::from(value.rotation), + scale: DVec3::from(value.scale), } } } #[repr(C)] #[derive(Clone, Copy)] -pub struct ColliderFFI { +pub struct NCollider { pub index: IndexNative, pub entity_id: u64, pub id: u32, } -impl ToJObject for ColliderFFI { +impl ToJObject for NCollider { fn to_jobject<'a>(&self, env: &mut JNIEnv<'a>) -> DropbearNativeResult<JObject<'a>> { let collider_cls = env.find_class("com/dropbear/physics/Collider") .map_err(|_| DropbearNativeError::JNIClassNotFound)?; @@ -281,7 +452,7 @@ impl ToJObject for ColliderFFI { } } -impl FromJObject for ColliderFFI { +impl FromJObject for NCollider { fn from_jobject(env: &mut JNIEnv, obj: &JObject) -> DropbearNativeResult<Self> where Self: Sized @@ -316,7 +487,7 @@ impl FromJObject for ColliderFFI { .i() .map_err(|_| DropbearNativeError::JNIUnwrapFailed)?; - Ok(ColliderFFI { + Ok(NCollider { index: IndexNative { index: idx_val as u32, generation: gen_val as u32, @@ -330,8 +501,8 @@ impl FromJObject for ColliderFFI { #[repr(C)] #[derive(Clone, Copy)] pub struct IndexNative { - pub(crate) index: u32, - pub(crate) generation: u32, + pub index: u32, + pub generation: u32, } impl From<Index> for IndexNative { @@ -362,7 +533,7 @@ pub enum ColliderShapeType { #[repr(C)] #[derive(Clone, Copy)] -pub struct ColliderShapeFFI { +pub struct NColliderShape { pub shape_type: ColliderShapeType, pub radius: f32, pub half_height: f32, @@ -478,7 +649,7 @@ impl ToJObject for RigidBodyContext { #[repr(C)] #[derive(Clone, Copy)] pub struct RayHit { - pub collider: ColliderFFI, + pub collider: NCollider, pub distance: f64, } @@ -511,12 +682,12 @@ impl ToJObject for RayHit { #[repr(C)] #[derive(Clone, Copy)] pub struct ShapeCastHitFFI { - pub collider: ColliderFFI, + pub collider: NCollider, pub distance: f64, - pub witness1: Vector3, - pub witness2: Vector3, - pub normal1: Vector3, - pub normal2: Vector3, + pub witness1: NVector3, + pub witness2: NVector3, + pub normal1: NVector3, + pub normal2: NVector3, pub status: rapier3d::parry::query::ShapeCastStatus, } @@ -600,8 +771,8 @@ impl ToJObject for CollisionEventType { #[derive(Clone, Copy)] pub struct CollisionEvent { pub(crate) event_type: CollisionEventType, - pub(crate) collider1: ColliderFFI, - pub(crate) collider2: ColliderFFI, + pub(crate) collider1: NCollider, + pub(crate) collider2: NCollider, pub(crate) flags: u64, } @@ -658,12 +829,12 @@ impl CollisionEvent { Some(Self { event_type: CollisionEventType::Started, - collider1: ColliderFFI { + collider1: NCollider { index: IndexNative::from(col1.0), entity_id: collider1_info.to_bits().get(), id: col1.into_raw_parts().0, }, - collider2: ColliderFFI { + collider2: NCollider { index: IndexNative::from(col2.0), entity_id: collider2_info.to_bits().get(), id: col2.into_raw_parts().0, @@ -708,12 +879,12 @@ impl CollisionEvent { Some(Self { event_type: CollisionEventType::Stopped, - collider1: ColliderFFI { + collider1: NCollider { index: IndexNative::from(col1.0), entity_id: collider1_info.to_bits().get(), id: col1.into_raw_parts().0, }, - collider2: ColliderFFI { + collider2: NCollider { index: IndexNative::from(col2.0), entity_id: collider2_info.to_bits().get(), id: col2.into_raw_parts().0, @@ -755,11 +926,11 @@ impl ToJObject for CollisionEvent { #[repr(C)] #[derive(Clone, Copy)] pub struct ContactForceEvent { - pub(crate) collider1: ColliderFFI, - pub(crate) collider2: ColliderFFI, - pub(crate) total_force: Vector3, + pub(crate) collider1: NCollider, + pub(crate) collider2: NCollider, + pub(crate) total_force: NVector3, pub(crate) total_force_magnitude: f64, - pub(crate) max_force_direction: Vector3, + pub(crate) max_force_direction: NVector3, pub(crate) max_force_magnitude: f64, } @@ -798,23 +969,23 @@ impl ContactForceEvent { }; Some(Self { - collider1: ColliderFFI { + collider1: NCollider { index: IndexNative::from(event.collider1.0), entity_id: find_entity(event.collider1)?.to_bits().get(), id: event.collider1.into_raw_parts().0, }, - collider2: ColliderFFI { + collider2: NCollider { index: IndexNative::from(event.collider2.0), entity_id: find_entity(event.collider2)?.to_bits().get(), id: event.collider2.into_raw_parts().0, }, - total_force: Vector3::new( + total_force: NVector3::new( event.total_force.x.into(), event.total_force.y.into(), event.total_force.z.into() ), total_force_magnitude: event.total_force_magnitude as f64, - max_force_direction: Vector3::new( + max_force_direction: NVector3::new( event.max_force_direction.x.into(), event.max_force_direction.y.into(), event.max_force_direction.z.into() @@ -324,7 +324,7 @@ fn resolve_resource_from_root(relative: &str, root: &Path) -> anyhow::Result<Pat } anyhow::bail!( - "Resource '{}' was resolved to '{}' but the file does not exist. Ensure the asset_old is packaged under '{}'", + "Resource '{}' was resolved to '{}' but the file does not exist. Ensure the asset is packaged under '{}'", relative, resolved.display(), root.display() @@ -470,7 +470,7 @@ impl<'a> EditorTabViewer<'a> { } fn draw_asset_icon(ui: &mut egui::Ui) { - let image = egui::Image::from_bytes("bytes://asset_old-viewer-icon", NO_TEXTURE) + let image = egui::Image::from_bytes("bytes://asset-viewer-icon", NO_TEXTURE) .max_size(egui::vec2(14.0, 14.0)); ui.add(image); } @@ -1653,7 +1653,7 @@ impl<'a> EditorTabViewer<'a> { } fn draw_asset_icon(ui: &mut egui::Ui) { - let image = egui::Image::from_bytes("bytes://asset_old-viewer-icon", NO_TEXTURE) + let image = egui::Image::from_bytes("bytes://asset-viewer-icon", NO_TEXTURE) .max_size(egui::vec2(14.0, 14.0)); ui.add(image); } @@ -274,7 +274,7 @@ async fn load_renderer_from_serialized( let mut mesh_renderer = match &renderer.handle.ref_type { ResourceReferenceType::None => anyhow::bail!( - "Renderer for '{}' does not specify an asset_old reference", + "Renderer for '{}' does not specify an asset reference", label ), ResourceReferenceType::Unassigned { id } => { @@ -64,7 +64,7 @@ impl AssetServer { self.texture_labels.insert(label.into(), handle.clone()); } - /// Updates the asset_old server by inserting the texture provided at the location of the handle, + /// Updates the asset server by inserting the texture provided at the location of the handle, /// and removing the old texture (by returning it back to you). pub fn update_texture(&mut self, handle: Handle<Texture>, texture: Texture) -> Option<Texture> { self.textures.insert(handle.id, texture) @@ -4,13 +4,182 @@ #include <stdbool.h> #include <stdint.h> +#include <stddef.h> + +typedef void* WorldPtr; + +typedef struct NVector4 { + double x; + double y; + double z; + double w; +} NVector4; + +typedef struct NVector3 { + double x; + double y; + double z; +} NVector3; + +typedef struct Option Option;// opaque + +typedef struct NVector2 { + double x; + double y; +} NVector2; + +typedef struct NMaterial { + const char* name; + uint64_t diffuse_texture; + uint64_t normal_texture; + NVector4 tint; + NVector3 emissive_factor; + float metallic_factor; + float roughness_factor; + Option alpha_cutoff; + bool double_sided; + float occlusion_strength; + float normal_scale; + NVector2 uv_tiling; + Option emissive_texture; + Option metallic_roughness_texture; + Option occlusion_texture; +} NMaterial; + +typedef struct NMaterialArrayFfi { + const NMaterial* ptr; + size_t len; +} NMaterialArrayFfi; + +typedef void* AssetRegistryPtr; + +typedef void* SceneLoaderPtr; + +typedef struct size_t size_t;// opaque + typedef struct Progress { - uintptr_t current; - uintptr_t total; + size_t current; + size_t total; const char* message; } Progress; +typedef struct i32ArrayFfi { + const int32_t* ptr; + size_t len; +} i32ArrayFfi; + +typedef struct f64ArrayFfiArrayFfi { + const double* ptr; + size_t len; +} f64ArrayFfiArrayFfi; + +typedef struct NSkin { + const char* name; + i32ArrayFfi joints; + f64ArrayFfiArrayFfi inverse_bind_matrices; + Option skeleton_root; +} NSkin; + +typedef struct NSkinArrayFfi { + const NSkin* ptr; + size_t len; +} NSkinArrayFfi; + +typedef struct f64ArrayFfi { + const double* ptr; + size_t len; +} f64ArrayFfi; + +typedef struct NChannelValues NChannelValues;// opaque + +typedef struct NAnimationInterpolation NAnimationInterpolation;// opaque + +typedef struct NAnimationChannel { + int32_t target_node; + f64ArrayFfi times; + NChannelValues values; + NAnimationInterpolation interpolation; +} NAnimationChannel; + +typedef struct NAnimationChannelArrayFfi { + const NAnimationChannel* ptr; + size_t len; +} NAnimationChannelArrayFfi; + +typedef struct NAnimation { + const char* name; + NAnimationChannelArrayFfi channels; + float duration; +} NAnimation; + +typedef struct NAnimationArrayFfi { + const NAnimation* ptr; + size_t len; +} NAnimationArrayFfi; + +typedef struct AssetKind AssetKind;// opaque + +typedef struct NQuaternion { + double x; + double y; + double z; + double w; +} NQuaternion; + +typedef struct NNodeTransform { + NVector3 translation; + NQuaternion rotation; + NVector3 scale; +} NNodeTransform; + +typedef struct NNode { + const char* name; + Option parent; + i32ArrayFfi children; + NNodeTransform transform; +} NNode; + +typedef struct NNodeArrayFfi { + const NNode* ptr; + size_t len; +} NNodeArrayFfi; + +typedef struct NModelVertex { + NVector3 position; + NVector3 normal; + NVector4 tangent; + NVector2 tex_coords0; + NVector2 tex_coords1; + NVector4 colour0; + i32ArrayFfi joints0; + NVector4 weights0; +} NModelVertex; + +typedef struct NModelVertexArrayFfi { + const NModelVertex* ptr; + size_t len; +} NModelVertexArrayFfi; + +typedef struct NMesh { + const char* name; + int32_t num_elements; + int32_t material_index; + NModelVertexArrayFfi vertices; +} NMesh; + +typedef struct NMeshArrayFfi { + const NMesh* ptr; + size_t len; +} NMeshArrayFfi; + int32_t dropbear_scene_get_scene_load_progress(SceneLoaderPtr scene_loader, uint64_t scene_id, Progress* out0); int32_t dropbear_get_entity(WorldPtr world, const char* label, uint64_t* out0); +int32_t dropbear_engine_get_asset(AssetRegistryPtr asset, const char* label, const AssetKind* kind, uint64_t* out0, bool* out0_present); +int32_t dropbear_asset_model_get_label(AssetRegistryPtr asset, uint64_t model_handle, char** out0); +int32_t dropbear_asset_model_get_meshes(AssetRegistryPtr asset, uint64_t model_handle, NMeshArrayFfi* out0); +int32_t dropbear_asset_model_get_materials(AssetRegistryPtr asset, uint64_t model_handle, NMaterialArrayFfi* out0); +int32_t dropbear_asset_model_get_skins(AssetRegistryPtr asset, uint64_t model_handle, NSkinArrayFfi* out0); +int32_t dropbear_asset_model_get_animations(AssetRegistryPtr asset, uint64_t model_handle, NAnimationArrayFfi* out0); +int32_t dropbear_asset_model_get_nodes(AssetRegistryPtr asset, uint64_t model_handle, NNodeArrayFfi* out0); #endif /* DROPBEAR_H */ @@ -0,0 +1,17 @@ +package com.dropbear.asset; + +import com.dropbear.EucalyptusCoreLoader; +import com.dropbear.asset.model.*; + +public class ModelNative { + static { + new EucalyptusCoreLoader().ensureLoaded(); + } + + 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); +} @@ -0,0 +1,38 @@ +package com.dropbear.animation + +import com.dropbear.animation.AnimationComponent + +actual fun AnimationComponent.getActiveAnimationIndex(): Int? { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) { +} + +actual fun AnimationComponent.getTime(): Float { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setTime(value: Float) { +} + +actual fun AnimationComponent.getSpeed(): Float { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setSpeed(value: Float) { +} + +actual fun AnimationComponent.getLooping(): Boolean { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setLooping(value: Boolean) { +} + +actual fun AnimationComponent.getIsPlaying(): Boolean { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setIsPlaying(value: Boolean) { +} @@ -1,5 +1,6 @@ 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 @@ -7,25 +8,25 @@ import com.dropbear.asset.model.Node import com.dropbear.asset.model.Skin actual fun Model.getLabel(): String { - TODO("Not yet implemented") + return ModelNative.getLabel(DropbearEngine.native.assetHandle, label) } actual fun Model.getMeshes(): List<Mesh> { - return emptyList() + return ModelNative.getMeshes(DropbearEngine.native.assetHandle, this.id).toList() } actual fun Model.getMaterials(): List<Material> { - return emptyList() + return ModelNative.getMaterials(DropbearEngine.native.assetHandle, this.id).toList() } actual fun Model.getSkins(): List<Skin> { - return emptyList() + return ModelNative.getSkins(DropbearEngine.native.assetHandle, this.id).toList() } actual fun Model.getAnimations(): List<Animation> { - return emptyList() + return ModelNative.getAnimations(DropbearEngine.native.assetHandle, this.id).toList() } actual fun Model.getNodes(): List<Node> { - return emptyList() -} + return ModelNative.getNodes(DropbearEngine.native.assetHandle, this.id).toList() +} @@ -0,0 +1,11 @@ +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") +} @@ -0,0 +1,8 @@ +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") +} @@ -0,0 +1,7 @@ +package com.dropbear.ui.widgets + +import com.dropbear.ui.Response + +actual fun Text.getResponse(): Response { + TODO("Not yet implemented") +} @@ -0,0 +1,38 @@ +package com.dropbear.animation + +import com.dropbear.animation.AnimationComponent + +actual fun AnimationComponent.getActiveAnimationIndex(): Int? { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) { +} + +actual fun AnimationComponent.getTime(): Float { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setTime(value: Float) { +} + +actual fun AnimationComponent.getSpeed(): Float { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setSpeed(value: Float) { +} + +actual fun AnimationComponent.getLooping(): Boolean { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setLooping(value: Boolean) { +} + +actual fun AnimationComponent.getIsPlaying(): Boolean { + TODO("Not yet implemented") +} + +actual fun AnimationComponent.setIsPlaying(value: Boolean) { +} @@ -0,0 +1,11 @@ +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") +} @@ -0,0 +1,8 @@ +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") +} @@ -0,0 +1,7 @@ +package com.dropbear.ui.widgets + +import com.dropbear.ui.Response + +actual fun Text.getResponse(): Response { + TODO("Not yet implemented") +} @@ -1,36 +0,0 @@ -package com.dropbear.animation - -actual fun AnimationComponent.getActiveAnimationIndex(): Int? { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) { -} - -actual fun AnimationComponent.getTime(): Float { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setTime(value: Float) { -} - -actual fun AnimationComponent.getSpeed(): Float { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setSpeed(value: Float) { -} - -actual fun AnimationComponent.getLooping(): Boolean { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setLooping(value: Boolean) { -} - -actual fun AnimationComponent.getIsPlaying(): Boolean { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setIsPlaying(value: Boolean) { -} @@ -1,9 +0,0 @@ -package com.dropbear.ui - -actual fun com.dropbear.ui.Response.getClicked(): Boolean { - TODO("Not yet implemented") -} - -actual fun Response.getHovering(): Boolean { - TODO("Not yet implemented") -} @@ -1,7 +0,0 @@ -package com.dropbear.ui.widgets - -import com.dropbear.ui.Response - -actual fun Rectangle.getResponse(): Response { - TODO("Not yet implemented") -} @@ -1,7 +0,0 @@ -package com.dropbear.ui.widgets - -import com.dropbear.ui.Response - -actual fun Text.getResponse(): Response { - TODO("Not yet implemented") -} @@ -1,36 +0,0 @@ -package com.dropbear.animation - -actual fun AnimationComponent.getActiveAnimationIndex(): Int? { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setActiveAnimationIndex(index: Int?) { -} - -actual fun AnimationComponent.getTime(): Float { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setTime(value: Float) { -} - -actual fun AnimationComponent.getSpeed(): Float { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setSpeed(value: Float) { -} - -actual fun AnimationComponent.getLooping(): Boolean { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setLooping(value: Boolean) { -} - -actual fun AnimationComponent.getIsPlaying(): Boolean { - TODO("Not yet implemented") -} - -actual fun AnimationComponent.setIsPlaying(value: Boolean) { -} @@ -1,9 +0,0 @@ -package com.dropbear.ui - -actual fun com.dropbear.ui.Response.getClicked(): Boolean { - TODO("Not yet implemented") -} - -actual fun Response.getHovering(): Boolean { - TODO("Not yet implemented") -} @@ -1,7 +0,0 @@ -package com.dropbear.ui.widgets - -import com.dropbear.ui.Response - -actual fun Rectangle.getResponse(): Response { - TODO("Not yet implemented") -} @@ -1,7 +0,0 @@ -package com.dropbear.ui.widgets - -import com.dropbear.ui.Response - -actual fun Text.getResponse(): Response { - TODO("Not yet implemented") -}