Separate icon manager. Create well public interface for future work and improve
This commit is contained in:
parent
870561469f
commit
9d88830365
@ -97,6 +97,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/GUI_Geometry.hpp
|
||||
GUI/I18N.cpp
|
||||
GUI/I18N.hpp
|
||||
GUI/IconManager.cpp
|
||||
GUI/IconManager.hpp
|
||||
GUI/MainFrame.cpp
|
||||
GUI/MainFrame.hpp
|
||||
GUI/Plater.cpp
|
||||
|
@ -3795,23 +3795,9 @@ void GLGizmoEmboss::init_icons()
|
||||
std::string path = resources_dir() + "/icons/";
|
||||
for (std::string &filename : filenames) filename = path + filename;
|
||||
|
||||
// state order has to match the enum IconState
|
||||
std::vector<std::pair<int, bool>> states;
|
||||
states.push_back(std::make_pair(1, false)); // Activable
|
||||
states.push_back(std::make_pair(0, false)); // Hovered
|
||||
states.push_back(std::make_pair(2, false)); // Disabled
|
||||
|
||||
bool compress = false;
|
||||
bool is_loaded = m_icons_texture.load_from_svg_files_as_sprites_array(
|
||||
filenames, states, m_gui_cfg->icon_width, compress);
|
||||
|
||||
if (!is_loaded ||
|
||||
(size_t)m_icons_texture.get_width() < (states.size() * m_gui_cfg->icon_width) ||
|
||||
(size_t)m_icons_texture.get_height() < (filenames.size() * m_gui_cfg->icon_width)) {
|
||||
// bad load of icons, but all usage of m_icons_texture check that texture is initialized
|
||||
assert(false);
|
||||
m_icons_texture.reset();
|
||||
}
|
||||
ImVec2 size(m_gui_cfg->icon_width, m_gui_cfg->icon_width);
|
||||
auto type = IconManager::RasterType::color_wite_gray;
|
||||
m_icons = m_icon_manager.init(filenames, size, type);
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_icon(IconType icon, IconState state, ImVec2 size)
|
||||
@ -3820,48 +3806,32 @@ void GLGizmoEmboss::draw_icon(IconType icon, IconState state, ImVec2 size)
|
||||
assert(icon != IconType::_count);
|
||||
if (icon == IconType::_count) return;
|
||||
|
||||
unsigned int icons_texture_id = m_icons_texture.get_id();
|
||||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
// is icon loaded
|
||||
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1)){
|
||||
ImGui::Text("▮");
|
||||
return;
|
||||
}
|
||||
|
||||
int icon_width = m_gui_cfg->icon_width;
|
||||
ImTextureID tex_id = (void *) (intptr_t) (GLuint) icons_texture_id;
|
||||
int start_x = static_cast<unsigned>(state) * (icon_width + 1) + 1,
|
||||
start_y = static_cast<unsigned>(icon) * (icon_width + 1) + 1;
|
||||
|
||||
ImVec2 uv0(start_x / (float) tex_width,
|
||||
start_y / (float) tex_height);
|
||||
ImVec2 uv1((start_x + icon_width) / (float) tex_width,
|
||||
(start_y + icon_width) / (float) tex_height);
|
||||
|
||||
if (size.x < 1 || size.y < 1)
|
||||
size = ImVec2(m_gui_cfg->icon_width, m_gui_cfg->icon_width);
|
||||
|
||||
ImGui::Image(tex_id, size, uv0, uv1);
|
||||
const auto &i = *m_icons[static_cast<int>(icon)][static_cast<int>(state)];
|
||||
IconManager::draw(i);
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_transparent_icon()
|
||||
{
|
||||
unsigned int icons_texture_id = m_icons_texture.get_id();
|
||||
int tex_width = m_icons_texture.get_width();
|
||||
int tex_height = m_icons_texture.get_height();
|
||||
// is icon loaded
|
||||
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1)) {
|
||||
// use top left corner of first icon
|
||||
IconManager::Icon icon = *m_icons.front().front(); // copy
|
||||
|
||||
if (!icon.is_valid()) {
|
||||
ImGui::Text("▯");
|
||||
return;
|
||||
}
|
||||
|
||||
ImTextureID tex_id = (void *) (intptr_t) (GLuint) icons_texture_id;
|
||||
int icon_width = m_gui_cfg->icon_width;
|
||||
ImVec2 icon_size(icon_width, icon_width);
|
||||
ImVec2 pixel_size(1.f / tex_width, 1.f / tex_height);
|
||||
// zero pixel is transparent in texture
|
||||
ImGui::Image(tex_id, icon_size, ImVec2(0, 0), pixel_size);
|
||||
// size UV texture coors [in texture ratio]
|
||||
ImVec2 size_uv(
|
||||
icon.br.x-icon.tl.x,
|
||||
icon.br.y-icon.tl.y);
|
||||
ImVec2 one_px(
|
||||
size_uv.x/icon.size.x,
|
||||
size_uv.y/icon.size.y);
|
||||
// reduce uv coors to one pixel
|
||||
icon.br = ImVec2(
|
||||
icon.tl.x + one_px.x,
|
||||
icon.tl.y + one_px.y);
|
||||
IconManager::draw(icon);
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::draw_clickable(
|
||||
|
@ -5,15 +5,12 @@
|
||||
// which overrides our localization "L" macro.
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "GLGizmoRotate.hpp"
|
||||
#include "slic3r/GUI/GLTexture.hpp"
|
||||
#include "slic3r/GUI/IconManager.hpp"
|
||||
#include "slic3r/Utils/RaycastManager.hpp"
|
||||
#include "slic3r/Utils/EmbossStyleManager.hpp"
|
||||
|
||||
#include "admesh/stl.h" // indexed_triangle_set
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
#include "libslic3r/Emboss.hpp"
|
||||
@ -33,7 +30,6 @@ namespace Slic3r{
|
||||
}
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
class MeshRaycaster;
|
||||
class GLGizmoEmboss : public GLGizmoBase
|
||||
{
|
||||
public:
|
||||
@ -346,7 +342,9 @@ private:
|
||||
void calculate_scale();
|
||||
|
||||
// drawing icons
|
||||
GLTexture m_icons_texture;
|
||||
IconManager m_icon_manager;
|
||||
std::vector<IconManager::Icons> m_icons;
|
||||
|
||||
void init_icons();
|
||||
enum class IconType : unsigned {
|
||||
rename = 0,
|
||||
|
150
src/slic3r/GUI/IconManager.cpp
Normal file
150
src/slic3r/GUI/IconManager.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "IconManager.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
namespace priv {
|
||||
// set shared pointer to point on bad texture
|
||||
static void clear(IconManager::Icons &icons);
|
||||
static const std::vector<std::pair<int, bool>>& get_states(IconManager::RasterType type);
|
||||
}
|
||||
|
||||
IconManager::~IconManager() {
|
||||
priv::clear(m_icons);
|
||||
// release opengl texture is made in ~GLTexture()
|
||||
}
|
||||
|
||||
std::vector<IconManager::Icons> IconManager::init(const InitTypes &input)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Not implemented yet";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<IconManager::Icons> IconManager::init(const std::vector<std::string> &file_paths, const ImVec2 &size, RasterType type)
|
||||
{
|
||||
// TODO: remove in future
|
||||
if (!m_icons.empty()) {
|
||||
// not first initialization
|
||||
priv::clear(m_icons);
|
||||
m_icons.clear();
|
||||
m_icons_texture.reset();
|
||||
}
|
||||
|
||||
// only rectangle are supported
|
||||
assert(size.x == size.y);
|
||||
// no subpixel supported
|
||||
unsigned int width = static_cast<unsigned int>(std::fabs(std::round(size.x)));
|
||||
assert(size.x == static_cast<float>(width));
|
||||
|
||||
// state order has to match the enum IconState
|
||||
const auto& states = priv::get_states(type);
|
||||
|
||||
bool compress = false;
|
||||
bool is_loaded = m_icons_texture.load_from_svg_files_as_sprites_array(file_paths, states, width, compress);
|
||||
if (!is_loaded || (size_t) m_icons_texture.get_width() < (states.size() * width) ||
|
||||
(size_t) m_icons_texture.get_height() < (file_paths.size() * width)) {
|
||||
// bad load of icons, but all usage of m_icons_texture check that texture is initialized
|
||||
assert(false);
|
||||
m_icons_texture.reset();
|
||||
return {};
|
||||
}
|
||||
|
||||
unsigned count_files = file_paths.size();
|
||||
// count icons per file
|
||||
unsigned count = states.size();
|
||||
// create result
|
||||
std::vector<Icons> result;
|
||||
result.reserve(count_files);
|
||||
|
||||
Icon def_icon;
|
||||
def_icon.tex_id = m_icons_texture.get_id();
|
||||
def_icon.size = size;
|
||||
|
||||
// float beacouse of dividing
|
||||
float tex_height = static_cast<float>(m_icons_texture.get_height());
|
||||
float tex_width = static_cast<float>(m_icons_texture.get_width());
|
||||
|
||||
//for (const auto &f: file_paths) {
|
||||
for (unsigned f = 0; f < count_files; ++f) {
|
||||
// NOTE: there are space between icons
|
||||
unsigned start_y = static_cast<unsigned>(f) * (width + 1) + 1;
|
||||
float y1 = start_y / tex_height;
|
||||
float y2 = (start_y + width) / tex_height;
|
||||
Icons file_icons;
|
||||
file_icons.reserve(count);
|
||||
//for (const auto &s : states) {
|
||||
for (unsigned j = 0; j < count; ++j) {
|
||||
auto icon = std::make_shared<Icon>(def_icon);
|
||||
// NOTE: there are space between icons
|
||||
unsigned start_x = static_cast<unsigned>(j) * (width + 1) + 1;
|
||||
float x1 = start_x / tex_width;
|
||||
float x2 = (start_x + width) / tex_width;
|
||||
icon->tl = ImVec2(x1, y1);
|
||||
icon->br = ImVec2(x2, y2);
|
||||
file_icons.push_back(icon);
|
||||
m_icons.push_back(std::move(icon));
|
||||
}
|
||||
result.emplace_back(std::move(file_icons));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void IconManager::release() {
|
||||
BOOST_LOG_TRIVIAL(error) << "Not implemented yet";
|
||||
}
|
||||
|
||||
void IconManager::draw(const Icon &icon, const ImVec2 &size, const ImVec4 &tint_col, const ImVec4 &border_col)
|
||||
{
|
||||
// is icon loaded
|
||||
if (!icon.is_valid()) {
|
||||
ImGui::Text("?");
|
||||
return;
|
||||
}
|
||||
|
||||
ImTextureID id = (void *) icon.tex_id;
|
||||
const ImVec2 &s = (size.x < 1 || size.y < 1) ? icon.size : size;
|
||||
ImGui::Image(id, s, icon.tl, icon.br, tint_col, border_col);
|
||||
}
|
||||
|
||||
void priv::clear(IconManager::Icons &icons) {
|
||||
std::string message;
|
||||
for (auto &icon : icons) {
|
||||
// Exist more than this instance of shared ptr?
|
||||
long count = icon.use_count();
|
||||
if (count != 1) {
|
||||
// in existing icon change texture to non existing one
|
||||
icon->tex_id = 0;
|
||||
|
||||
std::string descr =
|
||||
((count > 2) ? (std::to_string(count - 1) + "x") : "") + // count
|
||||
std::to_string(icon->size.x) + "x" + std::to_string(icon->size.y); // resolution
|
||||
if (message.empty())
|
||||
message = descr;
|
||||
else
|
||||
message += ", " + descr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!message.empty())
|
||||
BOOST_LOG_TRIVIAL(warning) << "There is still used icons(" << message << ").";
|
||||
}
|
||||
|
||||
const std::vector<std::pair<int, bool>> &priv::get_states(IconManager::RasterType type) {
|
||||
static std::vector<std::pair<int, bool>> color = {std::make_pair(0, false)};
|
||||
static std::vector<std::pair<int, bool>> white = {std::make_pair(1, false)};
|
||||
static std::vector<std::pair<int, bool>> gray = {std::make_pair(2, false)};
|
||||
static std::vector<std::pair<int, bool>> color_wite_gray = {
|
||||
std::make_pair(1, false), // Activable
|
||||
std::make_pair(0, false), // Hovered
|
||||
std::make_pair(2, false) // Disabled
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case IconManager::RasterType::color: return color;
|
||||
case IconManager::RasterType::white_only_data: return white;
|
||||
case IconManager::RasterType::gray_only_data: return gray;
|
||||
case IconManager::RasterType::color_wite_gray: return color_wite_gray;
|
||||
default: return color;
|
||||
}
|
||||
}
|
110
src/slic3r/GUI/IconManager.hpp
Normal file
110
src/slic3r/GUI/IconManager.hpp
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef slic3r_IconManager_hpp_
|
||||
#define slic3r_IconManager_hpp_
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "imgui/imgui.h" // ImVec2
|
||||
#include "slic3r/GUI/GLTexture.hpp" // texture storage
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
/// <summary>
|
||||
/// Keep texture with icons for UI
|
||||
/// Manage texture live -> create and destruct texture
|
||||
/// by live of icon shared pointers.
|
||||
/// </summary>
|
||||
class IconManager
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Release texture
|
||||
/// Set shared pointers to invalid texture
|
||||
/// </summary>
|
||||
~IconManager();
|
||||
|
||||
/// <summary>
|
||||
/// Define way to convert svg data to raster
|
||||
/// </summary>
|
||||
enum class RasterType: int{
|
||||
color = 1 << 1,
|
||||
white_only_data = 1 << 2,
|
||||
gray_only_data = 1 << 3,
|
||||
color_wite_gray = color | white_only_data | gray_only_data
|
||||
// TODO: add type with backgrounds
|
||||
};
|
||||
|
||||
struct InitType {
|
||||
// path to file with image .. svg
|
||||
std::string filepath;
|
||||
|
||||
// resolution of stored rasterized icon
|
||||
ImVec2 size; // float will be rounded
|
||||
|
||||
// could contain more than one type
|
||||
RasterType type = RasterType::color;
|
||||
// together color, white and gray = color | white_only_data | gray_only_data
|
||||
};
|
||||
using InitTypes = std::vector<InitType>;
|
||||
|
||||
/// <summary>
|
||||
/// Data for render texture with icon
|
||||
/// </summary>
|
||||
struct Icon {
|
||||
// stored texture size
|
||||
ImVec2 size = ImVec2(-1, -1); // [in px] --> unsigned int values stored as float
|
||||
|
||||
// SubTexture UV coordinate in range from 0. to 1.
|
||||
ImVec2 tl; // top left -> uv0
|
||||
ImVec2 br; // bottom right -> uv1
|
||||
|
||||
// OpenGL texture id
|
||||
unsigned int tex_id = 0;
|
||||
bool is_valid() const { return tex_id != 0;}
|
||||
// && size.x > 0 && size.y > 0 && tl.x != br.x && tl.y != br.y;
|
||||
};
|
||||
using Icons = std::vector<std::shared_ptr<Icon> >;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize raster texture on GPU with given images
|
||||
/// NOTE: Have to be called after OpenGL initialization
|
||||
/// </summary>
|
||||
/// <param name="input">Define files and its </param>
|
||||
/// <returns>Rasterized icons stored on GPU,
|
||||
/// Same size and order as input, each item of vector is set of texture in order by RasterType</returns>
|
||||
std::vector<Icons> init(const InitTypes &input);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize multiple icons with same settings for size and type
|
||||
/// NOTE: Have to be called after OpenGL initialization
|
||||
/// </summary>
|
||||
/// <param name="file_paths">Define files with icon</param>
|
||||
/// <param name="size">Size of stored texture[in px], float will be rounded</param>
|
||||
/// <param name="type">Define way to rasterize icon,
|
||||
/// together color, white and gray = RasterType::color | RasterType::white_only_data | RasterType::gray_only_data</param>
|
||||
/// <returns>Rasterized icons stored on GPU,
|
||||
/// Same size and order as file_paths, each item of vector is set of texture in order by RasterType</returns>
|
||||
std::vector<Icons> init(const std::vector<std::string> &file_paths, const ImVec2 &size, RasterType type = RasterType::color);
|
||||
|
||||
/// <summary>
|
||||
/// Release icons which are hold only by this manager
|
||||
/// May change texture and position of icons.
|
||||
/// </summary>
|
||||
void release();
|
||||
|
||||
/// <summary>
|
||||
/// Draw imgui image with icon
|
||||
/// </summary>
|
||||
/// <param name="icon">Place in texture</param>
|
||||
/// <param name="size">[optional]Size of image, wen zero than use same size as stored texture</param>
|
||||
/// <param name="tint_col">viz ImGui::Image </param>
|
||||
/// <param name="border_col">viz ImGui::Image </param>
|
||||
static void draw(const Icon &icon, const ImVec2 &size = ImVec2(0, 0), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
|
||||
|
||||
private:
|
||||
// keep data stored on GPU
|
||||
GLTexture m_icons_texture;
|
||||
Icons m_icons;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
#endif // slic3r_IconManager_hpp_
|
Loading…
Reference in New Issue
Block a user