mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
7.7 KiB
209 lines
7.7 KiB
|
10 years ago
|
/*
|
||
|
|
This file is part of Magnum.
|
||
|
|
|
||
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
|
||
|
|
Vladimír Vondruš <mosra@centrum.cz>
|
||
|
|
|
||
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
copy of this software and associated documentation files (the "Software"),
|
||
|
|
to deal in the Software without restriction, including without limitation
|
||
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
Software is furnished to do so, subject to the following conditions:
|
||
|
|
|
||
|
|
The above copyright notice and this permission notice shall be included
|
||
|
|
in all copies or substantial portions of the Software.
|
||
|
|
|
||
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
DEALINGS IN THE SOFTWARE.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "GlfwApplication.h"
|
||
|
|
|
||
|
|
#include <tuple>
|
||
|
|
|
||
|
|
#include "Magnum/Version.h"
|
||
|
|
#include "Magnum/Platform/Context.h"
|
||
|
|
#include "Magnum/Platform/ScreenedApplication.hpp"
|
||
|
|
|
||
|
|
namespace Magnum { namespace Platform {
|
||
|
|
|
||
|
|
GlfwApplication* GlfwApplication::_instance = nullptr;
|
||
|
|
|
||
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
||
|
|
GlfwApplication::GlfwApplication(const Arguments& arguments): GlfwApplication{arguments, Configuration{}} {}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
GlfwApplication::GlfwApplication(const Arguments& arguments, const Configuration& configuration): GlfwApplication{arguments, nullptr} {
|
||
|
|
createContext(configuration);
|
||
|
|
}
|
||
|
|
|
||
|
|
GlfwApplication::GlfwApplication(const Arguments& arguments, std::nullptr_t)
|
||
|
|
: _context{new Context{NoCreate, arguments.argc, arguments.argv}},
|
||
|
|
_needsRedraw(true)
|
||
|
|
{
|
||
|
|
/* Save global instance */
|
||
|
|
_instance = this;
|
||
|
|
|
||
|
|
/* Init GLFW */
|
||
|
|
glfwSetErrorCallback(staticErrorCallback);
|
||
|
|
|
||
|
|
if(!glfwInit()) {
|
||
|
|
Error() << "Could not initialize GLFW";
|
||
|
|
std::exit(8);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::createContext() { createContext({}); }
|
||
|
|
|
||
|
|
void GlfwApplication::createContext(const Configuration& configuration) {
|
||
|
|
if(!tryCreateContext(configuration)) std::exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool GlfwApplication::tryCreateContext(const Configuration& configuration) {
|
||
|
|
CORRADE_ASSERT(_context->version() == Version::None, "Platform::GlfwApplication::tryCreateContext(): context already created", false);
|
||
|
|
|
||
|
|
static_assert(GLFW_TRUE == true && GLFW_FALSE == false, "GLFW does not have sane bool values.");
|
||
|
|
|
||
|
|
/* Window flags */
|
||
|
|
GLFWmonitor* monitor = nullptr; /* Needed for setting fullscreen */
|
||
|
|
if (configuration.windowFlags() >= Configuration::WindowFlag::Fullscreen) {
|
||
|
|
monitor = glfwGetPrimaryMonitor();
|
||
|
|
glfwWindowHint(GLFW_AUTO_ICONIFY, configuration.windowFlags() >= Configuration::WindowFlag::AutoIconify);
|
||
|
|
} else {
|
||
|
|
const Configuration::WindowFlags& flags = configuration.windowFlags();
|
||
|
|
glfwWindowHint(GLFW_RESIZABLE, flags >= Configuration::WindowFlag::Resizeable);
|
||
|
|
glfwWindowHint(GLFW_VISIBLE, !(flags >= Configuration::WindowFlag::Hidden));
|
||
|
|
glfwWindowHint(GLFW_MAXIMIZED, flags >= Configuration::WindowFlag::Maximized);
|
||
|
|
glfwWindowHint(GLFW_ICONIFIED, flags >= Configuration::WindowFlag::Minimized);
|
||
|
|
glfwWindowHint(GLFW_FLOATING, flags >= Configuration::WindowFlag::Floating);
|
||
|
|
}
|
||
|
|
glfwWindowHint(GLFW_FLOATING, configuration.windowFlags() >= Configuration::WindowFlag::Focused);
|
||
|
|
|
||
|
|
/* Context window hints */
|
||
|
|
glfwWindowHint(GLFW_SAMPLES, configuration.sampleCount());
|
||
|
|
glfwWindowHint(GLFW_SRGB_CAPABLE, configuration.isSRGBCapable());
|
||
|
|
|
||
|
|
const Configuration::Flags& flags = configuration.flags();
|
||
|
|
glfwWindowHint(GLFW_CONTEXT_NO_ERROR, flags >= Configuration::Flag::NoError);
|
||
|
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, flags >= Configuration::Flag::Debug);
|
||
|
|
glfwWindowHint(GLFW_STEREO, flags >= Configuration::Flag::Stereo);
|
||
|
|
|
||
|
|
/* Cursor flags */
|
||
|
|
glfwWindowHint(GLFW_CURSOR, Int(configuration.cursorMode()));
|
||
|
|
|
||
|
|
/* Set context version, if requested */
|
||
|
|
if(configuration.version() != Version::None) {
|
||
|
|
Int major, minor;
|
||
|
|
std::tie(major, minor) = version(configuration.version());
|
||
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
|
||
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
if(configuration.version() >= Version::GL310) {
|
||
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
||
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Set context flags */
|
||
|
|
_window = glfwCreateWindow(configuration.size().x(), configuration.size().y(), configuration.title().c_str(), monitor, nullptr);
|
||
|
|
if(!_window) {
|
||
|
|
Error() << "Platform::GlfwApplication::tryCreateContext(): cannot create context";
|
||
|
|
glfwTerminate();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Set callbacks */
|
||
|
|
glfwSetFramebufferSizeCallback(_window, staticViewportEvent);
|
||
|
|
glfwSetKeyCallback(_window, staticKeyEvent);
|
||
|
|
glfwSetCursorPosCallback(_window, staticMouseMoveEvent);
|
||
|
|
glfwSetMouseButtonCallback(_window, staticMouseEvent);
|
||
|
|
glfwSetScrollCallback(_window, staticMouseScrollEvent);
|
||
|
|
|
||
|
|
glfwMakeContextCurrent(_window);
|
||
|
|
glfwSwapInterval(1);
|
||
|
|
|
||
|
|
/* Return true if the initialization succeeds */
|
||
|
|
return _context->tryCreate();
|
||
|
|
}
|
||
|
|
|
||
|
|
GlfwApplication::~GlfwApplication() {
|
||
|
|
glfwDestroyWindow(_window);
|
||
|
|
glfwTerminate();
|
||
|
|
}
|
||
|
|
|
||
|
|
int GlfwApplication::exec() {
|
||
|
|
while(!glfwWindowShouldClose(_window)) {
|
||
|
|
if(_needsRedraw) {
|
||
|
|
drawEvent();
|
||
|
|
}
|
||
|
|
glfwPollEvents();
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::staticKeyEvent(GLFWwindow*, int key, int, int action, int) {
|
||
|
|
KeyEvent e(static_cast<KeyEvent::Key>(key));
|
||
|
|
|
||
|
|
if(action == GLFW_PRESS) {
|
||
|
|
_instance->keyPressEvent(e);
|
||
|
|
} else if(action == GLFW_RELEASE) {
|
||
|
|
_instance->keyReleaseEvent(e);
|
||
|
|
} /* we don't handle GLFW_REPEAT */
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::staticMouseMoveEvent(GLFWwindow*, double x, double y) {
|
||
|
|
MouseMoveEvent e{Vector2i{Int(x), Int(y)}};
|
||
|
|
_instance->mouseMoveEvent(e);
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::staticMouseEvent(GLFWwindow*, int button, int action, int) {
|
||
|
|
MouseEvent e(static_cast<MouseEvent::Button>(button));
|
||
|
|
|
||
|
|
if(action == GLFW_PRESS) {
|
||
|
|
_instance->mousePressEvent(e);
|
||
|
|
} else if(action == GLFW_RELEASE) {
|
||
|
|
_instance->mouseReleaseEvent(e);
|
||
|
|
} /* we don't handle GLFW_REPEAT */
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::staticMouseScrollEvent(GLFWwindow*, double xoffset, double yoffset) {
|
||
|
|
MouseScrollEvent e(Vector2d{xoffset, yoffset});
|
||
|
|
_instance->mouseScrollEvent(e);
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::staticErrorCallback(int, const char* description) {
|
||
|
|
Error() << description;
|
||
|
|
}
|
||
|
|
|
||
|
|
void GlfwApplication::viewportEvent(const Vector2i&) {}
|
||
|
|
void GlfwApplication::keyPressEvent(KeyEvent&) {}
|
||
|
|
void GlfwApplication::keyReleaseEvent(KeyEvent&) {}
|
||
|
|
void GlfwApplication::mousePressEvent(MouseEvent&) {}
|
||
|
|
void GlfwApplication::mouseReleaseEvent(MouseEvent&) {}
|
||
|
|
void GlfwApplication::mouseMoveEvent(MouseMoveEvent&) {}
|
||
|
|
void GlfwApplication::mouseScrollEvent(MouseScrollEvent&) {}
|
||
|
|
|
||
|
|
GlfwApplication::Configuration::Configuration()
|
||
|
|
: _title("Magnum GLFW Application"),
|
||
|
|
_size(800, 600), _sampleCount(0),
|
||
|
|
_version(Version::None),
|
||
|
|
_windowFlags(WindowFlag::Focused),
|
||
|
|
_cursorMode(CursorMode::Normal)
|
||
|
|
{}
|
||
|
|
|
||
|
|
GlfwApplication::Configuration::~Configuration() = default;
|
||
|
|
|
||
|
|
template class BasicScreen<GlfwApplication>;
|
||
|
|
template class BasicScreenedApplication<GlfwApplication>;
|
||
|
|
|
||
|
|
}}
|