1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
use crate::{
IntoSfResult, SfResult,
cpp::FBox,
ffi::graphics as ffi,
graphics::{Drawable, PrimitiveType, RenderStates, RenderTarget, Vertex},
};
/// Usage specifiers for a [`VertexBuffer`]
///
/// If data is going to be updated once or more every frame,
/// set the usage to `Stream`. If data is going to be set once and used
/// for a long time without being modified, set the usage to `Static`.
/// For everything else `Dynamic` should be a good compromise.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct VertexBufferUsage(pub(super) ffi::sfVertexBufferUsage);
impl VertexBufferUsage {
/// Constantly changing data.
pub const STREAM: Self = Self(ffi::sfVertexBufferUsage::Stream);
/// Occasionally changing data.
pub const DYNAMIC: Self = Self(ffi::sfVertexBufferUsage::Dynamic);
/// Rarely changing data.
pub const STATIC: Self = Self(ffi::sfVertexBufferUsage::Static);
}
decl_opaque! {
/// Define a set of one or more 2D primitives stored in graphics memory
pub VertexBuffer;
}
impl VertexBuffer {
/// Create a new initialized vertex buffer
///
/// # Arguments
/// * `primitive_type` - The type of the `VertexBuffer`
/// * `vertex_count` - The maximal number of vertex
pub fn new(
primitive_type: PrimitiveType,
vertex_count: usize,
usage: VertexBufferUsage,
) -> SfResult<FBox<Self>> {
let mut new = FBox::new(unsafe { ffi::sfVertexBuffer_new() }).into_sf_result()?;
new.set_usage(usage);
new.set_primitive_type(primitive_type);
new.recreate(vertex_count)?;
Ok(new)
}
/// Recreate the vertex buffer.
///
/// Recreates the vertex buffer and allocates enough graphics memory to hold
/// vertexCount vertices.
/// Any previously allocated memory is freed in the process.
///
/// In order to deallocate previously allocated memory pass 0 as vertexCount.
/// Don't forget to recreate with a non-zero value when graphics memory should be
/// allocated again.
pub fn recreate(&mut self, vertex_count: usize) -> SfResult<()> {
unsafe { ffi::sfVertexBuffer_create(self, vertex_count) }.into_sf_result()
}
/// Return the vertex count of a vertex buffer
///
/// Return the number of vertices in the buffer
#[must_use]
pub fn vertex_count(&self) -> usize {
unsafe { ffi::sfVertexBuffer_getVertexCount(self) }
}
/// Update a part of the buffer from an array of vertices.
///
/// `offset` is specified as the number of vertices to skip from the beginning of the buffer.
///
/// If `offset` is `0` and `vertices.len()` is equal to the size of the currently created buffer, its
/// whole contents are replaced.
///
/// If `offset` is `0` and `vertices.len()` is greater than the size of the currently created buffer, a
/// new buffer is created containing the vertex data.
///
/// If `offset` is `0` and `vertices.len()` is less than the size of the currently created buffer, only
/// the corresponding region is updated.
///
/// If `offset` is not `0` and `offset + vertices.len()` is greater than the size of the currently
/// created buffer, the update fails.
///
/// No additional check is performed on the size of the vertex array, passing invalid arguments
/// will lead to undefined behavior.
///
/// # Arguments
/// * vertices - Array of vertices to copy in the buffer
/// * offset - Offset in the buffer to copy to
///
/// Return True if the update was successful
pub fn update(&mut self, vertices: &[Vertex], offset: u32) -> SfResult<()> {
unsafe {
ffi::sfVertexBuffer_update(self, vertices.as_ptr().cast(), vertices.len(), offset)
}
.into_sf_result()
}
/// Copy the contents of another buffer into this buffer.
///
/// # Arguments
/// * other - Vertex buffer whose contents to copy into this vertex buffer
pub fn update_from_vertex_buffer(&mut self, other: &VertexBuffer) -> SfResult<()> {
unsafe { ffi::sfVertexBuffer_updateFromVertexBuffer(self, other) }.into_sf_result()
}
/// Swap the contents of this vertex buffer with those of another.
///
/// # Arguments
/// * other - Instance to swap with
pub fn swap(&mut self, other: &mut VertexBuffer) {
unsafe {
ffi::sfVertexBuffer_swap(self, other);
}
}
/// Get the underlying OpenGL handle of the vertex buffer.
///
/// You shouldn't need to use this function, unless you have very specific stuff to implement
/// that SFML doesn't support, or implement a temporary workaround until a bug is fixed.
///
/// Return OpenGL handle of the vertex buffer or 0 if not yet created
#[must_use]
pub fn native_handle(&self) -> u32 {
unsafe { ffi::sfVertexBuffer_getNativeHandle(self) }
}
/// Get the type of primitives drawn by the vertex buffer.
///
/// Return Primitive type
#[must_use]
pub fn primitive_type(&self) -> PrimitiveType {
unsafe { PrimitiveType(ffi::sfVertexBuffer_getPrimitiveType(self)) }
}
/// Set the type of primitives to draw.
///
/// This function defines how the vertices must be interpreted when it's time to draw them.
///
/// The default primitive type is `Points`.
///
/// # Arguments
/// * `primitive_type` - Type of primitive
pub fn set_primitive_type(&mut self, primitive_type: PrimitiveType) {
unsafe {
ffi::sfVertexBuffer_setPrimitiveType(self, primitive_type.0);
}
}
/// Get the usage specifier of this vertex buffer.
///
/// Return Usage specifier
#[must_use]
pub fn usage(&self) -> VertexBufferUsage {
unsafe { VertexBufferUsage(ffi::sfVertexBuffer_getUsage(self)) }
}
/// Set the usage specifier of this vertex buffer.
///
/// This function provides a hint about how this vertex buffer is going to be used in terms of
/// data update frequency.
///
/// After changing the usage specifier, the vertex buffer has to be updated with new data for
/// the usage specifier to take effect.
///
/// The default primitive type is `Stream`.
///
/// # Arguments
/// * usage - Usage specifier
pub fn set_usage(&mut self, usage: VertexBufferUsage) {
unsafe { ffi::sfVertexBuffer_setUsage(self, usage.0) }
}
/// Bind a vertex buffer for rendering.
///
/// This function is not part of the graphics API, it mustn't be used when drawing SFML
/// entities. It must be used only if you mix `sf::VertexBuffer` with OpenGL code.
///
#[cfg_attr(feature = "ci-headless", doc = "```no_run")]
#[cfg_attr(not(feature = "ci-headless"), doc = "```")]
/// use sfml::graphics::{PrimitiveType, VertexBuffer, VertexBufferUsage};
///
/// let mut vb1 = VertexBuffer::new(PrimitiveType::TRIANGLES, 32, VertexBufferUsage::STATIC).unwrap();
/// let mut vb2 = VertexBuffer::new(PrimitiveType::QUADS, 12, VertexBufferUsage::DYNAMIC).unwrap();
///
/// // ...
///
/// VertexBuffer::bind(Some(&vb1));
/// // draw OpenGL stuff that use vb1...
/// VertexBuffer::bind(Some(&vb2));
/// // draw OpenGL stuff that use vb2...
/// VertexBuffer::bind(None);
/// // draw OpenGL stuff that use no vertex buffer...
/// ```
///
/// # Arguments
/// * vb - Vertex buffer to use; None to use no vertex buffer.
pub fn bind(vb: Option<&VertexBuffer>) {
unsafe {
if let Some(vertex_buffer) = vb {
ffi::sfVertexBuffer_bind(vertex_buffer);
} else {
ffi::sfVertexBuffer_bind(std::ptr::null());
}
}
}
/// Tell whether or not the system supports vertex buffers.
///
/// This function should always be called before using the vertex buffer features. If it
/// returns false, then any attempt to use `VertexBuffer` will fail.
///
/// Return True if vertex buffers are supported, false otherwise
#[must_use]
pub fn available() -> bool {
unsafe { ffi::sfVertexBuffer_isAvailable() }
}
}
impl ToOwned for VertexBuffer {
type Owned = FBox<Self>;
fn to_owned(&self) -> Self::Owned {
let ptr = unsafe { ffi::sfVertexBuffer_cpy(self) };
match FBox::new(ptr) {
Some(new) => new,
None => panic!("Failed to clone VertexBuffer"),
}
}
}
impl Drop for VertexBuffer {
fn drop(&mut self) {
unsafe {
ffi::sfVertexBuffer_del(self);
}
}
}
impl Drawable for VertexBuffer {
fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
&'a self,
target: &mut dyn RenderTarget,
states: &RenderStates<'texture, 'shader, 'shader_texture>,
) {
target.draw_vertex_buffer(self, states)
}
}