SFML community forums

General => SFML projects => Topic started by: Aster on January 05, 2015, 07:51:23 pm

Title: [GUI] SFML backend for ImGui
Post by: Aster on January 05, 2015, 07:51:23 pm
Hello.

I've written an SFML backend (https://github.com/Mischa-Alff/imgui-backends) for ImGui (https://github.com/ocornut/imgui): https://github.com/Mischa-Alff/imgui-backends

Quote
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies. It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.

ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.

ImGui is particularly suited to integration in 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard.

The backend uses SFML's vertex arrays (and GL_TRIANGLES) for rendering, so this should work on every platform SFML supports.

Usage is explained in the repository's SFML/README.md, or here: https://github.com/Mischa-Alff/imgui-backends/blob/master/SFML/README.md

What isn't implemented:

Cheers
Title: Re: [GUI] SFML backend for ImGui
Post by: Ricky on January 06, 2015, 06:43:46 am
Dude this is flippin' awesome!
Title: Re: [GUI] SFML backend for ImGui
Post by: caxco93 on January 07, 2015, 04:53:35 pm
very cool but check out what i get as text and console output. any ideas why?

(http://i.cubeupload.com/pfoUTY.png)

#include "stdafx.h"
#include <stdio.h>
#include <SFML/Graphics.hpp>
#include "imgui.h"
#include "imgui-SFML.h"

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "ImGui test!");
        ImGui::SFML::SetWindow(window);
        ImGui::SFML::InitImGui();
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        ImGui::SFML::ProcessEvent(event);
                        if (event.type == sf::Event::Closed) window.close();
                }
                ImGui::SFML::UpdateImGui();
                static bool ui = true;
                if (ImGui::Begin("Test!", &ui, ImVec2(10, 10)))
                {
                        ImGui::Text("Hello, world!");
                }
                ImGui::End();
                ImGui::Render();
                window.display();
        }
        return 0;
}
 
Title: Re: [GUI] SFML backend for ImGui
Post by: Laurent on January 07, 2015, 04:59:53 pm
If you don't understand "PNG not supported: 8-bit only", I don't know what else can be said... :P
Title: Re: [GUI] SFML backend for ImGui
Post by: caxco93 on January 07, 2015, 05:02:40 pm
its not like im the one setting the path to a .png file . theres not even such string in the entire project.
Title: Re: [GUI] SFML backend for ImGui
Post by: Laurent on January 07, 2015, 05:05:10 pm
Yes, sorry, I didn't notice that your own code doesn't load any image (it was initially not displayed completely).

Well then I guess internal images should be converted to a supported format inside the SFML backend.
Title: Re: [GUI] SFML backend for ImGui
Post by: caxco93 on January 07, 2015, 05:22:09 pm
ok so its because of this method inside the imgui thingy 
Code: [Select]
ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);

that calls this
Code: [Select]
void ImGui::GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size)
{
    if (fnt_data) *fnt_data = (const void*)proggy_clean_13_fnt_data;
    if (fnt_size) *fnt_size = proggy_clean_13_fnt_size;
    if (png_data) *png_data = (const void*)proggy_clean_13_png_data;
    if (png_size) *png_size = proggy_clean_13_png_size;
}

which reads this.
Code: [Select]
static const unsigned int proggy_clean_13_png_size = 1271;
static const unsigned int proggy_clean_13_png_data[1272/4] =
{
    0x474e5089, 0x0a1a0a0d, 0x0d000000, 0x52444849, 0x00010000, 0x40000000, 0x00000301, 0x3b93cf00, 0x000000fd, 0x544c5006, 0xffffff45, 0x55ffffff,
    0x006cf57c, 0x74010000, 0x00534e52, 0x66d8e640, 0x9f040000, 0x54414449, 0xd2ed5e78, 0x57136f4d, 0xebe00518, 0x0c4c98c9, 0xdf1def0d, 0x52b2b494,
    0xe18a99db, 0x5d412243, 0x66adc8d8, 0x831a772e, 0x8c1c74aa, 0x534a9540, 0x2c162568, 0x50e1650a, 0x4e27b2a7, 0x8e289b19, 0x08555047, 0x5572c4a1,
    0x45d465e4, 0x23e2a2c5, 0x410d3602, 0x484a82ea, 0x48a58921, 0xa80d306c, 0xf5ea0150, 0x0aa91518, 0x59ed03fd, 0xa3c5de8c, 0x1dd2bef3, 0xdc02ad54,
    0xc786adbd, 0xa46249ef, 0x45672e07, 0x5368275f, 0xba00af1e, 0x50802410, 0x44584212, 0x0cc02d22, 0x54c385db, 0xa4304a20, 0x4ab0be59, 0x5581c073,
    0x3223c105, 0x3cca900e, 0x2f434141, 0xc31f00a2, 0x8381436e, 0x7582e1c3, 0xc61bd538, 0xd9d639b6, 0xac8f0873, 0x7cdf5051, 0x7068dc3a, 0x0f41ca81,
    0xb8e545db, 0xc77128e9, 0xc2357961, 0x0d9bd340, 0xb0385a6b, 0x378d1cd9, 0xf51d14c0, 0x7deed071, 0x378041c8, 0xb763cf3c, 0xca685541, 0xc170dff1,
    0x1c45eb9e, 0xca9f3beb, 0xec1a344c, 0x01c63105, 0x69b9a56c, 0xa920baa2, 0x2be30e9a, 0xa437e038, 0x68545174, 0x47a40e01, 0xbdd5104f, 0xacd51de1,
    0xb323a070, 0x00bd20d1, 0x6b8a332c, 0x3aeb8b1b, 0xf0720e7b, 0x7e6fac43, 0x20de0398, 0xaf476e65, 0xaf43df8c, 0x68be1248, 0xeb4b2d0e, 0x6009c5f5,
    0x1373d446, 0x5923eb42, 0x83bbfc11, 0x6b40b78d, 0x2c9c1e40, 0x1d25646d, 0x6dd95620, 0x2d121d08, 0xe153ea31, 0x569e2034, 0x89399009, 0x7d09e35a,
    0x6a299cc3, 0x1081d0ba, 0x93f350d6, 0x24e5f36d, 0x83939908, 0x2189e357, 0xbfa41382, 0x644cf977, 0x8d2da4a9, 0x2207ea47, 0x6f9db2c8, 0x852b401a,
    0xc88309e2, 0x926fa251, 0xcf81135f, 0x8b7fc309, 0x92d4baa1, 0xda9f9d6b, 0x285b71ff, 0x7cb1a1fe, 0xf37fc3ba, 0x5b1bd90d, 0x63fd19b9, 0x4e861b9e,
    0x5b98ba9d, 0xada921a0, 0x0d65816d, 0x0901d031, 0x8835ecaf, 0x4170458e, 0x67ae4dbe, 0xe1f03847, 0xca21ba9d, 0x09bcbc43, 0xa209a248, 0x1bccbc10,
    0xba6b0724, 0x560b7ad1, 0xbe45d18a, 0x8fc83662, 0x7845295c, 0xb4b30403, 0x083a5dab, 0xe03cd568, 0xad1cd320, 0xb16596e7, 0xf07a74ae, 0x3fdee918,
    0x9dff59d6, 0x59459b6c, 0xdf0bc40e, 0x622d7232, 0x4c58e581, 0x0289acb5, 0x9d39df61, 0x52091f79, 0x27ea7234, 0x2f862fd4, 0x018c6b90, 0xcf531873,
    0x9204974e, 0x79294e4f, 0xc42cd641, 0xe120a953, 0xb3d5d7c2, 0xcaaab02a, 0x3f57283e, 0xc6d4796f, 0x67057d81, 0xa9150405, 0xda65fc5d, 0x81abf954,
    0x52cf855a, 0x3b33e9e5, 0xa606f836, 0xd8edf562, 0x42885012, 0x4439866d, 0x5069aa75, 0xf647c08f, 0x5e5f2ad9, 0x13a29818, 0x8809993e, 0x6ce63187,
    0x039cea7e, 0x6d9a0600, 0xb23f3659, 0x54ee50e4, 0x51bd1d01, 0x69698176, 0xa78cc82e, 0x918fc7d3, 0xe68c782d, 0xddb6d41e, 0x05d50541, 0x6862b4cc,
    0x9fa0b8b5, 0x93d18d39, 0x61fb26d3, 0xc3d37c71, 0x60199ee8, 0xafd5f3d8, 0x8176ddbf, 0xc3f0d086, 0x5a4508ae, 0xb017a94b, 0x7bb4c447, 0xb47b0661,
    0x034adbe4, 0x5162d0d4, 0x145b3117, 0x265bb553, 0x13ada3d1, 0xfcf77203, 0x14cf0730, 0x79faf474, 0xc0e00514, 0x3a3397d8, 0xbef282f6, 0x9cfb06b7,
    0xbd868d8d, 0xbcf10521, 0x4313fcc5, 0xa9506c35, 0x231e9801, 0x80b83798, 0x2ffba8af, 0xea629967, 0x14bbd762, 0x404f5e86, 0x741c674e, 0xe1e4bddf,
    0xc8289e2b, 0x22161ede, 0x08ba737d, 0xfdd624de, 0x0c262c25, 0xf033fd82, 0x2d7df0c9, 0x01edfbc9, 0x1c063022, 0x5ab3cb48, 0x65787dad, 0xd174b636,
    0xcf3c6e44, 0xcec7a29e, 0xcd131c86, 0x1eb9d6e1, 0xf18cbd0d, 0xc7e3b3c4, 0x51a3855a, 0xb3b63099, 0x73791a88, 0x28bdd4b3, 0x0877396d, 0xdcb4af9f,
    0xda2678bf, 0x3f8388f1, 0xe1c23c49, 0x4bb1c0c9, 0x60811a9f, 0x32526321, 0x0de7bf4d, 0x272bb715, 0x36b4712b, 0xbecbb290, 0xf3f58cde, 0x4def93e3,
    0x68771d8e, 0x8f65effc, 0xc23357fd, 0x38a672d6, 0x6cd75a99, 0x4ba70848, 0xecfe3fd6, 0x0ed07878, 0x86fc3dda, 0xb96d25a0, 0xbd0465f3, 0xcb17658c,
    0xbb061db6, 0x5684b85c, 0x1a67638b, 0xe072ed60, 0xe41d5a04, 0x078f9275, 0xa955e8ea, 0x042929e6, 0xa473abd1, 0xfa3648a0, 0xdb13b097, 0xc91ff46c,
    0x250bf9ff, 0x6a079cd4, 0x004ebcd0, 0x49000000, 0xae444e45, 0x00826042,
};

apparently those are the bytes of a .png file that is not 8-bit.

so i assume i would have to change the size and bytes for those of an 8bit one?

now how can one get that string of bytes from a binary file?
Title: Re: [GUI] SFML backend for ImGui
Post by: SLC on January 07, 2015, 07:13:26 pm
now how can one get that string of bytes from a binary file?

I'm not sure it even works (correctly) but... uhm... you get the idea:
#include <iostream>
#include <iterator>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

int main(int argc, char** argv)
{
    std::cout << "Enter the number of bytes to add a new line or use 0 for continuous." << std::endl;
    std::cout << "Row length: ";

    unsigned int row_len = 0;

    std::cin >> row_len;

    std::cout << "Enter 1 if you want spacing between array elements or 0 if you don't." << std::endl;
    std::cout << "Element space: ";

    bool elem_space = false;

    std::cin >> elem_space;

    std::cout << "Enter the path of the input file that should be converted." << std::endl;
    std::cout << "File path: ";

    std::string src_path;

    std::cin >> src_path;

    if (src_path.empty()) {
        std::cout << "No path to the source file was specified. Aborting..." << std::endl;
        return 1;
    }

    std::ifstream src_file(src_path, std::ifstream::binary);

    if (!src_file.is_open()) {
        std::cout << "Unable to open source file: " << src_path << std::endl;
        return 1;
    }

    std::streampos src_size = 0;

    src_size = src_file.tellg();
    src_file.seekg(0, std::ios::end);
    src_size = src_file.tellg() - src_size;
    src_file.seekg(0, std::ios::beg);

    std::string dest_path(src_path);
    dest_path.append(".cpp");

    std::cout << "Note: Output data will be saved into " << dest_path << std::endl;

    std::ofstream dest_file(dest_path);
    if (!dest_file.is_open()) {
        std::cout << "Unable to open destination file: " << src_path << std::endl;
        src_file.close();
        return 1;
    }

    std::cout << "transferring from " << src_path << " to " << dest_path << \
                " with a row length of " << row_len << std::endl;


    std::vector<unsigned char> src_data;
    src_data.reserve(src_size);

    src_data.insert(src_data.begin(), \
                    std::istream_iterator<unsigned char>(src_file), \
                    std::istream_iterator<unsigned char>());

    dest_file << "static const unsigned char file_data[] = {\n";

    unsigned int byte_count = 0;
    for (std::vector<unsigned char>::iterator itr = src_data.begin(); itr != src_data.end(); ++itr)
    {
        if (itr + 1 != src_data.end()) {
            dest_file << "0x" << std::hex << std::setfill('0') << std::setw(2) \
                        << int(*itr) << (elem_space ? ", " : ",");
        } else {
            dest_file << "0x" << std::hex << std::setfill('0') << std::setw(2) \
                        << int(*itr) << "\n};";
            break;
        }

        ++byte_count;
        if(row_len > 0 && byte_count % row_len == 0) dest_file << "\n";
    }

    src_file.close();
    dest_file.close();

    return 0;
}
 
Title: Re: [GUI] SFML backend for ImGui
Post by: bock on January 07, 2015, 08:04:08 pm
There was a recent optimisation to compress the PNG to lower bit-per-pixel which although correct, meant the PNG didn't load on some incomplete PNG loader. The optimisation has been reverted now:
https://github.com/ocornut/imgui/issues/109

caxco93: The answer to your question "now how can one get that string of bytes from a binary file? " was a few lines above the one you looked at, there is a program in the comments that does exactly this.

Title: Re: [GUI] SFML backend for ImGui
Post by: Cpt. Bread on March 04, 2015, 01:50:11 pm
Good work. Unfortunately for me the clipping problem really made it a no go in its current state...
So to solve that I replaced the ImImpl_RenderDrawLists with the one you get from ImGuis example OpenGl implementation but modified to work with SFML textures... If someone else wants to use it remember you need to link opengl32.lib(or whatever is the equivalent if you aren't using VS)...

#include <SFML/OpenGL.hpp>
[...]
static void ImImpl_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
{
        if (cmd_lists_count == 0)
                return;

        ImImpl_window->pushGLStates();

        // We are using the OpenGL fixed pipeline to make the example code simpler to read!
        // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer.
        // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
        glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDisable(GL_CULL_FACE);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_SCISSOR_TEST);
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnable(GL_TEXTURE_2D);

        // Setup orthographic projection matrix
        const float width = ImGui::GetIO().DisplaySize.x;
        const float height = ImGui::GetIO().DisplaySize.y;
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();

        // Render command lists
        for (int n = 0; n < cmd_lists_count; n++)
        {
                const ImDrawList* cmd_list = cmd_lists[n];
                const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front();
                glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos)));
                glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv)));
                glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col)));

                int vtx_offset = 0;
                for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++)
                {
                        const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i];
                        sf::Texture::bind((sf::Texture*)pcmd->texture_id);
                        glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y));
                        glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count);
                        vtx_offset += pcmd->vtx_count;
                }
        }

        // Restore modified state
        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glPopAttrib();

        ImImpl_window->popGLStates();
}
There is probably a way so that you don't need to call push/popGLStates but I don't know OpenGL so I can't fix that...
Title: Re: [GUI] SFML backend for ImGui
Post by: bock on March 09, 2015, 10:00:55 am
Would be nice to have that pushed into the main repo.
Title: Re: [GUI] SFML backend for ImGui
Post by: Aster on March 16, 2015, 11:47:27 am
Would be nice to have that pushed into the main repo.

Sorry for my lack of response. I've been extremely busy lately, but I should have the repo updated with much more than this by Sunday (March 22nd). Rendering and event backends will be completely separate, allowing them to be used interchangeably with different libraries.

Not sure if I'll have time, but GLFW and SDL support should also be there soon enough, and I'll try to come up with a clever method for replacing glScissor without using OpenGL directly in the SFML rendering backend.
Title: Re: [GUI] SFML backend for ImGui
Post by: Laurent on March 16, 2015, 04:37:15 pm
Quote
I'll try to come up with a clever method for replacing glScissor without using OpenGL directly in the SFML rendering backend.
The usual workaround is to use a sf::View that has both the rectangle and viewport set to the clipped area.
Title: Re: [GUI] SFML backend for ImGui
Post by: eXpl0it3r on April 23, 2015, 04:46:15 pm
You should really post more than just an imagine. Describe your problem properly.

I've no idea how ImGui does it, but for SFML you'll always have to load a font.

Edit: Don't delete posts, otherwise conversations don't make sense anymore...
Title: Re: [GUI] SFML backend for ImGui
Post by: Memorix101 on April 23, 2015, 05:46:23 pm
It's alright now. ^-^
It's working, now.
I should learn to read .... :P
I forgot to paste the imconfig-SFML stuff in to my imconfig.h
Title: Re: [GUI] SFML backend for ImGui
Post by: Verra on May 29, 2015, 11:30:58 pm
The example at the top of the page is outdated as well as the instructions for how to set it up. The repository shows that you've split a lot of stuff into seperate files. I also noticed in imgui-rendering-SFML there is a reference to ImImpl_fontTex which doesn't exist anywhere as far as I can tell. It'd be nice to see you include an example in the repository. :)
Title: Re: [GUI] SFML backend for ImGui
Post by: Aster on June 28, 2015, 09:46:42 am
I've updated the repository and main post.
The usage has slightly changed, but everything works now.

Sorry for my absence and lack of response, thanks for your patience.
Title: Re: [GUI] SFML backend for ImGui
Post by: bock on July 06, 2015, 02:13:09 am
> What isn't implemented:
>  Stencils. If the horizontal ImGui window size is too small, you'll still see transparent rectangles, as SFML does not provide support for clipping, and I haven't gotten around to working on a solution.

Note that you want scissoring and not stencil. Scissoring is a cheaper operation than stenciling which rely on a buffer.

- For some reason it's not supported in sf::RenderStates. It's a rather rarely used feature but it's also trivial to implement so perhaps it could be added to SFML.

- Otherwise you can do the scissoring in a shader (which is possibly what a graphics card driver would do for do when enabling scissoring anyway). Pass the float4 cliprect as a uniform to your shader and do a clipping in the pixel shader/

( - Or last resort you might be able to use sf::View::setViewport() as a workaround for the clipping, but I don't know how SFML behave in term of performance when changing the viewport. but adding it to the shader would be more sane. )