ENH: font preview

Change-Id: I8151036cedcba9c57183414a9d134741bb2166a5
Signed-off-by: Stone Li <stone.li@bambulab.com>
This commit is contained in:
liz.li 2022-12-10 18:51:24 +08:00 committed by Lane.Wei
parent 4ee5dbb07f
commit 110d81f6f7
9 changed files with 372 additions and 26 deletions

View file

@ -620,6 +620,7 @@ namespace ImGui
// - A selectable highlights when hovered, and can display another color when selected.
// - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous.
IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
IMGUI_API bool BBLImageSelectable(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& font_size, int font_line, const ImVec4& tint_col, const ImVec2& uv0, const ImVec2& uv1, bool selected = false);
IMGUI_API bool BBLSelectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.

View file

@ -7064,6 +7064,161 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
return pressed;
}
bool ImGui::BBLImageSelectable(ImTextureID user_texture_id, const ImVec2& size_arg, const ImVec2& font_size, int font_line, const ImVec4& tint_col, const ImVec2& uv0, const ImVec2& uv1, bool selected)
{
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
PushID((void*)(intptr_t)user_texture_id);
const ImGuiID id = window->GetID("#BBLImageSelectable");
PopID();
ImGuiSelectableFlags flags = 0;
// Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : 0.0f, size_arg.y != 0.0f ? size_arg.y : 0.0f);
ImVec2 pos = window->DC.CursorPos;
pos.y += window->DC.CurrLineTextBaseOffset;
ItemSize(size, 0.0f);
// Fill horizontal space
// We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitly right-aligned sizes not visibly match other widgets.
const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0;
const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x;
const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x;
if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) size.x = ImMax(0.0f, max_x - min_x);
// Text stays at the submission position, but bounding box may be extended on both sides
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 text_min = ImVec2(pos.x + arrow_size, pos.y);
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
ImRect bb(min_x, pos.y, text_max.x, text_max.y);
if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) {
const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x;
const float spacing_y = style.ItemSpacing.y;
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
bb.Min.x -= spacing_L;
bb.Min.y -= spacing_U;
bb.Max.x += (spacing_x - spacing_L);
bb.Max.y += (spacing_y - spacing_U);
}
// if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); }
// Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackground for every Selectable..
const float backup_clip_rect_min_x = window->ClipRect.Min.x;
const float backup_clip_rect_max_x = window->ClipRect.Max.x;
if (span_all_columns) {
window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
}
bool item_add;
if (flags & ImGuiSelectableFlags_Disabled) {
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
item_add = ItemAdd(bb, id);
g.CurrentItemFlags = backup_item_flags;
}
else {
item_add = ItemAdd(bb, id);
}
if (span_all_columns) {
window->ClipRect.Min.x = backup_clip_rect_min_x;
window->ClipRect.Max.x = backup_clip_rect_max_x;
}
if (!item_add) return false;
// FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only,
// which would be advantageous since most selectable are not selected.
if (span_all_columns && window->DC.CurrentColumns)
PushColumnsBackground();
else if (span_all_columns && g.CurrentTable)
TablePushBackgroundChannel();
// We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
ImGuiButtonFlags button_flags = 0;
if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; }
if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; }
if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; }
if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; }
if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
if (flags & ImGuiSelectableFlags_Disabled) selected = false;
const bool was_selected = selected;
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
if (hovered || g.ActiveId == id) {
ImGui::PushStyleColor(ImGuiCol_Border, GetColorU32(ImGuiCol_BorderActive));
if (arrow_size == 0) {
RenderFrameBorder(bb.Min, ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), style.FrameRounding);
}
else {
RenderFrameBorder(ImVec2(bb.Min.x + style.WindowPadding.x, bb.Min.y), ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), style.FrameRounding);
}
ImGui::PopStyleColor(1);
}
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) {
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) {
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos));
g.NavDisableHighlight = true;
}
}
if (pressed) MarkItemEdited(id);
if (flags & ImGuiSelectableFlags_AllowItemOverlap) SetItemAllowOverlap();
// In this branch, Selectable() cannot toggle the selection so this will never trigger.
if (selected != was_selected) //-V547
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
// Render
if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) hovered = true;
if (hovered || selected) {
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
if (arrow_size == 0) {
RenderFrame(bb.Min, ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), col, false, 0.0f);
}
else {
RenderFrame(ImVec2(bb.Min.x + style.WindowPadding.x, bb.Min.y), ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), col, false, 0.0f);
}
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
}
if (span_all_columns && window->DC.CurrentColumns)
PopColumnsBackground();
else if (span_all_columns && g.CurrentTable)
TablePopBackgroundChannel();
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
// Render
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImVec2 p_min = bb.Min + ImVec2(2 * style.ItemSpacing.x, (bb.Max.y - bb.Min.y - font_size.y) / 2);
ImVec2 p_max = p_min + font_size;
window->DrawList->AddImage(user_texture_id, p_min, p_max, uv0, uv1, GetColorU32(tint_col));
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
// Automatically close popups
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed;
}
bool ImGui::BBLSelectable(const char *label, bool selected, ImGuiSelectableFlags flags, const ImVec2 &size_arg)
{
ImGuiWindow *window = GetCurrentWindow();

View file

@ -34,7 +34,7 @@ static std::map<std::string, std::string> g_occt_fonts_maps; //map<font_name, fo
static const std::vector<Standard_CString> fonts_suffix{ "Bold", "Medium", "Heavy", "Italic", "Oblique", "Inclined", "Light", "Thin",
"Semibold", "ExtraBold", "ExtraBold", "Semilight", "SemiLight", "ExtraLight", "Extralight", "Ultralight",
"Condensed", "Ultra", "Extra", "Expanded", "Extended", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Noto Sans"};
"Condensed", "Ultra", "Extra", "Expanded", "Extended", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Al Tarikh"};
std::map<std::string, std::string> get_occt_fonts_maps()
{

View file

@ -1881,6 +1881,8 @@ void GLCanvas3D::render(bool only_init)
_render_overlays();
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
ImGui::ShowMetricsWindow();
ImGuiWrapper& imgui = *wxGetApp().imgui();
imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
imgui.text("FPS (SwapBuffers() calls per second):");

View file

@ -27,6 +27,7 @@
#include "libslic3r/Utils.hpp"
#include "GUI_App.hpp"
#include <wx/dcgraph.h>
namespace Slic3r {
namespace GUI {
@ -468,7 +469,13 @@ void GLTexture::reset()
m_original_width = m_original_height = 0;
}
bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &font, wxColor background, wxColor foreground)
bool GLTexture::generate_from_text_string(const std::string& text_str, wxFont &font, wxColor background, wxColor foreground)
{
int w,h,hl;
return generate_from_text(text_str, font, background, foreground);
}
bool GLTexture::generate_from_text(const std::string &text_str, wxFont &font, wxColor background, wxColor foreground)
{
if (text_str.empty())
{
@ -488,7 +495,7 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
m_original_width = (int)w;
m_original_height = (int)h;
m_width = (int)next_highest_power_of_2((uint32_t)w);
m_height = (int)next_highest_power_of_2((uint32_t)h);
m_height = (int)next_highest_power_of_2((uint32_t)h);
// generates bitmap
wxBitmap bitmap(m_width, m_height);
@ -499,7 +506,7 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
// draw message
memDC.SetTextForeground(*wxWHITE);
memDC.DrawLabel(msg, wxRect(0,0, m_original_width, m_original_height), wxALIGN_CENTER);
memDC.DrawLabel(msg, wxRect(0, 0, m_original_width, m_original_height), wxALIGN_CENTER);
memDC.SelectObject(wxNullBitmap);
@ -508,7 +515,7 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
const unsigned char *src = image.GetData();
const unsigned char* src = image.GetData();
/* for debug use
std::ofstream fout;
fout.open(text_str+std::to_string(m_width)+"_"+std::to_string(m_height)+".rgb", std::ios::out);
@ -520,7 +527,7 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
*dst++ = foreground.Red();
*dst++ = foreground.Green();
*dst++ = foreground.Blue();
*dst++ = (unsigned char)std::min<int>(255, *src);
*dst++ = (unsigned char)std::min<int>(255, *src);
src += 3;
}
}
@ -530,9 +537,9 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id));
if (GLEW_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
@ -541,6 +548,111 @@ bool GLTexture::generate_from_text_string(const std::string &text_str, wxFont &f
return true;
}
bool GLTexture::generate_texture_from_text(const std::string& text_str, wxFont& font, int& ww, int& hh, int& hl, wxColor background, wxColor foreground)
{
if (text_str.empty())
{
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":no text string, should not happen\n";
return false;
}
wxString msg = _(text_str);
wxMemoryDC memDC;
memDC.SetFont(font);
// calculates texture size
wxCoord w, h, ll;
wxClientDC dc(wxGetApp().GetTopWindow());
dc.SetFont(font);
dc.GetMultiLineTextExtent(msg, &w, &h, &ll, &font);
m_original_width = (int)w;
m_original_height = (int)h;
m_width = (int)next_highest_power_of_2((uint32_t)w);
m_height = (int)next_highest_power_of_2((uint32_t)h);
ww = m_width;
hh = m_height;
hl = ll;
// generates bitmap
wxBitmap bitmap(m_width, m_height);
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(background));
memDC.Clear();
// draw message
memDC.SetTextForeground(*wxWHITE);
wxGCDC dc2(memDC);
dc2.SetFont(font);
dc2.SetBackground(wxBrush(background));
dc2.SetTextForeground(*wxWHITE);
dc2.DrawLabel(msg, wxRect(0, 0, m_width, m_height), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
wxImage image = bitmap.ConvertToImage();
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
const unsigned char* src = image.GetData();
/* for debug use
std::ofstream fout;
fout.open(text_str+std::to_string(m_width)+"_"+std::to_string(m_height)+".rgb", std::ios::out);
fout.write((const char*)src, 3 * m_width * m_height);
fout.close();*/
bool found = false;
for (int h = 0; h < m_height; ++h) {
unsigned char* dst = data.data() + 4 * h * m_width;
for (int w = 0; w < m_width; ++w) {
*dst++ = foreground.Red();
*dst++ = foreground.Green();
*dst++ = foreground.Blue();
*dst++ = (unsigned char)std::min<int>(255, *src);
if ((*src) != background.Red() && !found) {
found = true;
if (m_height - h < font.GetPointSize())
return false;
}
src += 3;
}
}
if (!found)
return false;
found = false;
src -= 3;
for (int h = m_height; h > 0; --h) {
for (int w = m_width; w > 0; --w) {
if ((*src) != background.Red() && !found) {
found = true;
if (h < font.GetPointSize())
return false;
}
src -= 3;
}
}
if (!found)
return false;
// sends buffer to gpu
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glGenTextures(1, &m_id));
glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id));
if (GLEW_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
return true;
}
void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top)
{

View file

@ -106,7 +106,10 @@ namespace GUI {
//BBS: add generate logic for text strings
int m_original_width;
int m_original_height;
bool generate_from_text_string(const std::string &text_str, wxFont &font, wxColor background = *wxBLACK, wxColor foreground = *wxWHITE);
bool generate_texture_from_text(const std::string& text_str, wxFont& font, int& ww, int& hh, int &hl, wxColor background = *wxBLACK, wxColor foreground = *wxWHITE);
bool generate_from_text(const std::string& text_str, wxFont& font, wxColor background = *wxBLACK, wxColor foreground = *wxWHITE);
bool generate_from_text_string(const std::string& text_str, wxFont& font, wxColor background = *wxBLACK, wxColor foreground = *wxWHITE);
unsigned int get_id() const { return m_id; }
int get_width() const { return m_width; }

View file

@ -185,7 +185,7 @@ public:
void render() { m_tooltip.clear(); on_render(); }
void render_for_picking() { on_render_for_picking(); }
void render_input_window(float x, float y, float bottom_limit);
void on_change_color_mode(bool is_dark) { m_is_dark_mode = is_dark; }
virtual void on_change_color_mode(bool is_dark) { m_is_dark_mode = is_dark; }
virtual std::string get_tooltip() const { return ""; }

View file

@ -23,20 +23,66 @@
namespace Slic3r {
namespace GUI {
static double g_normal_precise = 0.0015;
static const wxColour FONT_TEXTURE_BG = wxColour(0, 0, 0, 0);
static const wxColour FONT_TEXTURE_FG = *wxWHITE;
static const int FONT_SIZE = 12;
GLGizmoText::GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
{
}
GLGizmoText::~GLGizmoText()
{
for (int i = 0; i < m_textures.size(); i++) {
if (m_textures[i].texture != nullptr)
delete m_textures[i].texture;
}
}
bool GLGizmoText::on_init()
{
m_avail_font_names = init_occt_fonts();
update_font_texture();
m_scale = m_imgui->get_font_size();
m_shortcut_key = WXK_CONTROL_T;
return true;
}
void GLGizmoText::update_font_texture()
{
for (int i = 0; i < m_textures.size(); i++) {
if (m_textures[i].texture != nullptr)
delete m_textures[i].texture;
}
m_combo_width = 0.0f;
m_combo_height = 0.0f;
m_textures.clear();
m_textures.reserve(m_avail_font_names.size());
for (int i = 0; i < m_avail_font_names.size(); i++)
{
GLTexture* texture = new GLTexture();
auto face = wxString::FromUTF8(m_avail_font_names[i]);
auto retina_scale = m_parent.get_scale();
wxFont font { (int)round(retina_scale * FONT_SIZE), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, face };
int w, h, hl;
if (texture->generate_texture_from_text(m_avail_font_names[i], font, w, h, hl, FONT_TEXTURE_BG, FONT_TEXTURE_FG)) {
//if (h < m_imgui->scaled(2.f)) {
TextureInfo info;
info.texture = texture;
info.w = w;
info.h = h;
info.hl = hl;
info.font_name = m_avail_font_names[i];
m_textures.push_back(info);
m_combo_width = std::max(m_combo_width, static_cast<float>(texture->m_original_width));
//}
}
}
m_combo_height = m_imgui->scaled(32.f / 15.f);
}
void GLGizmoText::on_set_state()
{
}
@ -114,6 +160,8 @@ void GLGizmoText::push_combo_style(const float scale) {
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG_DARK);
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImGuiWrapper::COL_WINDOW_BG_DARK);
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImGuiWrapper::COL_WINDOW_BG_DARK);
ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f });
}
else {
@ -125,6 +173,8 @@ void GLGizmoText::push_combo_style(const float scale) {
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_Button, { 1.00f, 1.00f, 1.00f, 0.0f });
}
}
@ -132,12 +182,21 @@ void GLGizmoText::push_combo_style(const float scale) {
void GLGizmoText::pop_combo_style()
{
ImGui::PopStyleVar(2);
ImGui::PopStyleColor(7);
ImGui::PopStyleColor(9);
}
// BBS
void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
{
if (m_imgui->get_font_size() != m_scale) {
m_scale = m_imgui->get_font_size();
update_font_texture();
}
if (m_textures.size() == 0) {
BOOST_LOG_TRIVIAL(info) << "GLGizmoText has no texture";
return;
}
const float win_h = ImGui::GetWindowHeight();
y = std::min(y, bottom_limit - win_h);
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
@ -178,35 +237,31 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
ImGui::AlignTextToFramePadding();
const char** cstr_font_names = (const char**)calloc(m_avail_font_names.size(), sizeof(const char*));
for (int i = 0; i < m_avail_font_names.size(); i++)
cstr_font_names[i] = m_avail_font_names[i].c_str();
m_imgui->text(_L("Font"));
ImGui::SameLine(caption_size);
ImGui::PushItemWidth(input_text_size + ImGui::GetFrameHeight() * 2);
push_combo_style(currt_scale);
int font_index = m_curr_font_idx;
m_imgui->push_font_by_name(cstr_font_names[font_index]);
if (ImGui::BBLBeginCombo("##Font", cstr_font_names[m_curr_font_idx], 0)) {
if (ImGui::BBLBeginCombo("##Font", m_textures[m_curr_font_idx].font_name.c_str(), 0)) {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4.0f, 0.0f) * currt_scale);
for (int i = 0; i < m_avail_font_names.size(); i++) {
m_imgui->push_font_by_name(m_avail_font_names[i]);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8, 4));
for (int i = 0; i < m_textures.size(); i++) {
const bool is_selected = (m_curr_font_idx == i);
if (ImGui::BBLSelectable((cstr_font_names[i] + std::string("##") + std::to_string(i)).c_str(), is_selected, 0, {input_text_size + ImGui::GetFrameHeight() * 2 , 0.0f})) {
ImTextureID icon_id = (ImTextureID)(intptr_t)(m_textures[i].texture->get_id());
ImVec4 tint_color = ImGui::GetStyleColorVec4(ImGuiCol_Text);
ImVec2 selectable_size(std::max((input_text_size + ImGui::GetFrameHeight() * 2), m_combo_width), m_combo_height);
if (ImGui::BBLImageSelectable(icon_id, selectable_size, { (float)m_textures[i].w, (float)m_textures[i].h }, m_textures[i].hl, tint_color, { 0, 0 }, {1, 1}, is_selected)) {
m_curr_font_idx = i;
m_font_name = cstr_font_names[m_curr_font_idx];
m_font_name = m_textures[m_curr_font_idx].font_name;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
m_imgui->pop_font_by_name(m_avail_font_names[i]);
}
ImGui::PopStyleVar(2);
ImGui::PopStyleVar(3);
ImGui::EndCombo();
}
m_imgui->pop_font_by_name(cstr_font_names[font_index]);
pop_combo_style();
ImGui::AlignTextToFramePadding();

View file

@ -3,7 +3,7 @@
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include "../GLTexture.hpp"
namespace Slic3r {
@ -22,9 +22,27 @@ private:
bool m_bold = true;
bool m_italic = false;
float m_thickness = 2.f;
float m_combo_height = 0.0f;
float m_combo_width = 0.0f;
float m_scale;
class TextureInfo {
public:
GLTexture* texture { nullptr };
int h;
int w;
int hl;
std::string font_name;
};
std::vector<TextureInfo> m_textures;
public:
GLGizmoText(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
~GLGizmoText();
void update_font_texture();
protected:
virtual bool on_init() override;