egui_net_ffi/
lib.rs

1//! Allows for efficiently communicating with a C#-side `egui` Context from [Egui.NET](https://github.com/DouglasDwyer/Egui.NET).
2
3use std::ops::Deref;
4
5use egui::*;
6use egui::epaint::*;
7use serde::*;
8
9/// Allows for passing `egui` data back and forth with C#.
10#[repr(C)]
11pub struct EguiFfi {
12    /// The serialized bytes of the most recent [`FullOutput`].
13    full_output: FfiVec<u8>,
14    /// The meshes from the most recent call to [`Context::tessellate`].
15    meshes: FfiVec<(Rect, FfiTextureId, FfiVec<u32>, FfiVec<Vertex>)>,
16    /// The most recent raw input.
17    raw_input: FfiVec<u8>,
18}
19
20impl EguiFfi {
21    /// Gets the most recent [`FullOutput`]. [`FullOutput::shapes`] and
22    /// [`FullOutput::viewport_output`] are not included.
23    pub fn full_output(&self) -> FullOutput {
24        bincode::deserialize::<FullOutput2>(&self.full_output)
25            .expect("Failed to deserialize FullOutput").into()
26    }
27
28    /// Sets the most recent [`FullOutput`].
29    pub fn set_full_output(&mut self, full_output: FullOutput) {
30        self.full_output = bincode::serialize(&FullOutput2::from(full_output))
31            .expect("Failed to serialize FullOutput").into();
32    }
33
34    /// Gets the most recent [`RawInput`].
35    pub fn raw_input(&self) -> RawInput {
36        bincode::deserialize(&self.raw_input)
37            .expect("Failed to deserialize RawInput")
38    }
39
40    /// Sets the most recent [`RawInput`].
41    pub fn set_raw_input(&mut self, raw_input: RawInput) {
42        self.raw_input = bincode::serialize(&raw_input)
43            .expect("Failed to serialize RawInput").into();
44    }
45
46    /// Gets the most recent output of [`Context::tessellate`].
47    pub fn meshes(&self) -> Vec<(Rect, Mesh)> {
48        self.meshes.iter().map(|(clip_rect, texture_id, indices, vertices)|
49            (*clip_rect, Mesh {
50                indices: indices.to_vec(),
51                texture_id: (*texture_id).into(),
52                vertices: vertices.to_vec()
53            })).collect()
54    }
55
56    /// Sets the most recent output of [`Context::tessellate`].
57    pub fn set_meshes(&mut self, meshes: impl IntoIterator<Item = (Rect, Mesh)>) {
58        self.meshes = meshes.into_iter()
59            .map(|(clip_rect, mesh)| (clip_rect, mesh.texture_id.into(), mesh.indices.into(), mesh.vertices.into()))
60            .collect::<Vec<_>>().into()
61    }
62}
63
64impl Default for EguiFfi {
65    fn default() -> Self {
66        let mut result = Self {
67            full_output: Vec::new().into(),
68            meshes: Vec::new().into(),
69            raw_input: Vec::new().into()
70        };
71
72        result.set_full_output(FullOutput::default());
73        result.set_raw_input(RawInput::default());
74        
75        result
76    }
77}
78
79/// Holds the serializable members of [`FullOutput`]
80/// (since [`FullOutput`] is not serializable).
81#[derive(Clone, Serialize, Deserialize)]
82struct FullOutput2 {
83    /// The [`FullOutput::platform_output`] field.
84    pub platform_output: PlatformOutput,
85    /// The [`FullOutput::textures_delta`] field.
86    pub textures_delta: TexturesDelta,
87    /// The [`FullOutput::pixels_per_point`] field.
88    pub pixels_per_point: f32
89}
90
91impl From<FullOutput2> for FullOutput {
92    fn from(value: FullOutput2) -> Self {
93        Self {
94            pixels_per_point: value.pixels_per_point,
95            platform_output: value.platform_output,
96            textures_delta: value.textures_delta,
97            ..Default::default()
98        }
99    }
100}
101
102impl From<FullOutput> for FullOutput2 {
103    fn from(value: FullOutput) -> Self {
104        Self {
105            pixels_per_point: value.pixels_per_point,
106            platform_output: value.platform_output,
107            textures_delta: value.textures_delta
108        }
109    }
110}
111
112/// An FFI-compatible version of [`TextureId`].
113#[derive(Copy, Clone, Debug)]
114#[repr(C)]
115struct FfiTextureId {
116    /// The type of ID.
117    pub kind: TextureIdKind,
118    /// The integer identifier.
119    pub id: u64
120}
121
122impl From<TextureId> for FfiTextureId {
123    fn from(value: TextureId) -> Self {
124        match value {
125            TextureId::Managed(id) => Self {
126                kind: TextureIdKind::Managed,
127                id
128            },
129            TextureId::User(id) => Self {
130                kind: TextureIdKind::User,
131                id
132            }
133        }
134    }
135}
136
137impl From<FfiTextureId> for TextureId {
138    fn from(value: FfiTextureId) -> Self {
139        match value.kind {
140            TextureIdKind::Managed => TextureId::Managed(value.id),
141            TextureIdKind::User => TextureId::User(value.id),
142        }
143    }
144}
145
146/// Identifies a variant of [`TextureId`].
147#[derive(Copy, Clone, Debug)]
148#[repr(C)]
149enum TextureIdKind {
150    /// [`TextureId::Managed`]
151    Managed,
152    /// [`TextureId::User`]
153    User
154}
155
156/// A [`Vec`] that can be passed across FFI boundaries.
157#[derive(Debug)]
158#[repr(C)]
159struct FfiVec<T> {
160    /// Pointer to the allocation.
161    ptr: *mut T,
162    /// The length of the vector.
163    len: usize,
164    /// The capacity of the vector.
165    capacity: usize,
166    /// The function to call in order to free the vector.
167    on_free: unsafe extern "C" fn(&mut Self)
168}
169
170impl<T> FfiVec<T> {
171    /// Frees the vector using its original allocator.
172    /// 
173    /// # Safety
174    /// 
175    /// This function should be called a single time on each valid [`FfiVec`].
176    unsafe extern "C" fn on_free(&mut self) {
177        // Safety: this s
178        unsafe { Vec::from_raw_parts(self.ptr, self.len, self.capacity); }
179    }
180}
181
182impl<T> From<Vec<T>> for FfiVec<T> {
183    fn from(mut value: Vec<T>) -> Self {
184        let ptr = value.as_mut_ptr();
185        let len = value.len();
186        let capacity = value.capacity();
187        std::mem::forget(value);
188        Self {
189            ptr,
190            len,
191            capacity,
192            on_free: Self::on_free
193        }
194    }
195}
196
197impl<T> Deref for FfiVec<T> {
198    type Target = [T];
199
200    fn deref(&self) -> &Self::Target {
201        unsafe {
202            std::slice::from_raw_parts(self.ptr, self.len)
203        }
204    }
205}
206
207impl<T> Drop for FfiVec<T> {
208    fn drop(&mut self) {
209        unsafe {
210            (self.on_free)(self)
211        }
212    }
213}
214
215unsafe impl<T: Send> Send for FfiVec<T> {}
216unsafe impl<T: Send> Sync for FfiVec<T> {}