我目前正在创建一个轻量级程序来查看和操作类似于程序Blender或3DS max的3D对象。
我正在使用C ++,GLFW和OpenGL。虽然我打算让它成为跨平台,但我目前只在使用XFCE桌面环境运行Debian 9.0(延伸)的计算机上工作。
目前回调glfwSetDropCallback似乎永远不会被调用,无论我尝试什么。我设置了断点并断言但没有。我尝试过的所有其他回调都运行得很好。我从我的项目中包含了我的GLFW cpp。如果需要其他东西,请随意询问。
另外作为最后一点,我只是使用GLFW,因为其他一切似乎都太重了我的需求。同样使用X11直接看起来像很多工作没有太大的收获,特别是因为我需要针对每个目标操作系统的不同解决方案。最后,我只想将项目拖放到我的程序窗口,然后让我的代码对路径做一些事情。
#include "GLFWindow.h"
#include <cassert>
#include <iostream>
// Variables for callback.
static bool keys[1024];
static std::vector<std::string> dragAndDrop;
static Camera* _camera;
static GLdouble* _lastX;
static GLdouble* _lastY;
GLFWindow::GLFWindow()
:m_window(nullptr), m_lastX(0.0), m_lastY(0.0)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLFW_VERSION_MAJOR);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLFW_VERSION_MINOR);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // For OSX
glfwWindowHint(GLFW_FOCUSED, GL_TRUE);
std::cout << glfwGetVersionString() << std::endl;
m_window = glfwCreateWindow(1920, 1080, "Model Viewer", /*glfwGetPrimaryMonitor()*/nullptr, nullptr);
if(m_window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
assert(m_window != nullptr);
}
glfwMakeContextCurrent(m_window);
glfwSetWindowPos(m_window, 1920 - 1920/2, 1080 - 1080/2);
glfwSetKeyCallback(m_window,
[](GLFWwindow* window, int key, int, int action, int)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if(action == GLFW_PRESS)
keys[key] = true;
else if(action == GLFW_RELEASE)
keys[key] = false;
});
glfwSetInputMode(m_window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
glfwSetCursorEnterCallback(m_window,
[](GLFWwindow* window, int entered)
{
if(entered)
{
double xPos, yPos;
glfwGetCursorPos(window, &xPos, &yPos);
*_lastX = xPos;
*_lastY = yPos;
}
});
glfwSetDropCallback(m_window,
[](GLFWwindow*, int count, const char** paths)
{
std::cout << "Drag and Drop count - " << count << std::endl;
for(unsigned int i = 0; i < count; ++i)
{
std::cout << std::string(paths[i]) << std::endl;
dragAndDrop.push_back(std::string(paths[i]));
}
});
}
GLFWindow::~GLFWindow()
{
glfwTerminate();
}
GLint GLFWindow::GetWidth()
{
GLint width = 0;
glfwGetFramebufferSize(m_window, &width, nullptr);
return width;
}
GLint GLFWindow::GetHeight()
{
GLint height = 0;
glfwGetFramebufferSize(m_window, nullptr, &height);
return height;
}
std::string GLFWindow::GetDragAndDrop()
{
if(dragAndDrop.empty())
return "END";
std::string item = dragAndDrop[dragAndDrop.size()-1];
dragAndDrop.pop_back();
if(item.find(".obj") == std::string::npos && item.find(".fbx") == std::string::npos
&& item.find(".OBJ") == std::string::npos && item.find(".FBX") == std::string::npos)
return "INVALID";
return item;
}
bool GLFWindow::ShouldClose()
{
return glfwWindowShouldClose(m_window);
}
void GLFWindow::AddCamera(Camera* camera)
{
m_camera = camera;
_camera = m_camera;
_lastX = &m_lastX;
_lastY = &m_lastY;
glfwSetScrollCallback(m_window,
[](GLFWwindow*, double, double yoffset)
{
_camera->ProcessMouseScroll(yoffset);
});
glfwSetCursorPosCallback(m_window,
[](GLFWwindow*, double xPos, double yPos)
{
GLfloat xOffset = xPos - *_lastX;
GLfloat yOffset = *_lastY - yPos;
*_lastX = xPos;
*_lastY = yPos;
_camera->ProcessMouseMovement(xOffset, yOffset);
});
}
void GLFWindow::PollEvents(const GLfloat deltaTime)
{
glfwPollEvents();
if(keys[GLFW_KEY_W])
m_camera->ProcessKeyboard(0, deltaTime);
if(keys[GLFW_KEY_S])
m_camera->ProcessKeyboard(1, deltaTime);
if(keys[GLFW_KEY_A])
m_camera->ProcessKeyboard(2, deltaTime);
if(keys[GLFW_KEY_D])
m_camera->ProcessKeyboard(3, deltaTime);
if(keys[GLFW_KEY_Q])
m_camera->ProcessKeyboard(4, deltaTime);
if(keys[GLFW_KEY_E])
m_camera->ProcessKeyboard(5, deltaTime);
}
GLfloat GLFWindow::GetElapsedTime()
{
return glfwGetTime();
}
void GLFWindow::SwapBuffers()
{
glfwSwapBuffers(m_window);
}
谢谢你的时间, 布兰登
编辑:
我添加了一些X11代码来测试一些东西。
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
Display *display =XOpenDisplay((char *)0);
if(XInternAtom(display, "XdndAware", False))
std::cout << "Supported" << std::endl;
此代码始终返回Supported。我现在相信它是GLFW的一个错误。
最终编辑: 这是GLFW的一个错误。 错误是由于Thunar提供text / uri-list,而GLFW假定支持UTF8_STRING。修复传入。 如果其他人有这个问题,这里是修复。 https://github.com/glfw/glfw/commit/6a65341e14bc7745c52fe86fe53be08dbd682dd9
答案 0 :(得分:1)
修改: This was indeed a bug and has been resolved.
首先确保您使用最新的稳定GLFW版本(今天是3.2.1)。
最明显的原因可能是您从未致电GLFWindow::PollEvents()
,因此永远不会致电glfwPollEvents()
。但是,我怀疑这是原因,因为你从未提及任何其他输入问题。
要验证它是否真的是永远不会被调用的回调,请尝试这个最小的例子:
glfwInit();
// You might need some of the window hints
GLFWwindow *window = glfwCreateWindow(600, 400, "Test glfwSetDropCallback", NULL, NULL);
glfwSetDropCallback(window, [](GLFWwindow*, int count, const char **paths)
{
std::cout << "Drag and Drop count - " << count << std::endl;
for (unsigned int i = 0; i < count; ++i)
std::cout << "- " << paths[i] << std::endl;
});
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
我刚在Windows上测试了上面的代码,但它确实有效。因此,如果该代码不起作用。然后它可能是特定于X11的错误,应该在GLFW's issue tracker上通知。
如果它仍然无效。然后在认为它是一个错误之前,你应该测试你的显示器是否支持文件丢弃。所以虽然这是X11具体的。您只是用它来验证支持。
请注意,如果不支持删除文件,GLFW不会抱怨。
自从我触及X11以来已经很久了。但是,如果我没记错的话,检查对删除文件的支持将是这样的:
Display *display = ...
if (XInternAtom(display, "XdndAware", False))
std::cout << "Supported" << std::endl;