parent
33a8e3af8b
commit
dd44955f33
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2018 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,419 +0,0 @@
|
||||
#include "imgui/imgui-SFML.h"
|
||||
#include "imgui/imgui.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/Event.hpp>
|
||||
#include <SFML/Window/Window.hpp>
|
||||
|
||||
#include <cstddef> // offsetof, NULL
|
||||
#include <cassert>
|
||||
|
||||
// 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);
|
||||
|
||||
inline void RenderDrawLists(ImDrawData* draw_data); // rendering callback function prototype
|
||||
|
||||
// Implementation of ImageButton overload
|
||||
bool imageButtonImpl(const sf::Texture& texture, const sf::FloatRect& textureRect, const sf::Vector2f& size, const int framePadding,
|
||||
const sf::Color& bgColor, const sf::Color& tintColor);
|
||||
|
||||
} // anonymous namespace for helper / "private" functions
|
||||
|
||||
namespace ImGui
|
||||
{
|
||||
namespace SFML
|
||||
{
|
||||
|
||||
void Init(sf::RenderTarget& target, sf::Texture* fontTexture)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// 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
|
||||
|
||||
if (fontTexture == NULL) {
|
||||
if (s_fontTexture) { // delete previously created texture
|
||||
delete s_fontTexture;
|
||||
}
|
||||
|
||||
s_fontTexture = new sf::Texture;
|
||||
createFontTexture(*s_fontTexture);
|
||||
setFontTexture(*s_fontTexture);
|
||||
} else {
|
||||
setFontTexture(*fontTexture);
|
||||
}
|
||||
}
|
||||
|
||||
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, const sf::Vector2f& 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;
|
||||
|
||||
if (s_fontTexture) { // if internal texture was created, we delete it
|
||||
delete s_fontTexture;
|
||||
s_fontTexture = NULL;
|
||||
}
|
||||
|
||||
ImGui::Shutdown(); // need to specify namespace here, otherwise ImGui::SFML::Shutdown would be called
|
||||
}
|
||||
|
||||
void createFontTexture(sf::Texture& texture)
|
||||
{
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
texture.create(width, height);
|
||||
texture.update(pixels);
|
||||
|
||||
io.Fonts->ClearInputData();
|
||||
io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
void setFontTexture(sf::Texture& texture)
|
||||
{
|
||||
ImGui::GetIO().Fonts->TexID = (void*)texture.getNativeHandle();
|
||||
if (&texture != s_fontTexture) { // internal texture is not needed anymore
|
||||
delete s_fontTexture;
|
||||
s_fontTexture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace SFML
|
||||
|
||||
|
||||
/////////////// Image Overloads
|
||||
|
||||
void Image(const sf::Texture& texture,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
Image(texture, static_cast<sf::Vector2f>(texture.getSize()), tintColor, borderColor);
|
||||
}
|
||||
|
||||
void Image(const sf::Texture& texture, const sf::Vector2f& size,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
ImGui::Image((void*)texture.getNativeHandle(), size, ImVec2(0, 0), ImVec2(1, 1), tintColor, borderColor);
|
||||
}
|
||||
|
||||
void Image(const sf::Texture& texture, const sf::FloatRect& textureRect,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
Image(texture, sf::Vector2f(textureRect.width, textureRect.height), textureRect, tintColor, borderColor);
|
||||
}
|
||||
|
||||
void Image(const sf::Texture& texture, const sf::Vector2f& size, const sf::FloatRect& textureRect,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
sf::Vector2f textureSize = static_cast<sf::Vector2f>(texture.getSize());
|
||||
ImVec2 uv0(textureRect.left / textureSize.x, textureRect.top / textureSize.y);
|
||||
ImVec2 uv1((textureRect.left + textureRect.width) / textureSize.x,
|
||||
(textureRect.top + textureRect.height) / textureSize.y);
|
||||
ImGui::Image((void*)texture.getNativeHandle(), size, uv0, uv1, tintColor, borderColor);
|
||||
}
|
||||
|
||||
void Image(const sf::Sprite& sprite,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
sf::FloatRect bounds = sprite.getGlobalBounds();
|
||||
Image(sprite, sf::Vector2f(bounds.width, bounds.height), tintColor, borderColor);
|
||||
}
|
||||
|
||||
void Image(const sf::Sprite& sprite, const sf::Vector2f& size,
|
||||
const sf::Color& tintColor, const sf::Color& borderColor)
|
||||
{
|
||||
const sf::Texture* texturePtr = sprite.getTexture();
|
||||
// sprite without texture cannot be drawn
|
||||
if (!texturePtr) { return; }
|
||||
|
||||
Image(*texturePtr, size, tintColor, borderColor);
|
||||
}
|
||||
|
||||
/////////////// Image Button Overloads
|
||||
|
||||
bool ImageButton(const sf::Texture& texture,
|
||||
const int framePadding, const sf::Color& bgColor, const sf::Color& tintColor)
|
||||
{
|
||||
return ImageButton(texture, static_cast<sf::Vector2f>(texture.getSize()), framePadding, bgColor, tintColor);
|
||||
}
|
||||
|
||||
bool ImageButton(const sf::Texture& texture, const sf::Vector2f& size,
|
||||
const int framePadding, const sf::Color& bgColor, const sf::Color& tintColor)
|
||||
{
|
||||
sf::Vector2f textureSize = static_cast<sf::Vector2f>(texture.getSize());
|
||||
return ::imageButtonImpl(texture, sf::FloatRect(0.f, 0.f, textureSize.x, textureSize.y), size, framePadding, bgColor, tintColor);
|
||||
}
|
||||
|
||||
bool ImageButton(const sf::Sprite& sprite,
|
||||
const int framePadding, const sf::Color& bgColor, const sf::Color& tintColor)
|
||||
{
|
||||
sf::FloatRect spriteSize = sprite.getGlobalBounds();
|
||||
return ImageButton(sprite, sf::Vector2f(spriteSize.width, spriteSize.height), framePadding, bgColor, tintColor);
|
||||
}
|
||||
|
||||
bool ImageButton(const sf::Sprite& sprite, const sf::Vector2f& size,
|
||||
const int framePadding, const sf::Color& bgColor, const sf::Color& tintColor)
|
||||
{
|
||||
const sf::Texture* texturePtr = sprite.getTexture();
|
||||
if (!texturePtr) { return false; }
|
||||
return ::imageButtonImpl(*texturePtr, static_cast<sf::FloatRect>(sprite.getTextureRect()), size, framePadding, bgColor, tintColor);
|
||||
}
|
||||
|
||||
/////////////// Draw_list Overloads
|
||||
|
||||
void DrawLine(const sf::Vector2f& a, const sf::Vector2f& b, const sf::Color& color,
|
||||
float thickness)
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
sf::Vector2f pos = ImGui::GetCursorScreenPos();
|
||||
draw_list->AddLine(a + pos, b + pos, ColorConvertFloat4ToU32(color), thickness);
|
||||
}
|
||||
|
||||
void DrawRect(const sf::FloatRect& rect, const sf::Color& color,
|
||||
float rounding, int rounding_corners, float thickness)
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->AddRect(
|
||||
getTopLeftAbsolute(rect),
|
||||
getDownRightAbsolute(rect),
|
||||
ColorConvertFloat4ToU32(color), rounding, rounding_corners, thickness);
|
||||
}
|
||||
|
||||
void DrawRectFilled(const sf::FloatRect& rect, const sf::Color& color,
|
||||
float rounding, int rounding_corners)
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->AddRect(
|
||||
getTopLeftAbsolute(rect),
|
||||
getDownRightAbsolute(rect),
|
||||
ColorConvertFloat4ToU32(color), rounding, rounding_corners);
|
||||
}
|
||||
|
||||
} // 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]);
|
||||
}
|
||||
|
||||
bool imageButtonImpl(const sf::Texture& texture, const sf::FloatRect& textureRect, const sf::Vector2f& size, const int framePadding,
|
||||
const sf::Color& bgColor, const sf::Color& tintColor)
|
||||
{
|
||||
sf::Vector2f textureSize = static_cast<sf::Vector2f>(texture.getSize());
|
||||
|
||||
ImVec2 uv0(textureRect.left / textureSize.x, textureRect.top / textureSize.y);
|
||||
ImVec2 uv1((textureRect.left + textureRect.width) / textureSize.x,
|
||||
(textureRect.top + textureRect.height) / textureSize.y);
|
||||
|
||||
return ImGui::ImageButton((void*)texture.getNativeHandle(), size, uv0, uv1, framePadding, bgColor, tintColor);
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
@ -1,186 +1,187 @@
|
||||
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
static ImU32 InvertColorU32(ImU32 in)
|
||||
{
|
||||
ImVec4 in4 = ColorConvertU32ToFloat4(in);
|
||||
in4.x = 1.f - in4.x;
|
||||
in4.y = 1.f - in4.y;
|
||||
in4.z = 1.f - in4.z;
|
||||
return GetColorU32(in4);
|
||||
}
|
||||
|
||||
static void PlotMultiEx(
|
||||
ImGuiPlotType plot_type,
|
||||
const char* label,
|
||||
int num_datas,
|
||||
const char** names,
|
||||
const ImColor* colors,
|
||||
float(*getter)(const void* data, int idx),
|
||||
const void * const * datas,
|
||||
int values_count,
|
||||
float scale_min,
|
||||
float scale_max,
|
||||
ImVec2 graph_size)
|
||||
{
|
||||
const int values_offset = 0;
|
||||
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
||||
if (graph_size.x == 0.0f)
|
||||
graph_size.x = CalcItemWidth();
|
||||
if (graph_size.y == 0.0f)
|
||||
graph_size.y = label_size.y + (style.FramePadding.y * 2);
|
||||
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y));
|
||||
const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, NULL))
|
||||
return;
|
||||
|
||||
// Determine scale from values if not specified
|
||||
if (scale_min == FLT_MAX || scale_max == FLT_MAX)
|
||||
{
|
||||
float v_min = FLT_MAX;
|
||||
float v_max = -FLT_MAX;
|
||||
for (int data_idx = 0; data_idx < num_datas; ++data_idx)
|
||||
{
|
||||
for (int i = 0; i < values_count; i++)
|
||||
{
|
||||
const float v = getter(datas[data_idx], i);
|
||||
v_min = ImMin(v_min, v);
|
||||
v_max = ImMax(v_max, v);
|
||||
}
|
||||
}
|
||||
if (scale_min == FLT_MAX)
|
||||
scale_min = v_min;
|
||||
if (scale_max == FLT_MAX)
|
||||
scale_max = v_max;
|
||||
}
|
||||
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
|
||||
int res_w = ImMin((int) graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
|
||||
int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
|
||||
|
||||
// Tooltip on hover
|
||||
int v_hovered = -1;
|
||||
if (IsHovered(inner_bb, 0))
|
||||
{
|
||||
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
|
||||
const int v_idx = (int) (t * item_count);
|
||||
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
|
||||
|
||||
// std::string toolTip;
|
||||
ImGui::BeginTooltip();
|
||||
const int idx0 = (v_idx + values_offset) % values_count;
|
||||
if (plot_type == ImGuiPlotType_Lines)
|
||||
{
|
||||
const int idx1 = (v_idx + 1 + values_offset) % values_count;
|
||||
Text("%8d %8d | Name", v_idx, v_idx+1);
|
||||
for (int dataIdx = 0; dataIdx < num_datas; ++dataIdx)
|
||||
{
|
||||
const float v0 = getter(datas[dataIdx], idx0);
|
||||
const float v1 = getter(datas[dataIdx], idx1);
|
||||
TextColored(colors[dataIdx], "%8.4g %8.4g | %s", v0, v1, names[dataIdx]);
|
||||
}
|
||||
}
|
||||
else if (plot_type == ImGuiPlotType_Histogram)
|
||||
{
|
||||
for (int dataIdx = 0; dataIdx < num_datas; ++dataIdx)
|
||||
{
|
||||
const float v0 = getter(datas[dataIdx], idx0);
|
||||
TextColored(colors[dataIdx], "%d: %8.4g | %s", v_idx, v0, names[dataIdx]);
|
||||
}
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
v_hovered = v_idx;
|
||||
}
|
||||
|
||||
for (int data_idx = 0; data_idx < num_datas; ++data_idx)
|
||||
{
|
||||
const float t_step = 1.0f / (float) res_w;
|
||||
|
||||
float v0 = getter(datas[data_idx], (0 + values_offset) % values_count);
|
||||
float t0 = 0.0f;
|
||||
ImVec2 tp0 = ImVec2(t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min))); // Point in the normalized space of our target rectangle
|
||||
|
||||
const ImU32 col_base = colors[data_idx];
|
||||
const ImU32 col_hovered = InvertColorU32(colors[data_idx]);
|
||||
|
||||
//const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
|
||||
//const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
|
||||
|
||||
for (int n = 0; n < res_w; n++)
|
||||
{
|
||||
const float t1 = t0 + t_step;
|
||||
const int v1_idx = (int) (t0 * item_count + 0.5f);
|
||||
IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
|
||||
const float v1 = getter(datas[data_idx], (v1_idx + values_offset + 1) % values_count);
|
||||
const ImVec2 tp1 = ImVec2(t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)));
|
||||
|
||||
// NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
|
||||
ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
|
||||
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f));
|
||||
if (plot_type == ImGuiPlotType_Lines)
|
||||
{
|
||||
window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
|
||||
}
|
||||
else if (plot_type == ImGuiPlotType_Histogram)
|
||||
{
|
||||
if (pos1.x >= pos0.x + 2.0f)
|
||||
pos1.x -= 1.0f;
|
||||
window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
|
||||
}
|
||||
|
||||
t0 = t1;
|
||||
tp0 = tp1;
|
||||
}
|
||||
}
|
||||
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
|
||||
}
|
||||
|
||||
void PlotMultiLines(
|
||||
const char* label,
|
||||
int num_datas,
|
||||
const char** names,
|
||||
const ImColor* colors,
|
||||
float(*getter)(const void* data, int idx),
|
||||
const void * const * datas,
|
||||
int values_count,
|
||||
float scale_min,
|
||||
float scale_max,
|
||||
ImVec2 graph_size)
|
||||
{
|
||||
PlotMultiEx(ImGuiPlotType_Lines, label, num_datas, names, colors, getter, datas, values_count, scale_min, scale_max, graph_size);
|
||||
}
|
||||
|
||||
void PlotMultiHistograms(
|
||||
const char* label,
|
||||
int num_hists,
|
||||
const char** names,
|
||||
const ImColor* colors,
|
||||
float(*getter)(const void* data, int idx),
|
||||
const void * const * datas,
|
||||
int values_count,
|
||||
float scale_min,
|
||||
float scale_max,
|
||||
ImVec2 graph_size)
|
||||
{
|
||||
PlotMultiEx(ImGuiPlotType_Histogram, label, num_hists, names, colors, getter, datas, values_count, scale_min, scale_max, graph_size);
|
||||
}
|
||||
|
||||
} // namespace ImGui
|
||||
//
|
||||
//#pragma once
|
||||
//#include "imgui.h"
|
||||
//#include "imgui_internal.h"
|
||||
//
|
||||
//
|
||||
//
|
||||
//namespace ImGui {
|
||||
//
|
||||
// static ImU32 InvertColorU32(ImU32 in)
|
||||
// {
|
||||
// ImVec4 in4 = ColorConvertU32ToFloat4(in);
|
||||
// in4.x = 1.f - in4.x;
|
||||
// in4.y = 1.f - in4.y;
|
||||
// in4.z = 1.f - in4.z;
|
||||
// return GetColorU32(in4);
|
||||
// }
|
||||
//
|
||||
// static void PlotMultiEx(
|
||||
// ImGuiPlotType plot_type,
|
||||
// const char* label,
|
||||
// int num_datas,
|
||||
// const char** names,
|
||||
// const ImColor* colors,
|
||||
// float(*getter)(const void* data, int idx),
|
||||
// const void * const * datas,
|
||||
// int values_count,
|
||||
// float scale_min,
|
||||
// float scale_max,
|
||||
// ImVec2 graph_size)
|
||||
// {
|
||||
// const int values_offset = 0;
|
||||
//
|
||||
// ImGuiWindow* window = GetCurrentWindow();
|
||||
// if (window->SkipItems)
|
||||
// return;
|
||||
//
|
||||
// ImGuiContext& g = *GImGui;
|
||||
// const ImGuiStyle& style = g.Style;
|
||||
//
|
||||
// const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
||||
// if (graph_size.x == 0.0f)
|
||||
// graph_size.x = CalcItemWidth();
|
||||
// if (graph_size.y == 0.0f)
|
||||
// graph_size.y = label_size.y + (style.FramePadding.y * 2);
|
||||
//
|
||||
// const ImRect frame_bb();//window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y));
|
||||
// const ImRect inner_bb();//frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
|
||||
// const ImRect total_bb();//frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
|
||||
// ItemSize(total_bb, style.FramePadding.y);
|
||||
// if (!ItemAdd(total_bb, NULL))
|
||||
// return;
|
||||
//
|
||||
// // Determine scale from values if not specified
|
||||
// if (scale_min == FLT_MAX || scale_max == FLT_MAX)
|
||||
// {
|
||||
// float v_min = FLT_MAX;
|
||||
// float v_max = -FLT_MAX;
|
||||
// for (int data_idx = 0; data_idx < num_datas; ++data_idx)
|
||||
// {
|
||||
// for (int i = 0; i < values_count; i++)
|
||||
// {
|
||||
// const float v = getter(datas[data_idx], i);
|
||||
// v_min = ImMin(v_min, v);
|
||||
// v_max = ImMax(v_max, v);
|
||||
// }
|
||||
// }
|
||||
// if (scale_min == FLT_MAX)
|
||||
// scale_min = v_min;
|
||||
// if (scale_max == FLT_MAX)
|
||||
// scale_max = v_max;
|
||||
// }
|
||||
//
|
||||
// RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
//
|
||||
// int res_w = ImMin((int) graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
|
||||
// int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
|
||||
//
|
||||
// // Tooltip on hover
|
||||
// int v_hovered = -1;
|
||||
// if (IsHovered(inner_bb, 0))
|
||||
// {
|
||||
// const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
|
||||
// const int v_idx = (int) (t * item_count);
|
||||
// IM_ASSERT(v_idx >= 0 && v_idx < values_count);
|
||||
//
|
||||
// // std::string toolTip;
|
||||
// ImGui::BeginTooltip();
|
||||
// const int idx0 = (v_idx + values_offset) % values_count;
|
||||
// if (plot_type == ImGuiPlotType_Lines)
|
||||
// {
|
||||
// const int idx1 = (v_idx + 1 + values_offset) % values_count;
|
||||
// Text("%8d %8d | Name", v_idx, v_idx+1);
|
||||
// for (int dataIdx = 0; dataIdx < num_datas; ++dataIdx)
|
||||
// {
|
||||
// const float v0 = getter(datas[dataIdx], idx0);
|
||||
// const float v1 = getter(datas[dataIdx], idx1);
|
||||
// TextColored(colors[dataIdx], "%8.4g %8.4g | %s", v0, v1, names[dataIdx]);
|
||||
// }
|
||||
// }
|
||||
// else if (plot_type == ImGuiPlotType_Histogram)
|
||||
// {
|
||||
// for (int dataIdx = 0; dataIdx < num_datas; ++dataIdx)
|
||||
// {
|
||||
// const float v0 = getter(datas[dataIdx], idx0);
|
||||
// TextColored(colors[dataIdx], "%d: %8.4g | %s", v_idx, v0, names[dataIdx]);
|
||||
// }
|
||||
// }
|
||||
// ImGui::EndTooltip();
|
||||
// v_hovered = v_idx;
|
||||
// }
|
||||
//
|
||||
// for (int data_idx = 0; data_idx < num_datas; ++data_idx)
|
||||
// {
|
||||
// const float t_step = 1.0f / (float) res_w;
|
||||
//
|
||||
// float v0 = getter(datas[data_idx], (0 + values_offset) % values_count);
|
||||
// float t0 = 0.0f;
|
||||
// ImVec2 tp0 = ImVec2(t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min))); // Point in the normalized space of our target rectangle
|
||||
//
|
||||
// const ImU32 col_base = colors[data_idx];
|
||||
// const ImU32 col_hovered = InvertColorU32(colors[data_idx]);
|
||||
//
|
||||
// //const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
|
||||
// //const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
|
||||
//
|
||||
// for (int n = 0; n < res_w; n++)
|
||||
// {
|
||||
// const float t1 = t0 + t_step;
|
||||
// const int v1_idx = (int) (t0 * item_count + 0.5f);
|
||||
// IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
|
||||
// const float v1 = getter(datas[data_idx], (v1_idx + values_offset + 1) % values_count);
|
||||
// const ImVec2 tp1 = ImVec2(t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)));
|
||||
//
|
||||
// // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
|
||||
// ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
|
||||
// ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f));
|
||||
// if (plot_type == ImGuiPlotType_Lines)
|
||||
// {
|
||||
// window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
|
||||
// }
|
||||
// else if (plot_type == ImGuiPlotType_Histogram)
|
||||
// {
|
||||
// if (pos1.x >= pos0.x + 2.0f)
|
||||
// pos1.x -= 1.0f;
|
||||
// window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
|
||||
// }
|
||||
//
|
||||
// t0 = t1;
|
||||
// tp0 = tp1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
|
||||
//}
|
||||
//
|
||||
//void PlotMultiLines(
|
||||
// const char* label,
|
||||
// int num_datas,
|
||||
// const char** names,
|
||||
// const ImColor* colors,
|
||||
// float(*getter)(const void* data, int idx),
|
||||
// const void * const * datas,
|
||||
// int values_count,
|
||||
// float scale_min,
|
||||
// float scale_max,
|
||||
// ImVec2 graph_size)
|
||||
//{
|
||||
// PlotMultiEx(ImGuiPlotType_Lines, label, num_datas, names, colors, getter, datas, values_count, scale_min, scale_max, graph_size);
|
||||
//}
|
||||
//
|
||||
//void PlotMultiHistograms(
|
||||
// const char* label,
|
||||
// int num_hists,
|
||||
// const char** names,
|
||||
// const ImColor* colors,
|
||||
// float(*getter)(const void* data, int idx),
|
||||
// const void * const * datas,
|
||||
// int values_count,
|
||||
// float scale_min,
|
||||
// float scale_max,
|
||||
// ImVec2 graph_size)
|
||||
//{
|
||||
// PlotMultiEx(ImGuiPlotType_Histogram, label, num_hists, names, colors, getter, datas, values_count, scale_min, scale_max, graph_size);
|
||||
//}
|
||||
//
|
||||
//} // namespace ImGui
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue