Need some advice with AddInputCharacter()

#1

Hey there, I’ve been using imgui for a lot of my projects so first of all thank you very much.

The reason I’m posting this question is because I need some help with my first ever multi threaded game. I simply want to get Text Input working, as per the console demo and text input demos. Inside the demo which allows you to see the keyboard state, while keypresses register, the queued characters never register. The rendering is on a seperate thread to the input handling and logic.

I’m not asking people to write my code, however after looking at some issues surrounding this (like this?) but I don’t know how imgui has changed recently and I thought I’d post here to see if I could get some general advice.

            // Inside the SFML bindings
            case sf::Event::TextEntered:
                if (event.text.unicode > 0 && event.text.unicode < 0x10000) {
                    io.AddInputCharacter(static_cast<ImWchar>(event.text.unicode));
                }
                break;

As per Elias’ bindings, I am passing things through to his ImGui::SFML::ProcessEvent. I have even placed print statements in his code to ensure that it’s been fired and that my characters are valid.

// Respond to any key or mouse related events
void
Game::handleEvent(const sf::Event& event) {

  // Adjust the viewport if window is resized
  if (event.type == sf::Event::Resized) {
    displaySize_ = sf::Vector2f(event.size.width, event.size.height);
    sf::FloatRect visibleArea(0.f, 0.f, displaySize_.x, displaySize_.y);
    Game::view = sf::View(visibleArea);
  }

  // Pass events to IMGUI debug interface
  bool passToGame = true;
  bool passToImgui = true;
  if (debug_) {

    // Decide whether the game should get the event
    if (event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseButtonReleased) {
      if (ImGui::GetIO().WantCaptureMouse) passToGame = false;
    }
    else if (event.type == sf::Event::KeyPressed || event.type == sf::Event::KeyReleased) {
      if (ImGui::GetIO().WantCaptureKeyboard) passToGame = false;
    }
  }

  // Handle imgui events
  if (passToImgui) { ImGui::SFML::ProcessEvent(event); }

  // Pass events to scene
  if (currentScene_ != nullptr && passToGame) {
    currentScene_->handleEvent(event);
  }
}

This is where my input handling happens, it’s pretty straight forward. The reason I know it is due to multi threading, is that when I run my game in single thread mode, it works. This means that when I handle Events -> Update -> Render in that order, it works. However, in multi threaded mode, I have handleEvents -> Update on one thread, and Render in another.

Seeing as I call ImGui::SFML::Render inside my Render function which is on a different thread, I have reason to believe that this may mess with the implementation with regards to imgui. In it’s current state, I cannot control how many times I handle events before I render. I flip-flop my update call with the render call by using a bool (I only update when it’s false, I only render when it’s true. This means that no matter how many times each thread executes I’m updating before I render). However, I don’t want to constrain my event handling to the same fate just yet.

Could I be given some guidance as to when exactly the buffer of characters I’m sending in a text entry is consumed (such as in the console demo)? With this information I should be able to work it out

Thank you very much!

0 Likes

#2

io.AddInputCharacter() needs to called before NewFrame() and the data is being consumed between NewFrame() and the end of the frame aka EndFrame()/Render().

If your input comes in a different thread than your thread running imgui stuff, queue them to a buffer and pass them to imgui before you call NewFrame().

0 Likes

#3

I’m sorry I didn’t reply sooner, had some stuff on.

On further inspection, the SFML bindings handle the calling of NewFrame for me. I was trying to do this on my own and I was getting errors which lead to a bit of confusion.

Thank you for your simple but effective advice, I have solved the problem using your suggestion!

0 Likes