memononen / nanovg

Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.
zlib License
5.06k stars 767 forks source link

Multiple scissors #652

Open Miska711 opened 1 year ago

Miska711 commented 1 year ago

Hi people,

I have situation when I need two scissors. I create the list of multiline textviews placed on scrollview.

First scissor cuts text lines of textview to match it's width and height. This works well, I implemented it without issues. Then I place several textviews on scrollview. And textviews should be scissored second time to match width and height of the scrollview. This I still cant get to work.

Can someone help me please? Is it possible?

mulle-nat commented 1 year ago

If you first set the scissor for the scrollview and then for each textview, you do save the context, then intersect the scrollview scissor with the textview scissor and after drawing you restore the state, wouldn't that work ?

Miska711 commented 1 year ago

Hm, seems it does not work. Here is pseudocode how i do it

void draw() {
  nvgBeginFrame();
    scrollView->draw();
  nvgEndFrame();
}

void ScrollView::draw() {
  nvgScissor(vg, x, y, w, h);

  for (int i=0; i< 10; i++) {
     textView[i]->draw();
  }
}

void TextView::draw() {
  nvgSave(vg);
  nvgScissor(vg, x, y, w, h);
  nvgText(vg, x,y, "text", NULL); 
  nvgRestore(vg);
}

EDIT: I replaced nvgScissor in TextView with nvgIntersectScissor and it seems to work. Thank you.

Btw, I start my "void draw()" function, which is main application drawing loop with void nvgBeginFrame. And between nvgBeginFrame and nvgEndFrame I mix my own drawing functions using standard opengl es 2.0 commands and nanovg commands. I experienced few problems, which I work-arounded somehow. Should I avoid it? Instead, should I split it and use nanovg drawing in multiple local nvgBeginFrame/nvgEndFrame blocks?

mulle-nat commented 1 year ago

nanovg collects all the draw commands and then at nvgEndFrame paints them all at once. When you mix OpenGL with nanovg, you can draw on top (after nvgEndFrame) or below (before) it. It just gets confusing in the long run, if you don't have a clean separation of OpenGL drawing and nanovg. Because you see draw commands, which look like they are intertwined but actually they are not. So I would go with multiple nvgBeginFrame/nvgEndFrame blocks.