over the last week I experimented with drawing QWidgets ontop of the 3d scene with transparent background. I noticed from some unused code that you tried this before. The problem, as you know, is that you can not simply add child widgets to the 3d widget as the 3d content is unknown to the qt render system and therefore all child widgets get some weird background. If you bring in transperency you can't see "through" the child to the 3d scene but only see gibberish.
I found 2 ways to make this working, but before going any further with a real implementation I like to hear your opinion about the topic itself and what would be a sensible approach. Let me explain both methods:
1. Draw the widgets inside the 3d scene
---------------------------------------------------
it is possible to Initialise a QPainter on the openGL context and use it to render all qt stuff with opengl commands. This makes it possible to render arbitrary QWidgets directly into the 3d scene from within the current render code View3dInventorViewer::renderScene(). (pseudocode as I don't have acces to my code right now):
Code: Select all
glPushAttrip(Atr_all)
QPainter painter(getGlWidget());
my3dwidget->render(painter);
painter.end();
glPopAttrip()
- Transperency and all works very nicely.
- You can draw anything qt can draw directly into the scene, basicly no adjustment of freecad render code needed
Disadvantage:
- As the widget is hidden it won't get any events from qt. So to make it behave as normal you need to forward all events. I made this work for mouse events so that you can use the widgets, but it is impossible to get updates from within the widget. It all feels a bit flaky
- every widget change need a full scene redraw inclusing a redraw of every other widget added to the scene, which makes the widgets slow for big scenes
- every scene update need a full widget redraw, which makes the scene update a bit slower
2. Make the 3d content known to qt drawing system
-------------------------------------------------------------------
If we want standart qt parent-child relationship to get all evetn handling and stuff one need to make the 3d content known to qt. I made this work by rendering the 3d scene to a framebuffer (already supported by freecad) and then draw this framebuffer into a qwidget. Than you can add childs to this widget and transperency and stuff works nicely.
Advantage:
- Transperency and all works very nicely.
- Full qt event handling
- QT update optimisations: Only the updated widget gets redrawn, not the whole scene or any other widget
- Widgets stay responsive even for very big scenes
- rednering the scene does not need to render widgets
Disadvantage:
- Needs quite intrusive changes to freecad render scene (as the normal render code would be obsolede, only the framebuffer code would be needed)
- rendering to framebuffer may be slower or have some disadvantages not know yet as it is not widly used by freecad
In my opinion method two is more promising, but maybe too intrusive? Or is this whole conept of overlay widgets something you would rather not add to freecad? I would realy love to have the possibility to use qidgets ontop of the 3d scene some day, so I look forward to hear your opinion.
Stefan