[英]Proper way to handle SDL2 Resizing in Emscripten
Looking for the proper way to resize an SDL2 window/canvas that is coming from Emscripten.寻找调整来自 Emscripten 的 SDL2 窗口/画布大小的正确方法。 Currently I'm adding an event listener on the JS 'resize' event and sending the Canvas parent's client width + height to Emscripten, then updating a width and a height variable which are called on each render.
目前,我在 JS 的“调整大小”事件上添加了一个事件侦听器,并将 Canvas 父级的客户端宽度 + 高度发送到 Emscripten,然后更新在每次渲染时调用的宽度和高度变量。
This is producing weird results - the scale is always off, the actual usable SDL2 area isn't changed, and the pointer events no longer line up with SDL.这产生了奇怪的结果——比例总是关闭,实际可用的 SDL2 区域没有改变,指针事件不再与 SDL 对齐。
My window size variables are:我的 window 大小变量是:
int canvasWidth = 800;
int canvasHeight = 600;
This is my init code:这是我的初始化代码:
void Init()
{
int i;
for (i = 0; i < 256; i++)
gPressed[i] = gWasPressed[i] = 0;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0)
{
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
SDL_Quit();
exit(0);
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
int flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
gSDLWindow = SDL_CreateWindow(
"",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800,
600,
flags);
SDL_SetRenderDrawColor(SDL_GetRenderer(gSDLWindow), 0, 0, 0, 0);
SDL_GLContext glcontext = SDL_GL_CreateContext(gSDLWindow);
SDL_GL_SetSwapInterval(1);
glViewport(0, 0, canvasWidth, canvasHeight);
glewInit();
InitImGui();
framework_init_flat();
framework_init_tex();
atexit(SDL_Quit);
}
And this is my per-frame update code:这是我的每帧更新代码:
void Update()
{
ImGuiIO& io = ImGui::GetIO();
// Setup resolution (every frame to accommodate for window resizing)
io.DisplaySize = ImVec2((float)canvasWidth, (float)canvasHeight);
SDL_SetWindowSize(gSDLWindow, canvasWidth, canvasHeight);
// Setup time step
static double time = 0.0f;
const double current_time = SDL_GetTicks() / 1000.0;
if (current_time == time)
return;
io.DeltaTime = (float)(current_time - time);
time = current_time;
io.MousePos = ImVec2((float)gUIState.mousex, (float)gUIState.mousey);
io.MouseDown[0] = gUIState.mousedown != 0;
io.MouseDown[1] = 0;
if (gUIState.scroll)
{
io.MouseWheel += (float)gUIState.scroll * 0.5f;
gUIState.scroll = 0;
}
if (gUIState.textinput[0])
{
io.AddInputCharactersUTF8(gUIState.textinput);
gUIState.textinput[0] = 0;
}
for (int n = 0; n < 256; n++)
io.KeysDown[n] = gPressed[n] != 0;
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
}
Why not use the SDL window event system?为什么不使用 SDL window 事件系统? This works for me:
这对我有用:
void update_screen_size(int w, int h)
{
glViewport(0, 0, w, h);
}
void somewhere_in_your_main_loop()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
emscripten_cancel_main_loop();
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_RESIZED)
{
update_screen_size(event.window.data1, event.window.data2);
}
break;
default:
break;
}
}
}
Another way is to query the html canvas each frame:另一种方式是查询html canvas每一帧:
EM_JS(int, get_canvas_width, (), { return canvas.width; });
EM_JS(int, get_canvas_height, (), { return canvas.height; });
void somewhere_in_your_main_loop()
{
update_screen_size(get_canvass_width(), get_canvas_height());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.