简体   繁体   English

在 Emscripten 中处理 SDL2 大小调整的正确方法

[英]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.

相关问题 具有SDL2的脚本-错误:WebGL:drawArrays:空 - Emscripten with SDL2 - Error: WebGL: drawArrays: null 如何在 cmake 中使用 emscripten 端口(SDL2 和 Freetype) - How to use emscripten ports (SDL2 and Freetype) with cmake Emscripten SDL2 - 调整画布大小时画布的原点似乎会移动 - Emscripten SDL2 - Origin of canvas appears to move when canvas is resized 使用SDL2调整无边框窗口大小时出错 - Bug when resizing borderless window with SDL2 为什么 Intellisense with Emscripten 找不到 SDL2/SDL.h 的包含路径? - Why does Intellisense with Emscripten does not find the include path of SDL2/SDL.h? 在SDL2中创建TextureManager的最有效方法 - Most efficient way of creating a TextureManager in SDL2 SDL2如何在调整窗口大小后缩放鼠标坐标? - SDL2 how to scale mouse coordinates after window resizing? SDL2:调整窗口大小时如何保持宽高比 - SDL2: How to keep aspect ratio when resizing the window 使用SDL2 + Emscripten时浏览器不会加载本地图像 - Browser doesn't load local images while using SDL2 + emscripten 有没有办法在存储库中没有 dll 文件的情况下运行使用 SDL2 和 SDL2 映像的 C++ 可执行文件? - Is there a way to run a C++ executable that uses SDL2 and SDL2 image without having the dll files in the repository?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM