diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c7c18bb8a..253bb5bda 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3276,7 +3276,12 @@ bool GLCanvas3D::Gizmos::generate_icons_texture() const } } - bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, GLGizmoBase::Num_States, (unsigned int)(m_overlay_icons_size * m_overlay_scale)); + std::vector<std::pair<int, bool>> states; + states.push_back(std::make_pair(1, false)); + states.push_back(std::make_pair(0, false)); + states.push_back(std::make_pair(0, true)); + + bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, (unsigned int)(m_overlay_icons_size * m_overlay_scale)); if (res) m_icons_texture_dirty = false; @@ -3713,7 +3718,11 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) #endif , m_in_render(false) , m_bed(nullptr) +#if ENABLE_SVG_ICONS + , m_toolbar(GLToolbar::Normal, "Top") +#else , m_toolbar(GLToolbar::Normal) +#endif // ENABLE_SVG_ICONS , m_view_toolbar(nullptr) , m_use_clipping_planes(false) , m_sidebar_field("") @@ -5988,7 +5997,7 @@ bool GLCanvas3D::_init_toolbar() item.icon_filename = "split_parts.svg"; #endif // ENABLE_SVG_ICONS item.tooltip = GUI::L_str("Split to parts"); - item.sprite_id = 8; + item.sprite_id = 7; item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; if (!m_toolbar.add_item(item)) return false; @@ -6001,7 +6010,7 @@ bool GLCanvas3D::_init_toolbar() item.icon_filename = "layers.svg"; #endif // ENABLE_SVG_ICONS item.tooltip = GUI::L_str("Layers editing"); - item.sprite_id = 7; + item.sprite_id = 8; item.is_toggable = true; item.action_event = EVT_GLTOOLBAR_LAYERSEDITING; if (!m_toolbar.add_item(item)) diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 7e822a4c1..2f1b68048 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -138,19 +138,19 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps) #endif // ENABLE_TEXTURES_FROM_SVG #if ENABLE_SVG_ICONS -bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, unsigned int num_states, unsigned int sprite_size_px) +bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, const std::vector<std::pair<int, bool>>& states, unsigned int sprite_size_px) { - static int pass = 0; - ++pass; - reset(); - if (filenames.empty() || (num_states == 0) || (sprite_size_px == 0)) + if (filenames.empty() || states.empty() || (sprite_size_px == 0)) return false; - m_width = (int)(sprite_size_px * num_states); + m_width = (int)(sprite_size_px * states.size()); m_height = (int)(sprite_size_px * filenames.size()); int n_pixels = m_width * m_height; + int sprite_n_pixels = sprite_size_px * sprite_size_px; + int sprite_bytes = sprite_n_pixels * 4; + int sprite_stride = sprite_size_px * 4; if (n_pixels <= 0) { @@ -159,7 +159,10 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri } std::vector<unsigned char> data(n_pixels * 4, 0); - std::vector<unsigned char> sprite_data(sprite_size_px * sprite_size_px * 4, 0); + std::vector<unsigned char> sprite_data(sprite_bytes, 0); + std::vector<unsigned char> sprite_white_only_data(sprite_bytes, 0); + std::vector<unsigned char> sprite_gray_only_data(sprite_bytes, 0); + std::vector<unsigned char> output_data(sprite_bytes, 0); NSVGrasterizer* rast = nsvgCreateRasterizer(); if (rast == nullptr) @@ -185,16 +188,58 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri float scale = (float)sprite_size_px / std::max(image->width, image->height); - nsvgRasterize(rast, image, 0, 0, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_size_px * 4); + nsvgRasterize(rast, image, 0, 0, scale, sprite_data.data(), sprite_size_px, sprite_size_px, sprite_stride); + + // makes white only copy of the sprite + ::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes); + for (int i = 0; i < sprite_n_pixels; ++i) + { + if (sprite_white_only_data.data()[i * 4] != 0) + ::memset((void*)&sprite_white_only_data.data()[i * 4], 255, 3); + } + + // makes gray only copy of the sprite + ::memcpy((void*)sprite_gray_only_data.data(), (const void*)sprite_data.data(), sprite_bytes); + for (int i = 0; i < sprite_n_pixels; ++i) + { + if (sprite_gray_only_data.data()[i * 4] != 0) + ::memset((void*)&sprite_gray_only_data.data()[i * 4], 128, 3); + } int sprite_offset_px = sprite_id * sprite_size_px * m_width; - for (unsigned int i = 0; i < num_states; ++i) + int state_id = -1; + for (const std::pair<int, bool>& state : states) { - int state_offset_px = sprite_offset_px + i * sprite_size_px; + ++state_id; + + // select the sprite variant + std::vector<unsigned char>* src = nullptr; + switch (state.first) + { + case 1: { src = &sprite_white_only_data; break; } + case 2: { src = &sprite_gray_only_data; break; } + default: { src = &sprite_data; break; } + } + + ::memcpy((void*)output_data.data(), (const void*)src->data(), sprite_bytes); + // applies background, if needed + if (state.second) + { + for (int i = 0; i < sprite_n_pixels; ++i) + { + float alpha = (float)output_data.data()[i * 4 + 3] / 255.0f; + output_data.data()[i * 4 + 0] = (unsigned char)(0 * (1.0f - alpha) + output_data.data()[i * 4 + 0] * alpha); + output_data.data()[i * 4 + 1] = (unsigned char)(0 * (1.0f - alpha) + output_data.data()[i * 4 + 1] * alpha); + output_data.data()[i * 4 + 2] = (unsigned char)(0 * (1.0f - alpha) + output_data.data()[i * 4 + 2] * alpha); + output_data.data()[i * 4 + 3] = (unsigned char)(128 * (1.0f - alpha) + output_data.data()[i * 4 + 3] * alpha); + } + } + + int state_offset_px = sprite_offset_px + state_id * sprite_size_px; for (int j = 0; j < sprite_size_px; ++j) { int data_offset = (state_offset_px + j * m_width) * 4; - ::memcpy((void*)&data.data()[data_offset], (const void*)&sprite_data.data()[j * sprite_size_px * 4], sprite_size_px * 4); + ::memcpy((void*)&data.data()[data_offset], (const void*)&output_data.data()[j * sprite_stride], sprite_stride); } } @@ -216,6 +261,11 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri m_source = filenames.front(); + +#if 0 + // debug output + static int pass = 0; + ++pass; wxImage output(m_width, m_height); output.InitAlpha(); @@ -232,6 +282,7 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri } output.SaveFile("C:/prusa/slic3r/svg_icons/temp/test_" + std::to_string(pass) + ".png", wxBITMAP_TYPE_PNG); +#endif // 0 return true; } diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 55e5c4c07..9b1f04ea6 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -42,7 +42,15 @@ namespace GUI { bool load_from_svg_file(const std::string& filename, bool use_mipmaps, unsigned int max_size_px); #endif // ENABLE_TEXTURES_FROM_SVG #if ENABLE_SVG_ICONS - bool load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, unsigned int num_states, unsigned int sprite_size_px); + // meanings of states: (std::pair<int, bool>) + // first field (int): + // 0 -> no changes + // 1 -> use white only color variant + // 2 -> use gray only color variant + // second field (bool): + // false -> no changes + // true -> add background color + bool load_from_svg_files_as_sprites_array(const std::vector<std::string>& filenames, const std::vector<std::pair<int, bool>>& states, unsigned int sprite_size_px); #endif // ENABLE_SVG_ICONS void reset(); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 5f5350299..144662c3f 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -124,8 +124,15 @@ GLToolbar::Layout::Layout() { } +#if ENABLE_SVG_ICONS +GLToolbar::GLToolbar(GLToolbar::EType type, const std::string& name) +#else GLToolbar::GLToolbar(GLToolbar::EType type) +#endif // ENABLE_SVG_ICONS : m_type(type) +#if ENABLE_SVG_ICONS + , m_name(name) +#endif // ENABLE_SVG_ICONS , m_enabled(false) #if ENABLE_SVG_ICONS , m_icons_texture_dirty(true) @@ -1231,7 +1238,25 @@ bool GLToolbar::generate_icons_texture() const filenames.push_back(path + icon_filename); } - bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, GLToolbarItem::Num_States, (unsigned int)(m_layout.icons_size * m_layout.scale)); + std::vector<std::pair<int, bool>> states; + if (m_name == "Top") + { + states.push_back(std::make_pair(1, false)); + states.push_back(std::make_pair(0, false)); + states.push_back(std::make_pair(2, false)); + states.push_back(std::make_pair(0, false)); + states.push_back(std::make_pair(0, false)); + } + else if (m_name == "View") + { + states.push_back(std::make_pair(1, false)); + states.push_back(std::make_pair(1, true)); + states.push_back(std::make_pair(1, false)); + states.push_back(std::make_pair(0, false)); + states.push_back(std::make_pair(1, true)); + } + + bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, (unsigned int)(m_layout.icons_size * m_layout.scale)); if (res) m_icons_texture_dirty = false; diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 30a9ff04d..e14f7b3bb 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -203,6 +203,9 @@ private: typedef std::vector<GLToolbarItem*> ItemsList; EType m_type; +#if ENABLE_SVG_ICONS + std::string m_name; +#endif // ENABLE_SVG_ICONS bool m_enabled; #if ENABLE_SVG_ICONS mutable GLTexture m_icons_texture; @@ -216,7 +219,11 @@ private: ItemsList m_items; public: +#if ENABLE_SVG_ICONS + GLToolbar(EType type, const std::string& name); +#else explicit GLToolbar(EType type); +#endif // ENABLE_SVG_ICONS ~GLToolbar(); #if ENABLE_SVG_ICONS diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6c2c3a1ea..24d366ced 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1178,7 +1178,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , sidebar(new Sidebar(q)) , delayed_scene_refresh(false) , project_filename(wxEmptyString) +#if ENABLE_SVG_ICONS + , view_toolbar(GLToolbar::Radio, "View") +#else , view_toolbar(GLToolbar::Radio) +#endif // ENABLE_SVG_ICONS { arranging.store(false); rotoptimizing.store(false);