Simple OpenGL GUI Framework User Interaction Advice? [closed]

ぃ、小莉子 提交于 2019-12-29 09:13:11

问题


I'm designing a simple GUI framework from scratch as a project, using OpenGL and nothing else external and need some advice on how I might implement user interaction.

Basically, I've a base class GUIItem from which all elements inherit. This gives each item some basic variables such as position, a vector to contain child elements as well as some basic functions for mouse movement and clicking.

All elements are setup as above, with their relevant member variables.

What I'm struggling with is how to implement user interaction properly. In my window manager I would create a new instance of an item, say GUIButton and call it button1. The window manager would, upon a click occurring, iterate through its list of elements and any child elements they may have, calculating a rectangular area around the object based on its coordinates, height and width, then running any "on click" function associated with said item, like change the value of textlabel1.

Firstly, is there a better way to do this calculation? It would work for rectangular elements but spherical objects and others would have a much larger erroneous area which could be clicked. Ideally I would check pixels but I've no real idea how that would be achieved. I've heard about but never used GLUT (my project only allows use of this for handling mouse/keyboard interaction though). Does GLUT provide anything to assist in this case?

My main issue is with handling what would occur when an "On click" event actually occurred. At the moment GUIButton for example, has an "On click" function built in, so as far as I can see, I'd have to do something like make it a virtual function, meaning that each new button I created would have to have its own class just to overwrite the "on click" function and each instance of a button would be an instance of a unique class that simply inherited off of GUIButton. This seems messy to me, as I've no idea where I would store all those classes, and it seems a lot of extra code. Would I be creating a button1.cpp and button1.h file?

Any advice on this really would be welcome as I'm new to C++, OpenGL and it's the first time I've been exposed to GUI programming and there's not a lot to go on when an existing GUI framework is the usual choice.


回答1:


if you want something stupidly simple and fast then you could:

  1. create shadow screen buffer containing ID/index/pointer instead of color
  2. pre-render this buffer

    Just render each of your visual component to it but instead coloring/texturing just fill in the ID/index/pointer of rendered component. Do not forget to clear this with some NULL first ... After this you should have mask of your components. You need to do this just once ...

  3. On mouse events

    you simply convert mouse coordinates to the shadow screen space and pick the value. If it is NULL then you clicked or whatever on empty area. If it contains ID instead update or call the callbacks for component ID. if you have a list of all components then ID can be the list index, otherwise use its actual pointer or encode in style (component_type, component_index). As you can see this is pretty fast O(1) item selection no matter how many components you have ... The shadow screen can have different resolution then your actual screen (to preserve memory).

This have pixel perfect mouse selection accuracy no matter the shape of your components without the need for nested component search loops.

[Notes]

As I did this stuff here are some hints:

create a window class containing configuration of your components for single screen. Programs have usually more screens with different set of components and doing dynamically the screens over and over again just because you switch page/screen sucks.

use separate list of components one list per component type.

create IDE editor for your windows see drag & drop example in C++ it might get handy for this. Add get,set functions controlled by string/enum or flag to easy obtain/change properties to make Object Inspector possible. Also this is how mine IDE looks like:

The window is saved from IDE directly as C++ code I can just copy to my App. This is the above example without the knob (forgot to save it):

//---------------------------------------------------------------------------
// OpenGL VCL window beg: win
    win.grid.allocate(0);
    win.grid.num=0;
    win.scale.allocate(0);
    win.scale.num=0;
    win.button.allocate(0);
    win.button.num=0;
    win.knob.allocate(0);
    win.knob.num=0;
    win.scrollbar.allocate(3);
    win.scrollbar.num=3;
    win.scrollbar[0].x0=200.0;
    win.scrollbar[0].y0=19.0;
    win.scrollbar[0].xs=256.0;
    win.scrollbar[0].ys=16.0;
    win.scrollbar[0].fxs=8.0;
    win.scrollbar[0].fys=19.0;
    win.scrollbar[0].name="_vcl_scrollbar0";
    win.scrollbar[0].hint="";
    win.scrollbar[0].min=0.000;
    win.scrollbar[0].max=1.000;
    win.scrollbar[0].pos=0.000;
    win.scrollbar[0].dpos=0.100;
    win.scrollbar[0].horizontal=1;
    win.scrollbar[0].style=0;
    win.scrollbar[0].resize();
    win.scrollbar[1].x0=200.0;
    win.scrollbar[1].y0=45.0;
    win.scrollbar[1].xs=256.0;
    win.scrollbar[1].ys=16.0;
    win.scrollbar[1].fxs=8.0;
    win.scrollbar[1].fys=19.0;
    win.scrollbar[1].name="_vcl_scrollbar1";
    win.scrollbar[1].hint="";
    win.scrollbar[1].min=0.000;
    win.scrollbar[1].max=1.000;
    win.scrollbar[1].pos=0.000;
    win.scrollbar[1].dpos=0.100;
    win.scrollbar[1].horizontal=1;
    win.scrollbar[1].style=0;
    win.scrollbar[1].resize();
    win.scrollbar[2].x0=200.0;
    win.scrollbar[2].y0=70.0;
    win.scrollbar[2].xs=256.0;
    win.scrollbar[2].ys=16.0;
    win.scrollbar[2].fxs=8.0;
    win.scrollbar[2].fys=19.0;
    win.scrollbar[2].name="_vcl_scrollbar2";
    win.scrollbar[2].hint="";
    win.scrollbar[2].min=0.000;
    win.scrollbar[2].max=1.000;
    win.scrollbar[2].pos=0.000;
    win.scrollbar[2].dpos=0.100;
    win.scrollbar[2].horizontal=1;
    win.scrollbar[2].style=0;
    win.scrollbar[2].resize();
    win.interpbox.allocate(0);
    win.interpbox.num=0;
    win.dblist.allocate(0);
    win.dblist.num=0;
// OpenGL VCL window end: win
//---------------------------------------------------------------------------

Look at images here plotting real time Data on Oscillocope for some ideas (I got this working for both GDI and OpenGL)

It is better to use pixel units instead of OpenGL <-1,+1> screen units for better visual quality and editing comfort.



来源:https://stackoverflow.com/questions/34247742/simple-opengl-gui-framework-user-interaction-advice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!