richardanaya / conifer

Apache License 2.0
37 stars 4 forks source link

Canvas layers #9

Open nbrr opened 4 years ago

nbrr commented 4 years ago

In the drag example I drew a line to represent the drag. However it stays. We probably want at some point to be able to draw over something in a non destructive way. In the present case, to have a line between the origin and the contact point only, without leaving a trace of the movement. When we set a pixel in Frame, we could associate a layer to it, and then render only the top most pixel.

richardanaya commented 4 years ago

Hmm, interesting idea, this does seem like a really common thing I could imagine people wanting to do.

richardanaya commented 4 years ago

It would be interesting to offer "smart layers" that could also handle input out of the box like fps, mouse cursors, exit buttons, keyboard launcher overlays.

richardanaya commented 4 years ago

brainstorm:

use conifer::prelude::*;
use conifer::helper_layers::fps::*;
use conifer::helper_layers::exit::*;

struct MyLayer { ... }

impl Layer for MyLayer {
  fn run(screen:Screen,input_event:Event,delta_time:usize){
     ...
  }
}

fn main() -> Result<(), Box<dyn Error>> {
   let layers = Layers::build(vec![
      FPSLayer::new(),
      ExitLayer::new(Position::TopRight) ,
      MyLayer::new()
   ]);
    Config::auto()?.run(layers.run);
    Ok(())
}
nbrr commented 4 years ago

I rather had in mind something like:

struct Layer {
    pixels: Vec<Option<u8>>;
    // and maybe a callback to give the layer a special functionality, I think that is what you were going for
    f: Fn<Stuff>
}
pub struct Frame {
    ...
    layers: Vec<(Layer, Depth)> 
    ...
}

Possibly also a Position if the layer doesn't have to be as big as the canvas, this could allow relative positioning but I think that's a question for later.

nbrr commented 4 years ago

Since you have introduced blitting, how can we think about layers? First is it desirable? I see this as a notion of depth, you might want to manipulate objects thinking they are on the same plan, and keep this organization through iterations. But maybe that is not something for the display to know but rather something for the user's universe to worry about? e.g. if they want to keep a button somewhere to close the application, it is their job to keep it on top of everything else when they build the canvas?

richardanaya commented 4 years ago

It's a really great question. There's a part of me that feels blitting is super powerful and could be even more optimized than my simplistic implementation. It could be a solution for most scenarios.

There's a part of me that likes the direction canvas is going, it's just a very efficient way to write to to the array of pixels that's going to eventually be written to the framebuffer.

There's a part of me that would like to build something non-trivial with what we have now, and see if we observe any patterns in what we have to do to make it possible.

I feel like if we try to generalize a Layers concept, we should keep it separate from Canvas.

let layers = Layers();
layers.push(NintendoControlsLayer::new());
layers.push(GameLayer::new());
run(|screen,event|{
    screen.draw_canvas(0,0,layers.flatten_to_canvas());
});

This way we don't force any particular rendering strategy on any one.