PistonDevelopers / gfx_text

Draw text for gfx using freetype
http://docs.piston.rs/gfx_text/gfx_text/
MIT License
22 stars 12 forks source link

Provide non-Canvas API as an alternative #4

Closed kvark closed 9 years ago

kvark commented 9 years ago

Canvas should not be the only way to use this library. It would be more flexible to work with Stream and Factory types, while leaving the canvas API redirecting to them for convenience. See gfx-debug-draw for an example. Note: this will look better when factories start carrying their own capabilities.

Kagami commented 9 years ago

Yea, at first I tried to make an API which returns just batch, as you recommended. Something like this:

canvs.draw(text.get_batch(&canvas.factory, &canvas.output))

But it turned out Rust's borrow checker doesn't allow to do this, you need either:

  1. Create batch as a separate step, assign it to some variable and pass it to canvas.draw
  2. Pass three variables: renderer, factory and output, render it inside the library and return just draw result to the user

gfx_debug_draw uses the second variant. We can provide the same method, but it looks too inconvenient for the end-user IMO. Any suggestions?

Btw, canvas used only for rendering, you provide just factory on initialize.

kvark commented 9 years ago

But it turned out Rust's borrow checker doesn't allow to do this, you need either:

Could you post a full error message and some code, maybe right here?

Btw, canvas used only for rendering, you provide just factory on initialize.

Oh, right, that's nice.

kvark commented 9 years ago

I've refined gfx-debug-draw initialization and rendering. Device is no longer needed for the new(), since gfx::Factory carries the capabilities as well.

Please see https://github.com/PistonDevelopers/gfx-debug-draw/pull/38 for the details.

Kagami commented 9 years ago

Could you post a full error message and some code, maybe right here?

With that function inside lib:

pub fn get_batch<
    F: Factory<R>,
    O: Output<R>,
> (
    &mut self,
    factory: &mut F,
    output: &mut O,
) -> gfx::batch::OwnedBatch<ShaderParams<R>> {
    let ver_len = self.vertex_data.len();
    let ver_buf_len = self.vertex_buffer.len();
    let ind_len = self.index_data.len();
    let ind_buf_len = self.index_buffer.len();

    // Reallocate buffers if there is no enough space for data.
    if ver_len > ver_buf_len {
        self.vertex_buffer = factory.create_buffer(
            grow_buffer_size(ver_buf_len, ver_len),
            gfx::BufferUsage::Dynamic);
    }
    if ind_len > ind_buf_len {
        self.index_buffer = create_index_buffer(
            factory,
            grow_buffer_size(ind_buf_len, ind_len),
            gfx::BufferUsage::Dynamic);
    }
    // Move vertex/index data.
    factory.update_buffer(&self.vertex_buffer, &self.vertex_data, 0);
    update_index_buffer(factory, &self.index_buffer, &self.index_data, 0);
    // Clear state.
    self.vertex_data.clear();
    self.index_data.clear();

    let nv = ind_len as gfx::VertexCount;
    let mesh = gfx::Mesh::from_format(self.vertex_buffer.clone(), nv);
    let slice = self.index_buffer.to_slice(PrimitiveType::TriangleList);
    self.params.screen_size = {
        let (w, h) = output.get_size();
        [w as f32, h as f32]
    };
    // Only as an example.
    gfx::batch::OwnedBatch::new(
        mesh,
        self.program.clone(),
        self.params.clone()
    ).unwrap()
}

And that usage in example:

canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));

I get this error message:

examples/styles.rs:46:49: 46:63 error: cannot borrow `canvas.factory` as mutable more than once at a time
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                                                                      ^~~~~~~~~~~~~~
examples/styles.rs:46:9: 46:15 note: previous borrow of `canvas` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `canvas` until the borrow ends
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                              ^~~~~~
examples/styles.rs:46:85: 46:85 note: previous borrow ends here
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                                                                                                         ^
examples/styles.rs:46:70: 46:83 error: cannot borrow `canvas.output` as mutable more than once at a time
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                                                                                           ^~~~~~~~~~~~~
examples/styles.rs:46:9: 46:15 note: previous borrow of `canvas` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `canvas` until the borrow ends
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                              ^~~~~~
examples/styles.rs:46:85: 46:85 note: previous borrow ends here
examples/styles.rs:46         canvas.draw(&normal_text.get_batch(&mut canvas.factory, &mut canvas.output));
                                                                                                         ^
error: aborting due to 2 previous errors

I was able to make get_batch work only with this:

let batch = normal_text.get_batch(&mut canvas.factory, &mut canvas.output);
canvas.draw(&batch);

or this:

canvas.renderer.draw(
    &normal_text.get_batch(&mut canvas.factory, &mut canvas.output),
    &canvas.output,
);

which are both quite inconvenient to use in my opinion.

I've refined gfx-debug-draw initialization and rendering

Nice, I didn't know you can use Stream for both drawing and getting the output dimensions. If we won't able to manage get_batch I will replace canvas with stream too. It's not so straightforward as get_batch but still better than the current variant with canvas and simpler.