Fix viewport & window issues (#2630)

* Add support for multiple windows & viewports
With correct rendering of both Scene and Overlays/GUI.
GUI is restricted to either the first window or any other windows tagged
with "GUI", overlays are drawn on all windows/viewports.

Closes #2542 and #1645
This commit is contained in:
Joakim Kilby
2023-05-17 22:02:47 +02:00
committed by GitHub
parent f613b6651d
commit ca4b6d2ce2
9 changed files with 112 additions and 37 deletions
+73 -21
View File
@@ -264,12 +264,12 @@ void checkJoystickStatus() {
}
bool isGuiWindow(sgct::Window* window) {
if (Engine::instance().windows().size() == 1) {
// If we only have one window, assume it's also the GUI window.
// It might not have been given the 'GUI' tag
return true;
if (global::windowDelegate->hasGuiWindow()) {
return window->hasTag("GUI");
}
return window->hasTag("GUI");
const sgct::Window* first = Engine::instance().windows().front().get();
return window->id() == first->id();
}
//
@@ -742,13 +742,6 @@ void setSgctDelegateFunctions() {
sgctDelegate.currentSubwindowSize = []() {
ZoneScoped;
if (currentWindow->viewports().size() > 1) {
const Viewport& viewport = *currentWindow->viewports().front();
return glm::ivec2(
currentWindow->resolution().x * viewport.size().x,
currentWindow->resolution().y * viewport.size().y
);
}
switch (currentWindow->stereoMode()) {
case Window::StereoMode::SideBySide:
case Window::StereoMode::SideBySideInverted:
@@ -764,26 +757,20 @@ void setSgctDelegateFunctions() {
);
default:
return glm::ivec2(
currentWindow->resolution().x,
currentWindow->resolution().y
currentWindow->resolution().x * currentViewport->size().x,
currentWindow->resolution().y * currentViewport->size().y
);
}
};
sgctDelegate.currentDrawBufferResolution = []() {
ZoneScoped;
Viewport* viewport = currentWindow->viewports().front().get();
const Viewport* viewport = dynamic_cast<const Viewport*>(currentViewport);
if (viewport != nullptr) {
if (viewport->hasSubViewports() && viewport->nonLinearProjection()) {
ivec2 dim = viewport->nonLinearProjection()->cubemapResolution();
return glm::ivec2(dim.x, dim.y);
}
else if (currentWindow->viewports().size() > 1) {
// @TODO (abock, 2020-04-09) This should probably be based on the current
// viewport?
ivec2 dim = currentWindow->finalFBODimensions();
return glm::ivec2(dim.x * viewport->size().x, dim.y * viewport->size().y);
}
else {
ivec2 dim = currentWindow->finalFBODimensions();
return glm::ivec2(dim.x, dim.y);
@@ -800,12 +787,43 @@ void setSgctDelegateFunctions() {
}
return glm::ivec2(-1, -1);
};
sgctDelegate.currentViewportResolution = []() {
ZoneScoped;
if (currentViewport != nullptr) {
ivec2 res = currentWindow->resolution();
vec2 size = currentViewport->size();
return glm::ivec2(size.x * res.x, size.y * res.y);
}
return glm::ivec2(-1, -1);
};
sgctDelegate.dpiScaling = []() {
ZoneScoped;
vec2 scale = currentWindow->scale();
return glm::vec2(scale.x, scale.y);
};
sgctDelegate.firstWindowResolution = []() {
ZoneScoped;
sgct::Window* window = Engine::instance().windows().front().get();
return glm::ivec2(window->resolution().x, window->resolution().y);
};
sgctDelegate.guiWindowResolution = []() {
ZoneScoped;
const Window* guiWindow = nullptr;
for (const std::unique_ptr<Window>& window : Engine::instance().windows()) {
if (window->hasTag("GUI")) {
guiWindow = window.get();
break;
}
}
if (!guiWindow) {
guiWindow = Engine::instance().windows().front().get();
}
return glm::ivec2(guiWindow->resolution().x, guiWindow->resolution().y);
};
sgctDelegate.osDpiScaling = []() {
ZoneScoped;
@@ -901,6 +919,11 @@ void setSgctDelegateFunctions() {
return currentWindow->id();
};
sgctDelegate.firstWindowId = []() {
ZoneScoped;
return Engine::instance().windows().front()->id();
};
sgctDelegate.openGLProcedureAddress = [](const char* func) {
ZoneScoped;
@@ -959,6 +982,35 @@ void setSgctDelegateFunctions() {
sgctDelegate.currentNode = []() {
return ClusterManager::instance().thisNodeId();
};
sgctDelegate.mousePositionViewportRelative = [](glm::vec2 mousePosition) {
for (const std::unique_ptr<Window>& window : Engine::instance().windows()) {
if (isGuiWindow(window.get())) {
sgct::ivec2 res = window->resolution();
for (const std::unique_ptr<Viewport>& viewport : window->viewports()) {
sgct::vec2 pos = viewport->position();
sgct::vec2 size = viewport->size();
glm::vec4 bounds = glm::vec4(
pos.x * res.x,
(1.0 - pos.y - size.y) * res.y,
(pos.x + size.x) * res.x,
(1.0 - pos.y) * res.y
);
if (
(mousePosition.x >= bounds.x && mousePosition.x <= bounds.z) &&
(mousePosition.y >= bounds.y && mousePosition.y <= bounds.w)
) {
return glm::vec2(
res.x * (mousePosition.x - bounds.x) / (bounds.z - bounds.x),
res.y * (mousePosition.y - bounds.y) / (bounds.w - bounds.y)
);
}
}
}
}
return mousePosition;
};
}
void checkCommandLineForSettings(int& argc, char** argv, bool& hasSGCT, bool& hasProfile,