Let me illustrate with some code where I am at and what's my problem with mutability at the moment.
I have the following struct:
pub struct SpriteBatcher<'a> {
initial_batch_size: i32,
max_batch_size: i32,
initial_vertex_array_size: i32,
renderer: &'a Canvas<Window>,
graphics_device: &'a GraphicsDevice,
batch_item_list: Vec<SpriteBatchItem<'a>>, /// The list of batch items to process.
batch_item_count: i32, /// Index pointer to the next available SpriteBatchItem in _batchItemList.
index: Vec<i32>, /// Vertex index array. The values in this array never change.
vertex_array: Vec<VertexPositionColorTexture>,
}
For the time being just ignore the contained structs, as that shouldn't really be the issue.
Then I have the following function in the impl
of SpriteBatcher
:
pub fn draw_batch(&'a mut self, sort_mode: SpriteSortMode/*, Effect effect*/, render_state: &'a mut RenderState<'a>) {
// nothing to do
if self.batch_item_count == 0 {
return;
}
// sort the batch items
match sort_mode {
SpriteSortMode::SpriteSortModeTexture => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
SpriteSortMode::SpriteSortModeFrontToBack => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
SpriteSortMode::SpriteSortModeBackToFront => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
_ => self.batch_item_list.sort_by(|a, b| a.cmp(b)),
}
// Determine how many iterations through the drawing code we need to make
let mut batch_index: i32 = 0;
let mut batch_count: i32 = self.batch_item_count;
// Iterate through the batches, doing short.MaxValue sets of vertices only.
while batch_count > 0 {
// setup the vertexArray array
let mut startIndex: i32 = 0;
let mut index: i32 = 0;
let mut tex: Option<&Texture> = None;
let mut numBatchesToProcess: i32 = batch_count;
if numBatchesToProcess > self.max_batch_size {
numBatchesToProcess = self.max_batch_size;
}
{
self.ensure_array_capacity(numBatchesToProcess);
}
// Draw the batches
for i in 0..numBatchesToProcess {
let mut item = &mut self.batch_item_list[batch_index as usize];
// if the texture changed, we need to flush and bind the new texture
let shouldFlush: bool = &**item.texture.as_ref().unwrap() as *const _ != &**tex.as_ref().unwrap() as *const _;
if shouldFlush {
self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);
tex = self.batch_item_list[batch_index as usize].texture;
startIndex = 0;
index = 0;
}
// store the SpriteBatchItem data in our vertexArray
index = index + 1;
self.vertex_array[index as usize] = item.vertexTL;
index = index + 1;
self.vertex_array[index as usize] = item.vertexTR;
index = index + 1;
self.vertex_array[index as usize] = item.vertexBL;
index = index + 1;
self.vertex_array[index as usize] = item.vertexTR;
index = index + 1;
self.vertex_array[index as usize] = item.vertexBR;
index = index + 1;
self.vertex_array[index as usize] = item.vertexBL;
// Release the texture.
item.set_texture(None);
}
// flush the remaining vertexArray data
self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);
// Update our batch count to continue the process of culling down
// large batches
batch_count -= numBatchesToProcess;
}
// return items to the pool.
self.batch_item_count = 0;
}
And the signature of flush_vertex_array
is the following:
pub fn flush_vertex_array(&self, start: i32, end: i32 /*, Effect effect*/, texture: Option<&'a Texture<'a>>, render_state: &'a mut RenderState<'a>)
As you can see, with let mut item = &mut self.batch_item_list[batch_index as usize];
I'm borrowing one of the element of the vector as mutable.
Next I'm calling self.flush_vertex_array(startIndex, index /*, effect*/, tex, render_state);
where self is passed as immutable so that an immutable borrow occurs, but since I mutably borrowed a field of self, this leads to an error.
I would like to find a correct way to write this kind of function in Rust. Any help is really appreciated as I'm banging my head against the borrow checker at the moment.