【问题标题】:Proper way to handle SDL2 Resizing in Emscripten在 Emscripten 中处理 SDL2 调整大小的正确方法
【发布时间】:2021-01-07 06:08:45
【问题描述】:

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

这会产生奇怪的结果——刻度总是关闭,实际可用的 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,
        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);

}

这是我的每帧更新代码:

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

【问题讨论】:

    标签: c++ sdl-2 emscripten


    【解决方案1】:

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

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

    另一种方法是每帧查询html画布:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      • 2017-04-12
      • 2014-01-11
      • 1970-01-01
      • 2016-11-19
      相关资源
      最近更新 更多