SFML / imgui-sfml

Dear ImGui backend for use with SFML
MIT License
1.15k stars 173 forks source link

imgui cannot show utf-8 chinese character correctly,how to solve #237

Open aliule2020 opened 1 year ago

aliule2020 commented 1 year ago
//#include <SFML/Graphics.hpp>
//
//int main()
//{
//    sf::RenderWindow window(sf::VideoMode(sf::Vector2u{200,200}), "SFML works!");
//    sf::CircleShape shape(100.f);
//    shape.setFillColor(sf::Color::Green);
//
//    while (window.isOpen())
//    {
//        sf::Event event;
//        while (window.pollEvent(event))
//        {
//            if (event.type == sf::Event::Closed)
//                window.close();
//        }
//
//        window.clear();
//        window.draw(shape);
//        window.display();
//    }
//
//    return 0;
//}

#include <string>
using namespace std;

#include "imgui.h" // necessary for ImGui::*, imgui-SFML.h doesn't include imgui.h

#include "imgui-SFML.h" // for ImGui::SFML::* functions and SFML-specific overloads

#include <SFML/Graphics.hpp>
#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>

int main() {
    sf::RenderWindow window(sf::VideoMode(sf::Vector2u{ 1024,768 }), "SFML works!");
    window.setFramerateLimit(60);
    ImGui::SFML::Init(window);

    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    sf::Text tx;
    tx.setString( sf::String(L"你好") );   //here is ok
    sf::Font font;
    font.loadFromFile("C:\\Windows\\Fonts\\stsong.ttf");
    tx.setFont(font);
    tx.setCharacterSize(36);
    tx.setFillColor(sf::Color::Red);
    tx.setPosition(sf::Vector2f{ 400, 400 });

    sf::Clock deltaClock;
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            ImGui::SFML::ProcessEvent(window, event);

            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        ImGui::SFML::Update(window, deltaClock.restart());   

        ImGui::BeginMainMenuBar();
        ImGui::SetWindowFontScale(1);

        if (ImGui::BeginMenu("File"))
        {

            if (ImGui::MenuItem("Open..", "Ctrl+O")) { /* Do stuff */ }
            if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Do stuff */ }
            if (ImGui::MenuItem("Close", "Ctrl+W")) {  }
            ImGui::EndMenu();
        }
        ImGui::EndMainMenuBar();

        ImGui::ShowDemoWindow();

        ImGuiIO& io = ImGui::GetIO();
        //io.Fonts->Clear();
        io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\stsong.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
        io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\simhei.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
        //ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
        ImGui::SFML::UpdateFontTexture();

        ImGui::Begin("hello");
        ImGui::SetWindowFontScale(4);
        ImGui::SetWindowPos("hello", ImVec2{ 50,50 });
        ImGui::SetWindowSize("hello", ImVec2{ 200,200 });
        ImGui::Button((char*)u8"中文测试");      //here is failed
        ImGui::End();

        window.clear(sf::Color::White);
        window.draw(shape);

        ImGui::SFML::Render(window);

        window.draw(tx);
        window.display();
    }

    ImGui::SFML::Shutdown();

    return 0;
}
eliasdaler commented 1 year ago

Hello. Can you please show me what you're seeing instead? What OS are you on, by the way?

P.S. Does the custom font work for ASCII characters?

aliule2020 commented 1 year ago

image

I am using windows 10 for china version , by vs 2022, yes the ascii characters works well.

eliasdaler commented 1 year ago

Doing ImGui::PushFont is important, by the way. I think you're using the default Dear ImGui's font by not doing this. Try to get Dear ImGui to print simple English characters in this font (e.g. "ABC" should be printed in your custom font) and then try Chinese characters.

And you should only call AddFontFromFileTTF and UpdateFontTexture on the startup, not inside your main loop.

(if this doesn't help, I'll come up with a good starting example tomorrow)

aliule2020 commented 1 year ago

Thank you for your help, but the problem is still on. At first, in my program the ImGui::PushFont cannot be used, or the exception will happen. Secondly, the English characters works well, you can see my picture below. Last, I correct my program following your instructions ,here is the result: image

#include "string"
using namespace std;

#include "imgui.h" // necessary for ImGui::*, imgui-SFML.h doesn't include imgui.h

#include "imgui-SFML.h" // for ImGui::SFML::* functions and SFML-specific overloads

#include <SFML/Graphics.hpp>
#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>

int main() {
    sf::RenderWindow window(sf::VideoMode(sf::Vector2u{ 1024,768 }), "SFML works!");
    window.setFramerateLimit(60);
    ImGui::SFML::Init(window);

    ImGuiIO& io = ImGui::GetIO();
    io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\stsong.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
    //io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\simhei.ttf", 13.0f, NULL, io.Fonts->GetGlyphRangesChineseFull());
    //ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]);
    ImGui::SFML::UpdateFontTexture();

    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    sf::Text tx;
    tx.setString( sf::String(L"你好") );
    sf::Font font;
    font.loadFromFile("C:\\Windows\\Fonts\\stsong.ttf");
    tx.setFont(font);
    tx.setCharacterSize(36);
    tx.setFillColor(sf::Color::Red);
    tx.setPosition(sf::Vector2f{ 400, 400 });

    sf::Clock deltaClock;
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            ImGui::SFML::ProcessEvent(window, event);

            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        ImGui::SFML::Update(window, deltaClock.restart());   

        ImGui::BeginMainMenuBar();
        ImGui::SetWindowFontScale(1);

        if (ImGui::BeginMenu("File"))
        {

            if (ImGui::MenuItem("Open..", "Ctrl+O")) { /* Do stuff */ }
            if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Do stuff */ }
            if (ImGui::MenuItem("Close", "Ctrl+W")) {  }
            ImGui::EndMenu();
        }
        ImGui::EndMainMenuBar();

        ImGui::ShowDemoWindow();

        ImGui::Begin("hello");
        ImGui::SetWindowFontScale(4);
        ImGui::SetWindowPos("hello", ImVec2{ 50,50 });
        ImGui::SetWindowSize("hello", ImVec2{ 200,200 });
        ImGui::Button((char*)u8"中文测试");
        ImGui::Button("ABC");
        ImGui::End();

        window.clear(sf::Color::White);
        window.draw(shape);

        ImGui::SFML::Render(window);

        window.draw(tx);
        window.display();
    }

    ImGui::SFML::Shutdown();

    return 0;
}
ghost commented 1 year ago

You're not calling io.Fonts->Build(); and BuildRanges as in the official example before doing ImGui::SFML::UpdateFontTexture(); : https://github.com/ocornut/imgui/blob/master/docs/FONTS.md#using-custom-glyph-ranges

ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;
builder.AddText("Hello world");
builder.AddChar(0x7262);
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese());
builder.BuildRanges(&ranges);
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
io.Fonts->Build();

Works for me with i.e. cyrllic glyph ranges.