1use cxx::{type_id, ExternType};
2use static_assertions::const_assert_eq;
3use std::fmt::{self, Debug, Formatter};
4use std::ops::{Deref, DerefMut};
5use std::pin::Pin;
6use std::{mem, ptr};
7
8use crate::base::XError;
9use crate::detour::base::{DtAABB, DtBuf};
10
11pub const DT_VERTS_PER_POLYGON: usize = 6;
12
13pub const DT_NAVMESH_MAGIC: u32 = (('D' as u32) << 24) | (('N' as u32) << 16) | (('A' as u32) << 8) | ('V' as u32);
14pub const DT_NAVMESH_VERSION: u32 = 7;
15pub const DT_NAVMESH_STATE_MAGIC: u32 =
16 (('D' as u32) << 24) | (('N' as u32) << 16) | (('M' as u32) << 8) | ('S' as u32);
17pub const DT_NAVMESH_STATE_VERSION: u32 = 1;
18
19pub const DT_EXT_LINK: u16 = 0x8000;
20pub const DT_NULL_LINK: u32 = 0xffffffff;
21
22pub const DT_OFFMESH_CON_BIDIR: u32 = 1;
23
24pub const DT_MAX_AREAS: usize = 64;
25
26pub const DT_RAY_CAST_LIMIT_PROPORTIONS: f32 = 50.0;
27
28const DT_TILE_FREE_DATA: i32 = 1;
29
30#[cxx::bridge]
31pub(crate) mod ffi {
32 #[repr(u32)]
33 enum dtPolyTypes {
34 DT_POLYTYPE_GROUND = 0,
35 DT_POLYTYPE_OFFMESH_CONNECTION = 1,
36 }
37
38 unsafe extern "C++" {
39 include!("recastnavigation-rs/src/detour/detour-ffi.h");
40
41 type dtStatus = crate::detour::base::ffi::dtStatus;
42
43 type dtPolyRef = crate::detour::mesh::DtPolyRef;
44 type dtTileRef = crate::detour::mesh::DtTileRef;
45
46 type dtPolyTypes;
47
48 type dtPoly = crate::detour::mesh::DtPoly;
49 fn dtp_setArea(poly: Pin<&mut dtPoly>, a: u8);
50 fn dtp_setType(poly: Pin<&mut dtPoly>, t: u8);
51 fn dtp_getArea(poly: &dtPoly) -> u8;
52 fn dtp_getType(poly: &dtPoly) -> u8;
53
54 type dtPolyDetail = crate::detour::mesh::DtPolyDetail;
55 type dtLink = crate::detour::mesh::DtLink;
56 type dtBVNode = crate::detour::mesh::DtBVNode;
57 type dtOffMeshConnection = crate::detour::mesh::DtOffMeshConnection;
58 type dtMeshHeader = crate::detour::mesh::DtMeshHeader;
59 type dtNavMeshParams = crate::detour::mesh::DtNavMeshParams;
60
61 type dtMeshTile = crate::detour::mesh::CxxDtMeshTile;
62
63 fn dtGetDetailTriEdgeFlags(triFlags: u8, edgeIndex: i32) -> i32;
64
65 type dtNavMesh;
66 fn dtAllocNavMesh() -> *mut dtNavMesh;
67 unsafe fn dtFreeNavMesh(ptr: *mut dtNavMesh);
68 #[rust_name = "init_with_params"]
69 unsafe fn init(self: Pin<&mut dtNavMesh>, params: *const dtNavMeshParams) -> dtStatus;
70 #[rust_name = "init_with_data"]
71 unsafe fn init(self: Pin<&mut dtNavMesh>, data: *mut u8, dataSize: i32, flags: i32) -> dtStatus;
72 fn getParams(self: &dtNavMesh) -> *const dtNavMeshParams;
73 unsafe fn addTile(
74 self: Pin<&mut dtNavMesh>,
75 data: *mut u8,
76 dataSize: i32,
77 flags: i32,
78 lastRef: dtTileRef,
79 result: *mut dtTileRef,
80 ) -> dtStatus;
81 unsafe fn removeTile(
82 self: Pin<&mut dtNavMesh>,
83 re: dtTileRef,
84 data: *mut *mut u8,
85 dataSize: *mut i32,
86 ) -> dtStatus;
87 unsafe fn calcTileLoc(self: &dtNavMesh, pos: *const f32, tx: *mut i32, ty: *mut i32);
88 unsafe fn getTileAt(self: &dtNavMesh, x: i32, y: i32, layer: i32) -> *const dtMeshTile;
89 unsafe fn getTilesAt(self: &dtNavMesh, x: i32, y: i32, tiles: *mut *const dtMeshTile, maxTiles: i32) -> i32;
90 fn getTileRefAt(self: &dtNavMesh, x: i32, y: i32, layer: i32) -> dtTileRef;
91 unsafe fn getTileRef(self: &dtNavMesh, tile: *const dtMeshTile) -> dtTileRef;
92 unsafe fn getTileByRef(self: &dtNavMesh, re: dtTileRef) -> *const dtMeshTile;
93 fn getMaxTiles(self: &dtNavMesh) -> i32;
94 unsafe fn getTile(self: &dtNavMesh, i: i32) -> *const dtMeshTile;
95 unsafe fn getTileAndPolyByRef(
96 self: &dtNavMesh,
97 re: dtPolyRef,
98 tile: *mut *const dtMeshTile,
99 poly: *mut *const dtPoly,
100 ) -> dtStatus;
101 unsafe fn getTileAndPolyByRefUnsafe(
102 self: &dtNavMesh,
103 re: dtPolyRef,
104 tile: *mut *const dtMeshTile,
105 poly: *mut *const dtPoly,
106 );
107 fn isValidPolyRef(self: &dtNavMesh, re: dtPolyRef) -> bool;
108 unsafe fn getPolyRefBase(self: &dtNavMesh, tile: *const dtMeshTile) -> dtPolyRef;
109 unsafe fn getOffMeshConnectionPolyEndPoints(
110 self: &dtNavMesh,
111 prevRef: dtPolyRef,
112 polyRef: dtPolyRef,
113 startPos: *mut f32,
114 endPos: *mut f32,
115 ) -> dtStatus;
116 fn getOffMeshConnectionByRef(self: &dtNavMesh, re: dtPolyRef) -> *const dtOffMeshConnection;
117 fn setPolyFlags(self: Pin<&mut dtNavMesh>, re: dtPolyRef, flags: u16) -> dtStatus;
118 unsafe fn getPolyFlags(self: &dtNavMesh, re: dtPolyRef, resultFlags: *mut u16) -> dtStatus;
119 fn setPolyArea(self: Pin<&mut dtNavMesh>, re: dtPolyRef, area: u8) -> dtStatus;
120 unsafe fn getPolyArea(self: &dtNavMesh, re: dtPolyRef, resultArea: *mut u8) -> dtStatus;
121 unsafe fn getTileStateSize(self: &dtNavMesh, tile: *const dtMeshTile) -> i32;
122 fn encodePolyId(self: &dtNavMesh, salt: u32, it: u32, ip: u32) -> dtPolyRef;
123 unsafe fn decodePolyId(self: &dtNavMesh, re: dtPolyRef, salt: &mut u32, it: &mut u32, ip: &mut u32);
124 fn decodePolyIdSalt(self: &dtNavMesh, re: dtPolyRef) -> u32;
125 fn decodePolyIdTile(self: &dtNavMesh, re: dtPolyRef) -> u32;
126 fn decodePolyIdPoly(self: &dtNavMesh, re: dtPolyRef) -> u32;
127 unsafe fn dtmt_storeTileState(navMesh: &dtNavMesh, re: dtTileRef, data: *mut u8, maxDataSize: i32) -> dtStatus;
128 unsafe fn dtmt_restoreTileState(
129 navMesh: Pin<&mut dtNavMesh>,
130 re: dtTileRef,
131 data: *const u8,
132 maxDataSize: i32,
133 ) -> dtStatus;
134 }
135}
136
137pub type DtPolyTypes = ffi::dtPolyTypes;
138
139#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
140#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
141pub struct DtPolyRef(pub u32);
142
143unsafe impl ExternType for DtPolyRef {
144 type Id = type_id!("dtPolyRef");
145 type Kind = cxx::kind::Trivial;
146}
147
148#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
149pub struct DtTileRef(pub u32);
150
151unsafe impl ExternType for DtTileRef {
152 type Id = type_id!("dtTileRef");
153 type Kind = cxx::kind::Trivial;
154}
155
156impl DtPolyRef {
157 pub fn is_null(&self) -> bool {
158 return self.0 == 0;
159 }
160}
161
162#[repr(C)]
167#[derive(Debug, Clone)]
168pub struct DtPoly {
169 pub first_link: u32,
170 pub verts: [u16; DT_VERTS_PER_POLYGON],
171 pub neis: [u16; DT_VERTS_PER_POLYGON],
172 pub flags: u16,
173 pub vert_count: u8,
174 pub area_and_type: u8,
175}
176
177const_assert_eq!(mem::size_of::<DtPoly>(), 32);
178
179unsafe impl ExternType for DtPoly {
180 type Id = type_id!("dtPoly");
181 type Kind = cxx::kind::Trivial;
182}
183
184impl DtPoly {
185 pub fn set_area(&mut self, a: u8) {
186 return ffi::dtp_setArea(Pin::new(self), a);
187 }
188
189 pub fn set_type(&mut self, t: DtPolyTypes) {
190 return ffi::dtp_setType(Pin::new(self), t.repr as u32 as u8);
191 }
192
193 pub fn area(&self) -> u8 {
194 return ffi::dtp_getArea(self);
195 }
196
197 pub fn typ(&self) -> DtPolyTypes {
198 let t = ffi::dtp_getType(self) as u32;
199 if t == DtPolyTypes::DT_POLYTYPE_OFFMESH_CONNECTION.repr as u32 {
200 return DtPolyTypes::DT_POLYTYPE_OFFMESH_CONNECTION;
201 } else {
202 return DtPolyTypes::DT_POLYTYPE_GROUND;
203 };
204 }
205}
206
207#[repr(C)]
212#[derive(Debug, Clone)]
213pub struct DtPolyDetail {
214 pub vert_base: u32,
215 pub tri_base: u32,
216 pub vert_count: u8,
217 pub tri_count: u8,
218}
219
220const_assert_eq!(mem::size_of::<DtPolyDetail>(), 12);
221
222unsafe impl ExternType for DtPolyDetail {
223 type Id = type_id!("dtPolyDetail");
224 type Kind = cxx::kind::Trivial;
225}
226
227#[repr(C)]
232#[derive(Debug, Clone)]
233pub struct DtLink {
234 pub re: DtPolyRef,
235 pub next: u32,
236 pub edge: u8,
237 pub side: u8,
238 pub bmin: u8,
239 pub bmax: u8,
240}
241
242const_assert_eq!(mem::size_of::<DtLink>(), 12);
243
244unsafe impl ExternType for DtLink {
245 type Id = type_id!("dtLink");
246 type Kind = cxx::kind::Trivial;
247}
248
249#[repr(C)]
254#[derive(Debug, Clone)]
255pub struct DtBVNode {
256 pub bmin: [u16; 3],
257 pub bmax: [u16; 3],
258 pub i: i32,
259}
260
261const_assert_eq!(mem::size_of::<DtBVNode>(), 16);
262
263unsafe impl ExternType for DtBVNode {
264 type Id = type_id!("dtBVNode");
265 type Kind = cxx::kind::Trivial;
266}
267
268#[repr(C)]
273#[derive(Debug, Clone)]
274pub struct DtOffMeshConnection {
275 pub pos: DtAABB,
276 pub rad: f32,
277 pub poly: u16,
278 pub flags: u8,
279 pub side: u8,
280 pub user_id: u32,
281}
282
283const_assert_eq!(mem::size_of::<DtOffMeshConnection>(), 36);
284
285unsafe impl ExternType for DtOffMeshConnection {
286 type Id = type_id!("dtOffMeshConnection");
287 type Kind = cxx::kind::Trivial;
288}
289
290#[repr(C)]
295#[derive(Debug, Clone, PartialEq)]
296pub struct DtMeshHeader {
297 pub magic: i32,
298 pub version: i32,
299 pub x: i32,
300 pub y: i32,
301 pub layer: i32,
302 pub user_id: u32,
303 pub poly_count: i32,
304 pub vert_count: i32,
305 pub max_link_count: i32,
306 pub detail_mesh_count: i32,
307 pub detail_vert_count: i32,
308 pub detail_tri_count: i32,
309 pub bv_node_count: i32,
310 pub off_mesh_con_count: i32,
311 pub off_mesh_base: i32,
312 pub walkable_height: f32,
313 pub walkable_radius: f32,
314 pub walkable_climb: f32,
315 pub bmin: [f32; 3],
316 pub bmax: [f32; 3],
317 pub bv_quant_factor: f32,
318}
319
320const_assert_eq!(mem::size_of::<DtMeshHeader>(), 100);
321
322unsafe impl ExternType for DtMeshHeader {
323 type Id = type_id!("dtMeshHeader");
324 type Kind = cxx::kind::Trivial;
325}
326
327#[repr(C)]
332#[derive(Debug)]
333pub struct CxxDtMeshTile {
334 pub salt: u32,
335 pub links_free_list: u32,
336 header: *mut ffi::dtMeshHeader,
337 polys: *mut ffi::dtPoly,
338 verts: *mut [f32; 3],
339 links: *mut ffi::dtLink,
340 detail_meshes: *mut ffi::dtPolyDetail,
341 detail_verts: *mut [f32; 3],
342 detail_tris: *mut [u8; 4],
343 bv_tree: *mut ffi::dtBVNode,
344 off_mesh_cons: *mut ffi::dtOffMeshConnection,
345 data: *mut u8,
346 data_size: i32,
347 _flags: i32,
348 next: *mut ffi::dtMeshTile,
349}
350
351#[cfg(target_pointer_width = "64")]
352const_assert_eq!(mem::size_of::<CxxDtMeshTile>(), 104);
353
354#[cfg(target_pointer_width = "32")]
355const_assert_eq!(mem::size_of::<CxxDtMeshTile>(), 60);
356
357unsafe impl ExternType for CxxDtMeshTile {
358 type Id = type_id!("dtMeshTile");
359 type Kind = cxx::kind::Trivial;
360}
361
362pub struct DtMeshTile(CxxDtMeshTile);
363
364impl Deref for DtMeshTile {
365 type Target = CxxDtMeshTile;
366
367 fn deref(&self) -> &Self::Target {
368 return self.inner();
369 }
370}
371
372impl DerefMut for DtMeshTile {
373 fn deref_mut(&mut self) -> &mut Self::Target {
374 return self.inner_mut().get_mut();
375 }
376}
377
378impl Debug for DtMeshTile {
379 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
380 return self.inner().fmt(f);
381 }
382}
383
384impl DtMeshTile {
385 fn inner(&self) -> &ffi::dtMeshTile {
386 return &self.0;
387 }
388
389 fn inner_mut(&mut self) -> Pin<&mut ffi::dtMeshTile> {
390 return unsafe { Pin::new_unchecked(&mut self.0) };
391 }
392
393 pub fn as_ptr(&self) -> *const ffi::dtMeshTile {
394 return &self.0;
395 }
396
397 pub fn as_mut_ptr(&mut self) -> *mut ffi::dtMeshTile {
398 return &mut self.0;
399 }
400
401 pub fn header(&self) -> Option<&DtMeshHeader> {
402 unsafe {
403 if self.header.is_null() {
404 return None;
405 } else {
406 return Some(&*self.header);
407 }
408 };
409 }
410
411 pub fn header_mut(&mut self) -> Option<&mut DtMeshHeader> {
412 unsafe {
413 if self.header.is_null() {
414 return None;
415 } else {
416 return Some(&mut *self.header);
417 }
418 };
419 }
420
421 pub fn polys(&self) -> &[DtPoly] {
422 let poly_count = self.header().map_or(0, |h| h.poly_count as usize);
423 return unsafe { std::slice::from_raw_parts(self.polys, poly_count) };
424 }
425
426 pub fn polys_mut(&mut self) -> &mut [DtPoly] {
427 let poly_count = self.header().map_or(0, |h| h.poly_count as usize);
428 return unsafe { std::slice::from_raw_parts_mut(self.polys, poly_count) };
429 }
430
431 pub fn verts(&self) -> &[[f32; 3]] {
432 let vert_count = self.header().map_or(0, |h| h.vert_count as usize);
433 return unsafe { std::slice::from_raw_parts(self.verts, vert_count) };
434 }
435
436 pub fn verts_mut(&mut self) -> &mut [[f32; 3]] {
437 let vert_count = self.header().map_or(0, |h| h.vert_count as usize);
438 return unsafe { std::slice::from_raw_parts_mut(self.verts, vert_count) };
439 }
440
441 pub fn links(&self) -> &[DtLink] {
442 let link_count = self.header().map_or(0, |h| h.max_link_count as usize);
443 return unsafe { std::slice::from_raw_parts(self.links, link_count) };
444 }
445
446 pub fn links_mut(&mut self) -> &mut [DtLink] {
447 let link_count = self.header().map_or(0, |h| h.max_link_count as usize);
448 return unsafe { std::slice::from_raw_parts_mut(self.links, link_count) };
449 }
450
451 pub fn detail_meshes(&self) -> &[DtPolyDetail] {
452 let detail_mesh_count = self.header().map_or(0, |h| h.detail_mesh_count as usize);
453 return unsafe { std::slice::from_raw_parts(self.detail_meshes, detail_mesh_count) };
454 }
455
456 pub fn detail_meshes_mut(&mut self) -> &mut [DtPolyDetail] {
457 let detail_mesh_count = self.header().map_or(0, |h| h.detail_mesh_count as usize);
458 return unsafe { std::slice::from_raw_parts_mut(self.detail_meshes, detail_mesh_count) };
459 }
460
461 pub fn detail_verts(&self) -> &[[f32; 3]] {
462 let detail_vert_count = self.header().map_or(0, |h| h.detail_vert_count as usize);
463 return unsafe { std::slice::from_raw_parts(self.detail_verts, detail_vert_count) };
464 }
465
466 pub fn detail_verts_mut(&mut self) -> &mut [[f32; 3]] {
467 let detail_vert_count = self.header().map_or(0, |h| h.detail_vert_count as usize);
468 return unsafe { std::slice::from_raw_parts_mut(self.detail_verts, detail_vert_count) };
469 }
470
471 pub fn detail_tris(&self) -> &[[u8; 4]] {
472 let detail_tri_count = self.header().map_or(0, |h| h.detail_tri_count as usize);
473 return unsafe { std::slice::from_raw_parts(self.detail_tris, detail_tri_count) };
474 }
475
476 pub fn detail_tris_mut(&mut self) -> &mut [[u8; 4]] {
477 let detail_tri_count = self.header().map_or(0, |h| h.detail_tri_count as usize);
478 return unsafe { std::slice::from_raw_parts_mut(self.detail_tris, detail_tri_count) };
479 }
480
481 pub fn bv_tree(&self) -> &[DtBVNode] {
482 let bv_node_count = self.header().map_or(0, |h| h.bv_node_count as usize);
483 return unsafe { std::slice::from_raw_parts(self.bv_tree, bv_node_count) };
484 }
485
486 pub fn bv_tree_mut(&mut self) -> &mut [DtBVNode] {
487 let bv_node_count = self.header().map_or(0, |h| h.bv_node_count as usize);
488 return unsafe { std::slice::from_raw_parts_mut(self.bv_tree, bv_node_count) };
489 }
490
491 pub fn off_mesh_cons(&self) -> &[DtOffMeshConnection] {
492 let off_mesh_con_count = self.header().map_or(0, |h| h.off_mesh_con_count as usize);
493 return unsafe { std::slice::from_raw_parts(self.off_mesh_cons, off_mesh_con_count) };
494 }
495
496 pub fn off_mesh_cons_mut(&mut self) -> &mut [DtOffMeshConnection] {
497 let off_mesh_con_count = self.header().map_or(0, |h| h.off_mesh_con_count as usize);
498 return unsafe { std::slice::from_raw_parts_mut(self.off_mesh_cons, off_mesh_con_count) };
499 }
500
501 pub fn data(&self) -> &[u8] {
502 return unsafe { std::slice::from_raw_parts(self.data, self.data_size()) };
503 }
504
505 pub fn data_mut(&mut self) -> &mut [u8] {
506 return unsafe { std::slice::from_raw_parts_mut(self.data, self.data_size()) };
507 }
508
509 pub fn data_size(&self) -> usize {
510 return self.data_size as usize;
511 }
512
513 pub fn next(&self) -> Option<&DtMeshTile> {
514 if self.next.is_null() {
515 return None;
516 } else {
517 return Some(unsafe { mem::transmute(self.next) });
518 }
519 }
520
521 pub fn next_mut(&mut self) -> Option<&mut DtMeshTile> {
522 if self.next.is_null() {
523 return None;
524 } else {
525 return Some(unsafe { mem::transmute(self.next) });
526 }
527 }
528}
529
530pub fn get_detail_tri_edge_flags(tri_flags: u8, edge_index: i32) -> i32 {
531 return ffi::dtGetDetailTriEdgeFlags(tri_flags, edge_index);
532}
533
534#[repr(C)]
539#[derive(Debug, Default, Clone, PartialEq)]
540pub struct DtNavMeshParams {
541 pub orig: [f32; 3],
542 pub tile_width: f32,
543 pub tile_height: f32,
544 pub max_tiles: i32,
545 pub max_polys: i32,
546}
547
548const_assert_eq!(mem::size_of::<DtNavMeshParams>(), 28);
549
550unsafe impl ExternType for DtNavMeshParams {
551 type Id = type_id!("dtNavMeshParams");
552 type Kind = cxx::kind::Trivial;
553}
554
555#[derive(Debug)]
560pub struct DtNavMesh(*mut ffi::dtNavMesh);
561
562impl Drop for DtNavMesh {
563 fn drop(&mut self) {
564 unsafe { ffi::dtFreeNavMesh(self.0) };
565 self.0 = std::ptr::null_mut();
566 }
567}
568
569impl DtNavMesh {
570 pub fn new() -> DtNavMesh {
571 return DtNavMesh(ffi::dtAllocNavMesh());
572 }
573
574 pub(crate) unsafe fn from_ptr(ptr: *mut ffi::dtNavMesh) -> DtNavMesh {
575 return DtNavMesh(ptr);
576 }
577
578 fn inner(&self) -> &ffi::dtNavMesh {
579 return unsafe { &*self.0 };
580 }
581
582 fn inner_mut(&mut self) -> Pin<&mut ffi::dtNavMesh> {
583 return unsafe { Pin::new_unchecked(&mut *self.0) };
584 }
585
586 pub fn as_ptr(&self) -> *const ffi::dtNavMesh {
587 return self.0;
588 }
589
590 pub fn as_mut_ptr(&mut self) -> *mut ffi::dtNavMesh {
591 return self.0;
592 }
593
594 pub fn with_params(params: &DtNavMeshParams) -> Result<DtNavMesh, XError> {
595 let mut mesh = DtNavMesh::new();
596 unsafe { mesh.inner_mut().init_with_params(params) }.to_result()?;
597 return Ok(mesh);
598 }
599
600 pub fn with_data(buf: DtBuf) -> Result<DtNavMesh, XError> {
601 let mut mesh = DtNavMesh::new();
602 unsafe {
603 mesh.inner_mut()
604 .init_with_data(buf.data, buf.len() as i32, DT_TILE_FREE_DATA)
605 }
606 .to_result()?;
607 mem::forget(buf);
608 return Ok(mesh);
609 }
610
611 pub fn params(&self) -> &DtNavMeshParams {
612 return unsafe { &*self.inner().getParams() };
613 }
614
615 pub fn add_tile(&mut self, buf: DtBuf, last_ref: DtTileRef) -> Result<DtTileRef, XError> {
616 let mut re = DtTileRef::default();
617 unsafe {
618 self.inner_mut()
619 .addTile(buf.data, buf.len() as i32, DT_TILE_FREE_DATA, last_ref, &mut re)
620 }
621 .to_result()?;
622 mem::forget(buf);
623 return Ok(re);
624 }
625
626 pub fn remove_tile(&mut self, re: DtTileRef) -> Result<(), XError> {
627 return unsafe { self.inner_mut().removeTile(re, ptr::null_mut(), ptr::null_mut()) }.to_result();
628 }
629
630 pub fn calc_tile_loc(&self, pos: &[f32; 3]) -> [i32; 2] {
631 let mut t: [i32; 2] = [0, 0];
632 unsafe { self.inner().calcTileLoc(pos.as_ptr(), &mut t[0], &mut t[1]) };
633 return t;
634 }
635
636 pub fn get_tile_at(&self, x: i32, y: i32, layer: i32) -> Option<&DtMeshTile> {
637 let tile = unsafe { self.inner().getTileAt(x, y, layer) };
638 if tile.is_null() {
639 return None;
640 } else {
641 return Some(unsafe { mem::transmute(tile) });
642 }
643 }
644
645 pub fn get_tiles_at<'a, 'b: 'a>(&'b self, x: i32, y: i32, tiles: &mut [Option<&'a DtMeshTile>]) -> usize {
646 let count = unsafe {
647 self.inner()
648 .getTilesAt(x, y, tiles.as_mut_ptr() as *mut _, tiles.len() as i32)
649 };
650 return count as usize;
651 }
652
653 pub fn get_tile_ref_at(&self, x: i32, y: i32, layer: i32) -> DtTileRef {
654 return self.inner().getTileRefAt(x, y, layer);
655 }
656
657 pub fn get_tile_ref(&self, tile: &DtMeshTile) -> DtTileRef {
658 return unsafe { self.inner().getTileRef(tile.inner()) };
659 }
660
661 pub fn get_tile_by_ref(&self, re: DtTileRef) -> Option<&DtMeshTile> {
662 let tile = unsafe { self.inner().getTileByRef(re) };
663 if tile.is_null() {
664 return None;
665 } else {
666 return Some(unsafe { mem::transmute(tile) });
667 }
668 }
669
670 pub fn max_tiles(&self) -> i32 {
671 return self.inner().getMaxTiles();
672 }
673
674 pub fn get_tile(&self, i: i32) -> Option<&DtMeshTile> {
675 let tile = unsafe { self.inner().getTile(i) };
676 if tile.is_null() {
677 return None;
678 } else {
679 return Some(unsafe { mem::transmute(tile) });
680 }
681 }
682
683 pub fn get_tile_and_poly_by_ref(&self, re: DtPolyRef) -> Result<(&DtMeshTile, &DtPoly), XError> {
684 let mut tile = std::ptr::null();
685 let mut poly = std::ptr::null();
686 unsafe { self.inner().getTileAndPolyByRef(re, &mut tile, &mut poly) }.to_result()?;
687 return Ok(unsafe { (mem::transmute(tile), &*poly) });
688 }
689
690 pub unsafe fn get_tile_and_poly_by_ref_unsafe(&self, re: DtPolyRef) -> (&DtMeshTile, &DtPoly) {
691 let mut tile = std::ptr::null();
692 let mut poly = std::ptr::null();
693 unsafe { self.inner().getTileAndPolyByRefUnsafe(re, &mut tile, &mut poly) };
694 return (mem::transmute(tile), unsafe { &*poly });
695 }
696
697 pub fn is_valid_poly_ref(&self, re: DtPolyRef) -> bool {
698 return self.inner().isValidPolyRef(re);
699 }
700
701 pub unsafe fn get_poly_ref_base(&self, tile: &DtMeshTile) -> DtPolyRef {
702 return self.inner().getPolyRefBase(tile.inner());
703 }
704
705 pub fn get_off_mesh_connection_poly_end_points(
706 &self,
707 prev_ref: DtPolyRef,
708 poly_ref: DtPolyRef,
709 ) -> Result<([f32; 3], [f32; 3]), XError> {
710 let mut start_pos = [0.0; 3];
711 let mut end_pos = [0.0; 3];
712 unsafe {
713 self.inner()
714 .getOffMeshConnectionPolyEndPoints(prev_ref, poly_ref, &mut start_pos[0], &mut end_pos[0])
715 }
716 .to_result()?;
717 return Ok((start_pos, end_pos));
718 }
719
720 pub fn get_off_mesh_connection_by_ref(&self, re: DtPolyRef) -> &DtOffMeshConnection {
721 return unsafe { &*self.inner().getOffMeshConnectionByRef(re) };
722 }
723
724 pub fn set_poly_flags(&mut self, re: DtPolyRef, flags: u16) -> Result<(), XError> {
725 return self.inner_mut().setPolyFlags(re, flags).to_result();
726 }
727
728 pub fn get_poly_flags(&self, re: DtPolyRef) -> Result<u16, XError> {
729 let mut flags = 0;
730 unsafe { self.inner().getPolyFlags(re, &mut flags) }.to_result()?;
731 return Ok(flags);
732 }
733
734 pub fn set_poly_area(&mut self, re: DtPolyRef, area: u8) -> Result<(), XError> {
735 return self.inner_mut().setPolyArea(re, area).to_result();
736 }
737
738 pub fn get_poly_area(&self, re: DtPolyRef) -> Result<u8, XError> {
739 let mut area = 0;
740 unsafe { self.inner().getPolyArea(re, &mut area) }.to_result()?;
741 return Ok(area);
742 }
743
744 pub unsafe fn get_tile_state_size(&self, tile: &DtMeshTile) -> usize {
745 return self.inner().getTileStateSize(tile.inner()) as usize;
746 }
747
748 pub unsafe fn store_tile_state(&self, re: DtTileRef, data: &mut [u8]) -> Result<(), XError> {
749 return unsafe { ffi::dtmt_storeTileState(self.inner(), re, data.as_mut_ptr(), data.len() as i32) }.to_result();
750 }
751
752 pub unsafe fn restore_tile_state(&mut self, re: DtTileRef, data: &[u8]) -> Result<(), XError> {
753 return unsafe { ffi::dtmt_restoreTileState(self.inner_mut(), re, data.as_ptr(), data.len() as i32) }
754 .to_result();
755 }
756
757 pub fn encode_poly_id(&self, salt: u32, it: u32, ip: u32) -> DtPolyRef {
758 return self.inner().encodePolyId(salt, it, ip);
759 }
760
761 pub unsafe fn decode_poly_id(&self, re: DtPolyRef) -> (u32, u32, u32) {
762 let mut salt = 0;
763 let mut it = 0;
764 let mut ip = 0;
765 self.inner().decodePolyId(re, &mut salt, &mut it, &mut ip);
766 return (salt, it, ip);
767 }
768
769 pub fn decode_poly_id_salt(&self, re: DtPolyRef) -> u32 {
770 return self.inner().decodePolyIdSalt(re);
771 }
772
773 pub fn decode_poly_id_tile(&self, re: DtPolyRef) -> u32 {
774 return self.inner().decodePolyIdTile(re);
775 }
776
777 pub fn decode_poly_id_poly(&self, re: DtPolyRef) -> u32 {
778 return self.inner().decodePolyIdPoly(re);
779 }
780}