recastnavigation_rs/detour/
mesh.rs

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//
163// DtPoly
164//
165
166#[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//
208// DtPolyDetail
209//
210
211#[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//
228// DtLink
229//
230
231#[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//
250// DtBVNode
251//
252
253#[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//
269// DtOffMeshConnection
270//
271
272#[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//
291// DtMeshHeader
292//
293
294#[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//
328// DtMeshTile
329//
330
331#[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//
535// DtNavMeshParams
536//
537
538#[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//
556// DtNavMesh
557//
558
559#[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}