Created
March 2, 2017 18:28
-
-
Save colesnicov/571d725d376c90569572905ce4b84666 to your computer and use it in GitHub Desktop.
ImGui SFML2 bindings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "imguiSFML.h" | |
#include <SFML/OpenGL.hpp> | |
#include <SFML/Graphics/Color.hpp> | |
#include <SFML/Graphics/RenderTarget.hpp> | |
#include <SFML/Graphics/RenderWindow.hpp> | |
#include <SFML/Graphics/Sprite.hpp> | |
#include <SFML/Graphics/Texture.hpp> | |
#include <SFML/Window/Window.hpp> | |
#include <cstddef> // offsetof, NULL | |
#include <cassert> | |
#include "assetManager/AssetManager.hpp" | |
// Supress warnings caused by converting from uint to void* in pCmd->TextureID | |
#ifdef __clang__ | |
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' | |
#elif defined(__GNUC__) | |
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size | |
#endif | |
static bool s_windowHasFocus = true; | |
static bool s_mousePressed[3] = { false, false, false }; | |
static sf::Texture* s_fontTexture = NULL; // owning pointer to internal font atlas which is used if user doesn't set custom sf::Texture. | |
namespace | |
{ | |
ImVec2 getTopLeftAbsolute(const sf::FloatRect& rect); | |
ImVec2 getDownRightAbsolute(const sf::FloatRect& rect); | |
void RenderDrawLists(ImDrawData* draw_data); // rendering callback function prototype | |
} // anonymous namespace for helper / "private" functions | |
namespace ImGui | |
{ | |
namespace SFML | |
{ | |
void Init(sf::RenderTarget& target, sf::Texture* fontTexture) | |
{ | |
ImGuiIO& io = ImGui::GetIO(); | |
// disable .ini saving. | |
// TODO: mozna to nastavim na etc/configs/blabla.ini? | |
io.IniFilename = NULL; | |
// init keyboard mapping | |
io.KeyMap[ImGuiKey_Tab] = sf::Keyboard::Tab; | |
io.KeyMap[ImGuiKey_LeftArrow] = sf::Keyboard::Left; | |
io.KeyMap[ImGuiKey_RightArrow] = sf::Keyboard::Right; | |
io.KeyMap[ImGuiKey_UpArrow] = sf::Keyboard::Up; | |
io.KeyMap[ImGuiKey_DownArrow] = sf::Keyboard::Down; | |
io.KeyMap[ImGuiKey_PageUp] = sf::Keyboard::PageUp; | |
io.KeyMap[ImGuiKey_PageDown] = sf::Keyboard::PageDown; | |
io.KeyMap[ImGuiKey_Home] = sf::Keyboard::Home; | |
io.KeyMap[ImGuiKey_End] = sf::Keyboard::End; | |
io.KeyMap[ImGuiKey_Delete] = sf::Keyboard::Delete; | |
io.KeyMap[ImGuiKey_Backspace] = sf::Keyboard::BackSpace; | |
io.KeyMap[ImGuiKey_Enter] = sf::Keyboard::Return; | |
io.KeyMap[ImGuiKey_Escape] = sf::Keyboard::Escape; | |
io.KeyMap[ImGuiKey_A] = sf::Keyboard::A; | |
io.KeyMap[ImGuiKey_C] = sf::Keyboard::C; | |
io.KeyMap[ImGuiKey_V] = sf::Keyboard::V; | |
io.KeyMap[ImGuiKey_X] = sf::Keyboard::X; | |
io.KeyMap[ImGuiKey_Y] = sf::Keyboard::Y; | |
io.KeyMap[ImGuiKey_Z] = sf::Keyboard::Z; | |
// init rendering | |
io.DisplaySize = static_cast<sf::Vector2f>(target.getSize()); | |
io.RenderDrawListsFn = RenderDrawLists; // set render callback | |
AssetManager::getInstance()->initFonts(); | |
} | |
void ProcessEvent(const sf::Event& event) | |
{ | |
ImGuiIO& io = ImGui::GetIO(); | |
if (s_windowHasFocus) | |
{ | |
switch (event.type) | |
{ | |
case sf::Event::MouseButtonPressed: // fall-through | |
case sf::Event::MouseButtonReleased: | |
{ | |
int button = event.mouseButton.button; | |
if (event.type == sf::Event::MouseButtonPressed && | |
button >= 0 && button < 3) | |
{ | |
s_mousePressed[event.mouseButton.button] = true; | |
} | |
} | |
break; | |
case sf::Event::MouseWheelMoved: | |
io.MouseWheel += static_cast<float>(event.mouseWheel.delta); | |
break; | |
case sf::Event::KeyPressed: // fall-through | |
case sf::Event::KeyReleased: | |
io.KeysDown[event.key.code] = (event.type == sf::Event::KeyPressed); | |
io.KeyCtrl = event.key.control; | |
io.KeyShift = event.key.shift; | |
io.KeyAlt = event.key.alt; | |
break; | |
case sf::Event::TextEntered: | |
if (event.text.unicode > 0 && event.text.unicode < 0x10000) | |
{ | |
io.AddInputCharacter(static_cast<ImWchar>(event.text.unicode)); | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
switch (event.type) | |
{ | |
case sf::Event::LostFocus: | |
s_windowHasFocus = false; | |
break; | |
case sf::Event::GainedFocus: | |
s_windowHasFocus = true; | |
break; | |
default: | |
break; | |
} | |
} | |
void Update(sf::RenderWindow& window, sf::Time dt) | |
{ | |
Update(window, window, dt); | |
} | |
void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt) | |
{ | |
Update(sf::Mouse::getPosition(window), static_cast<sf::Vector2f>(target.getSize()), dt); | |
window.setMouseCursorVisible(!ImGui::GetIO().MouseDrawCursor); // don't draw mouse cursor if ImGui draws it | |
} | |
void Update(const sf::Vector2i& mousePos, ImVec2 displaySize, sf::Time dt) | |
{ | |
ImGuiIO& io = ImGui::GetIO(); | |
io.DisplaySize = displaySize; | |
io.DeltaTime = dt.asSeconds(); | |
if (s_windowHasFocus) | |
{ | |
io.MousePos = mousePos; | |
for (int i = 0; i < 3; ++i) | |
{ | |
io.MouseDown[i] = s_mousePressed[i] || sf::Mouse::isButtonPressed((sf::Mouse::Button)i); | |
s_mousePressed[i] = false; | |
} | |
} | |
assert(io.Fonts->Fonts.Size > 0); // You forgot to create and set up font atlas (see createFontTexture) | |
ImGui::NewFrame(); | |
} | |
void Shutdown() | |
{ | |
ImGui::GetIO().Fonts->TexID = NULL; | |
ImGui::Shutdown(); // need to specify namespace here, otherwise ImGui::SFML::Shutdown would be called | |
} | |
} // end of namespace SsFML | |
} // end of namespace ImGui | |
namespace | |
{ | |
ImVec2 getTopLeftAbsolute(const sf::FloatRect & rect) | |
{ | |
ImVec2 pos = ImGui::GetCursorScreenPos(); | |
return ImVec2(rect.left + pos.x, rect.top + pos.y); | |
} | |
ImVec2 getDownRightAbsolute(const sf::FloatRect & rect) | |
{ | |
ImVec2 pos = ImGui::GetCursorScreenPos(); | |
return ImVec2(rect.left + rect.width + pos.x, rect.top + rect.height + pos.y); | |
} | |
// Rendering callback | |
void RenderDrawLists(ImDrawData* draw_data) | |
{ | |
if (draw_data->CmdListsCount == 0) | |
{ | |
return; | |
} | |
ImGuiIO& io = ImGui::GetIO(); | |
assert(io.Fonts->TexID != NULL); // You forgot to create and set font texture | |
// scale stuff (needed for proper handling of window resize) | |
int fb_width = static_cast<int>(io.DisplaySize.x * io.DisplayFramebufferScale.x); | |
int fb_height = static_cast<int>(io.DisplaySize.y * io.DisplayFramebufferScale.y); | |
if (fb_width == 0 || fb_height == 0) | |
{ | |
return; | |
} | |
draw_data->ScaleClipRects(io.DisplayFramebufferScale); | |
// Save OpenGL state | |
GLint last_viewport[4]; | |
glGetIntegerv(GL_VIEWPORT, last_viewport); | |
GLint last_texture; | |
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | |
GLint last_scissor_box[4]; | |
glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); | |
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); | |
glEnable(GL_TEXTURE_2D); | |
glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); | |
glMatrixMode(GL_TEXTURE); | |
glPushMatrix(); | |
glLoadIdentity(); | |
glMatrixMode(GL_PROJECTION); | |
glPushMatrix(); | |
glLoadIdentity(); | |
glOrtho(0.0f, io.DisplaySize.x, io.DisplaySize.y, 0.0f, -1.0f, +1.0f); | |
glMatrixMode(GL_MODELVIEW); | |
glPushMatrix(); | |
glLoadIdentity(); | |
for (int n = 0; n < draw_data->CmdListsCount; ++n) | |
{ | |
const ImDrawList* cmd_list = draw_data->CmdLists[n]; | |
const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->VtxBuffer.front(); | |
const ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.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))); | |
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); ++cmd_i) | |
{ | |
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | |
if (pcmd->UserCallback) | |
{ | |
pcmd->UserCallback(cmd_list, pcmd); | |
} | |
else | |
{ | |
GLuint tex_id = (GLuint)*((unsigned int*)&pcmd->TextureId); | |
glBindTexture(GL_TEXTURE_2D, tex_id); | |
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), | |
(int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); | |
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer); | |
} | |
idx_buffer += pcmd->ElemCount; | |
} | |
} | |
// Restore modified state | |
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture); | |
glMatrixMode(GL_TEXTURE); | |
glPopMatrix(); | |
glMatrixMode(GL_MODELVIEW); | |
glPopMatrix(); | |
glMatrixMode(GL_PROJECTION); | |
glPopMatrix(); | |
glPopAttrib(); | |
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); | |
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); | |
} | |
} // end of anonymous namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <SFML/Graphics/Color.hpp> | |
#include <SFML/Graphics/Rect.hpp> | |
#include <SFML/Graphics/RenderWindow.hpp> | |
#include <SFML/Graphics/Sprite.hpp> | |
#include <SFML/Graphics/Texture.hpp> | |
#include <SFML/System/Time.hpp> | |
#include <SFML/System/Vector2.hpp> | |
#include <SFML/Window/Event.hpp> | |
#include "imgui/imgui.h" | |
namespace ImGui | |
{ | |
namespace SFML | |
{ | |
void Init(sf::RenderTarget& target, sf::Texture* fontTexture = NULL); | |
void ProcessEvent(const sf::Event& event); | |
void Update(sf::RenderWindow& window, sf::Time dt); | |
void Update(sf::Window& window, sf::RenderTarget& target, sf::Time dt); | |
void Update(const sf::Vector2i& mousePos, ImVec2 displaySize, sf::Time dt); | |
void Shutdown(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment