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

问题描述

寻找正确的方法来调整Emscripten的SDL2窗口/画布的大小。 目前,我正在JS'resize'事件上添加事件侦听器,并将Canvas父级的客户端宽度+高度发送给Emscripten,然后更新在每个渲染器上调用的width和height变量。

这将产生奇怪的结果-刻度始终处于关闭状态,实际可用的SDL2区域未更改,并且指针事件不再与SDL对齐。

我的窗口大小变量是:

int canvasWidth = 800;
int canvasHeight = 600;

这是我的初始化代码

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,800,600,flags);
    SDL_SetRenderDrawColor(SDL_GetRenderer(gSDLWindow),0);

    SDL_GLContext glcontext = SDL_GL_CreateContext(gSDLWindow);

    SDL_GL_SetSwapInterval(1);


    glViewport(0,canvasWidth,canvasHeight);
    glewInit();


    InitImGui();
    framework_init_flat();
    framework_init_tex();

    atexit(SDL_Quit);

}

这是我的每帧更新代码

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,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);
}

解决方法

为什么不使用SDL窗口事件系统?这对我有用:

void update_screen_size(int w,int h) 
{
   glViewport(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;
        }
    }
}

另一种方法是在每一帧查询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());
}