Compare commits

..
Author SHA1 Message Date
ExPikaPaka 991d421756 Stop reading a missing AMF metadata type as a string
A <metadata> element without a type attribute makes get_attribute() return
nullptr, which is then assigned to a std::string and read as a C string.

Check it the way the sibling metadata handler already does and stop the parse.
2026-10-01 08:50:05 +02:00
11 changed files with 37 additions and 120 deletions
+6 -1
View File
@@ -311,9 +311,14 @@ void AMFParserContext::startElement(const char *name, const char **atts)
case 2: case 2:
if (strcmp(name, "metadata") == 0) { if (strcmp(name, "metadata") == 0) {
if (m_path[1] == NODE_TYPE_MATERIAL || m_path[1] == NODE_TYPE_OBJECT) { if (m_path[1] == NODE_TYPE_MATERIAL || m_path[1] == NODE_TYPE_OBJECT) {
m_value[0] = get_attribute(atts, "type"); const char *type = get_attribute(atts, "type");
if (type == nullptr)
this->stop();
else {
m_value[0] = type;
node_type_new = NODE_TYPE_METADATA; node_type_new = NODE_TYPE_METADATA;
} }
}
}/* else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT) }/* else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
node_type_new = NODE_TYPE_LAYER_CONFIG;*/ node_type_new = NODE_TYPE_LAYER_CONFIG;*/
else if (strcmp(name, "mesh") == 0) { else if (strcmp(name, "mesh") == 0) {
-2
View File
@@ -55,8 +55,6 @@ public:
static bool parse_color(const std::string& scolor, unsigned char* rgb_out); static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
static bool parse_color4(const std::string& scolor, unsigned char* rgba_out); static bool parse_color4(const std::string& scolor, unsigned char* rgba_out);
// Rasterizes the SVG into a freshly generated GL texture; the caller owns it and has to delete
// it (ImGuiWrapper::svg_texture() caches the result for the whole session).
static bool load_from_svg_file_change_color(const std::string &filename, unsigned width, unsigned height, ImTextureID &texture_id, const char *hexColor); static bool load_from_svg_file_change_color(const std::string &filename, unsigned width, unsigned height, ImTextureID &texture_id, const char *hexColor);
+11 -28
View File
@@ -3245,8 +3245,7 @@ void GLCanvas3D::load_sla_preview()
void GLCanvas3D::bind_event_handlers() void GLCanvas3D::bind_event_handlers()
{ {
// Every view switch binds, so binding twice would run each handler twice per event. if (m_canvas != nullptr) {
if (m_canvas != nullptr && !m_event_handlers_bound) {
m_canvas->Bind(wxEVT_SIZE, &GLCanvas3D::on_size, this); m_canvas->Bind(wxEVT_SIZE, &GLCanvas3D::on_size, this);
m_canvas->Bind(wxEVT_IDLE, &GLCanvas3D::on_idle, this); m_canvas->Bind(wxEVT_IDLE, &GLCanvas3D::on_idle, this);
m_canvas->Bind(wxEVT_CHAR, &GLCanvas3D::on_char, this); m_canvas->Bind(wxEVT_CHAR, &GLCanvas3D::on_char, this);
@@ -3256,9 +3255,9 @@ void GLCanvas3D::bind_event_handlers()
m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this); m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
m_canvas->Bind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this); m_canvas->Bind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this);
m_toolbar_highlighter.set_timer_owner(m_canvas, 0); m_toolbar_highlighter.set_timer_owner(m_canvas, 0);
m_canvas->Bind(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, &GLCanvas3D::on_toolbar_highlighter_timer, this); m_canvas->Bind(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_toolbar_highlighter.blink(); });
m_gizmo_highlighter.set_timer_owner(m_canvas, 0); m_gizmo_highlighter.set_timer_owner(m_canvas, 0);
m_canvas->Bind(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, &GLCanvas3D::on_gizmo_highlighter_timer, this); m_canvas->Bind(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_gizmo_highlighter.blink(); });
m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this);
@@ -3273,7 +3272,14 @@ void GLCanvas3D::bind_event_handlers()
m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this); m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this); m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
m_canvas->Bind(wxEVT_KILL_FOCUS, &GLCanvas3D::on_kill_focus, this); m_canvas->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& evt) {
// The key-up that would commit a keyboard edit goes to whatever took the focus.
if (m_selection_edit.kind != SelectionEdit::None)
finish_selection_edit();
ImGui::SetWindowFocus(nullptr);
render();
evt.Skip();
});
m_event_handlers_bound = true; m_event_handlers_bound = true;
m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this); m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
@@ -3311,9 +3317,6 @@ void GLCanvas3D::unbind_event_handlers()
m_canvas->Unbind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this); m_canvas->Unbind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
m_canvas->Unbind(wxEVT_PAINT, &GLCanvas3D::on_paint, this); m_canvas->Unbind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
m_canvas->Unbind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this); m_canvas->Unbind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
m_canvas->Unbind(wxEVT_KILL_FOCUS, &GLCanvas3D::on_kill_focus, this);
m_canvas->Unbind(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, &GLCanvas3D::on_toolbar_highlighter_timer, this);
m_canvas->Unbind(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, &GLCanvas3D::on_gizmo_highlighter_timer, this);
m_event_handlers_bound = false; m_event_handlers_bound = false;
m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this); m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
@@ -4890,26 +4893,6 @@ void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style"); m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style");
} }
void GLCanvas3D::on_kill_focus(wxFocusEvent& evt)
{
// The key-up that would commit a keyboard edit goes to whatever took the focus.
if (m_selection_edit.kind != SelectionEdit::None)
finish_selection_edit();
ImGui::SetWindowFocus(nullptr);
render();
evt.Skip();
}
void GLCanvas3D::on_toolbar_highlighter_timer(wxTimerEvent& evt)
{
m_toolbar_highlighter.blink();
}
void GLCanvas3D::on_gizmo_highlighter_timer(wxTimerEvent& evt)
{
m_gizmo_highlighter.blink();
}
bool GLCanvas3D::clicked_button_matches_action(const wxMouseEvent& evt, const MouseAction action, const std::map<MouseButton, MouseAction>& mappings) const bool GLCanvas3D::clicked_button_matches_action(const wxMouseEvent& evt, const MouseAction action, const std::map<MouseButton, MouseAction>& mappings) const
{ {
MouseButton clicked = MouseButton::None; MouseButton clicked = MouseButton::None;
-3
View File
@@ -1133,9 +1133,6 @@ public:
void on_gesture(wxGestureEvent& evt); void on_gesture(wxGestureEvent& evt);
void on_paint(wxPaintEvent& evt); void on_paint(wxPaintEvent& evt);
void on_set_focus(wxFocusEvent& evt); void on_set_focus(wxFocusEvent& evt);
void on_kill_focus(wxFocusEvent& evt);
void on_toolbar_highlighter_timer(wxTimerEvent& evt);
void on_gizmo_highlighter_timer(wxTimerEvent& evt);
void force_set_focus(); void force_set_focus();
enum class MouseButton { None, Left, Middle, Right }; enum class MouseButton { None, Left, Middle, Right };
+6 -12
View File
@@ -2057,15 +2057,9 @@ wxMenu* MenuFactory::instance_menu()
return &m_instance_menu; return &m_instance_menu;
} }
MenuWithSeparators* MenuFactory::new_transient_menu()
{
m_transient_menu = std::make_unique<MenuWithSeparators>();
return m_transient_menu.get();
}
wxMenu* MenuFactory::layer_menu() wxMenu* MenuFactory::layer_menu()
{ {
MenuWithSeparators* menu = new_transient_menu(); MenuWithSeparators* menu = new MenuWithSeparators();
append_menu_item_settings(menu); append_menu_item_settings(menu);
return menu; return menu;
@@ -2091,13 +2085,13 @@ wxMenu* MenuFactory::multi_selection_menu()
} }
if (all_plates) { if (all_plates) {
wxMenu* menu = new_transient_menu(); wxMenu* menu = new MenuWithSeparators();
append_menu_item_replace_all_with_stl(menu); append_menu_item_replace_all_with_stl(menu);
return menu; return menu;
} }
if (undefined_type) if (undefined_type)
return nullptr; return nullptr;
wxMenu* menu = new_transient_menu(); wxMenu* menu = new MenuWithSeparators();
if (!multi_volume) { if (!multi_volume) {
int index = 0; int index = 0;
if (obj_list()->can_merge_to_multipart_object()) { if (obj_list()->can_merge_to_multipart_object()) {
@@ -2171,7 +2165,7 @@ wxMenu* MenuFactory::assemble_multi_selection_menu()
// show this menu only for Objects(Instances mixed with Objects)/Volumes selection // show this menu only for Objects(Instances mixed with Objects)/Volumes selection
return nullptr; return nullptr;
wxMenu* menu = new_transient_menu(); wxMenu* menu = new MenuWithSeparators();
append_menu_item_set_visible(menu); append_menu_item_set_visible(menu);
//append_menu_item_fix_through_cgal(menu); //append_menu_item_fix_through_cgal(menu);
//append_menu_item_simplify(menu); //append_menu_item_simplify(menu);
@@ -2217,7 +2211,7 @@ wxMenu* MenuFactory::plate_menu()
wxMenu* MenuFactory::assemble_object_menu() wxMenu* MenuFactory::assemble_object_menu()
{ {
wxMenu* menu = new_transient_menu(); wxMenu* menu = new MenuWithSeparators();
// Set Visible // Set Visible
append_menu_item_set_visible(menu); append_menu_item_set_visible(menu);
// Delete // Delete
@@ -2237,7 +2231,7 @@ wxMenu* MenuFactory::assemble_object_menu()
wxMenu* MenuFactory::assemble_part_menu() wxMenu* MenuFactory::assemble_part_menu()
{ {
wxMenu* menu = new_transient_menu(); wxMenu* menu = new MenuWithSeparators();
append_menu_item_set_visible(menu); append_menu_item_set_visible(menu);
append_menu_item_delete(menu); append_menu_item_delete(menu);
-10
View File
@@ -2,7 +2,6 @@
#define slic3r_GUI_Factories_hpp_ #define slic3r_GUI_Factories_hpp_
#include <map> #include <map>
#include <memory>
#include <vector> #include <vector>
#include <array> #include <array>
#include <cstddef> #include <cstddef>
@@ -122,21 +121,12 @@ private:
wxMenu m_filament_action_menu; wxMenu m_filament_action_menu;
// The selection dependent menus are rebuilt for every popup, so they cannot be members that
// outlive a build like the ones above; this owns the current one and destroys the previous.
// One slot is enough because PopupMenu() is synchronous: the menu a caller was handed is gone
// from the screen before anything can ask for the next one.
std::unique_ptr<MenuWithSeparators> m_transient_menu;
// Removed/Prepended Items according to the view mode // Removed/Prepended Items according to the view mode
std::array<wxMenuItem*, mtCount> items_increase; std::array<wxMenuItem*, mtCount> items_increase;
std::array<wxMenuItem*, mtCount> items_decrease; std::array<wxMenuItem*, mtCount> items_decrease;
std::array<wxMenuItem*, mtCount> items_set_number_of_copies; std::array<wxMenuItem*, mtCount> items_set_number_of_copies;
// Replaces m_transient_menu with an empty menu and returns it.
MenuWithSeparators* new_transient_menu();
void create_default_menu(); void create_default_menu();
void create_common_object_menu(wxMenu *menu); void create_common_object_menu(wxMenu *menu);
void create_object_menu(); void create_object_menu();
-4
View File
@@ -2272,10 +2272,6 @@ void GLGizmoMeasure::update_measurement_result()
void GLGizmoMeasure::reset_all_pick() void GLGizmoMeasure::reset_all_pick()
{ {
std::map<GLVolume*, std::shared_ptr<PickRaycaster>>().swap(m_mesh_raycaster_map); std::map<GLVolume*, std::shared_ptr<PickRaycaster>>().swap(m_mesh_raycaster_map);
// register_single_mesh_pick() fills both maps in lockstep, so the measurings have to go with
// the raycasters; otherwise the entries keyed on the GLVolumes of the previous selection stay
// behind for the rest of the session.
std::map<GLVolume*, std::shared_ptr<Measure::Measuring>>().swap(m_mesh_measure_map);
reset_gripper_pick(GripperType::UNDEFINE,true); reset_gripper_pick(GripperType::UNDEFINE,true);
} }
+3 -4
View File
@@ -27,7 +27,8 @@ enum class PainterGizmoType {
FDM_SUPPORTS, FDM_SUPPORTS,
SEAM, SEAM,
MM_SEGMENTATION, MM_SEGMENTATION,
FUZZY_SKIN FUZZY_SKIN,
TEXTURE_DISPLACEMENT
}; };
class TriangleSelectorGUI : public TriangleSelector { class TriangleSelectorGUI : public TriangleSelector {
@@ -101,9 +102,7 @@ class TriangleSelectorPatch : public TriangleSelectorGUI {
public: public:
explicit TriangleSelectorPatch(const TriangleMesh& mesh, const std::vector<ColorRGBA> ebt_colors, float edge_limit = 0.6f) explicit TriangleSelectorPatch(const TriangleMesh& mesh, const std::vector<ColorRGBA> ebt_colors, float edge_limit = 0.6f)
: TriangleSelectorGUI(mesh, edge_limit), m_ebt_colors(ebt_colors) {} : TriangleSelectorGUI(mesh, edge_limit), m_ebt_colors(ebt_colors) {}
// Releases the VAO and the per-patch VBOs built by finalize_triangle_indices(). The base class virtual ~TriangleSelectorPatch() = default;
// already deletes GL buffers from its GLModel members here, so this needs no context of its own.
virtual ~TriangleSelectorPatch() { release_geometry(); }
// Render current selection. Transformation matrices are supposed // Render current selection. Transformation matrices are supposed
// to be already set. // to be already set.
+9 -45
View File
@@ -361,7 +361,6 @@ ImGuiWrapper::~ImGuiWrapper()
{ {
//destroy_fonts_texture(); //destroy_fonts_texture();
destroy_font(); destroy_font();
destroy_svg_textures();
ImGui::DestroyContext(); ImGui::DestroyContext();
} }
@@ -543,12 +542,6 @@ bool ImGuiWrapper::update_key_data(wxKeyEvent &evt)
return ret; return ret;
} }
// SVG icons rasterized into GL textures, keyed on file name, size and recolor. Cleared as a whole
// from new_frame() once it grows past MAX_SVG_TEXTURES, which is safe there: the previous frame has
// been rendered and the frame about to be recorded asks for every icon it draws again.
static std::map<std::string, ImTextureID> s_svg_textures;
static const size_t MAX_SVG_TEXTURES = 256;
void ImGuiWrapper::new_frame() void ImGuiWrapper::new_frame()
{ {
if (m_new_frame_open) { if (m_new_frame_open) {
@@ -559,11 +552,6 @@ void ImGuiWrapper::new_frame()
init_font(true); init_font(true);
} }
// Recolored icons accumulate one texture per color the session has shown; drop them before
// anything references them again. This frame recreates the handful it actually draws.
if (s_svg_textures.size() > MAX_SVG_TEXTURES)
destroy_svg_textures();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui::NewFrame(); ImGui::NewFrame();
@@ -1816,7 +1804,8 @@ bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_si
if (icon_color != 0) if (icon_color != 0)
ImGui::RenderFrame(icon_pos, icon_pos + icon_size, icon_color); ImGui::RenderFrame(icon_pos, icon_pos + icon_size, icon_color);
else { else {
ImTextureID transparent = ImGuiWrapper::svg_texture(Slic3r::resources_dir() + "/images/transparent.svg", icon_size.x, icon_size.y); static ImTextureID transparent;
IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/transparent.svg", icon_size.x, icon_size.y, transparent);
window->DrawList->AddImage(transparent, icon_pos, icon_pos + icon_size, { 0,0 }, { 1,1 }, ImGui::GetColorU32(ImVec4(1.f, 1.f, 1.f, 1.f))); window->DrawList->AddImage(transparent, icon_pos, icon_pos + icon_size, { 0,0 }, { 1,1 }, ImGui::GetColorU32(ImVec4(1.f, 1.f, 1.f, 1.f)));
} }
} }
@@ -2642,7 +2631,11 @@ void ImGuiWrapper::push_toolbar_style(const float scale)
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 10 ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.00f)); // 10
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f)); // 11 ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 0.00f)); // 11
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, COL_GREEN_LIGHT); // 12 ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, COL_GREEN_LIGHT); // 12
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));//13 // The checkbox/radio frame behind this is drawn fully transparent (see FrameBg above,
// alpha 0), showing the light window background through it - a white check mark there is
// invisible. Dark mode doesn't have this problem (its window background is dark), so only
// this branch needs a check mark color with real contrast against a light background.
ImGui::PushStyleColor(ImGuiCol_CheckMark, ImVec4(0.f, 156 / 255.f, 136 / 255.f, 1.00f));//13
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
@@ -3396,36 +3389,6 @@ bool ImGuiWrapper::display_initialized() const
return io.DisplaySize.x >= 0.0f && io.DisplaySize.y >= 0.0f; return io.DisplaySize.x >= 0.0f && io.DisplaySize.y >= 0.0f;
} }
ImTextureID ImGuiWrapper::svg_texture(const std::string& filename, unsigned width, unsigned height, const char* hex_color)
{
std::string key = filename + "|" + std::to_string(width) + "x" + std::to_string(height);
if (hex_color != nullptr)
key += std::string("|") + hex_color;
const auto it = s_svg_textures.find(key);
if (it != s_svg_textures.end())
return it->second;
ImTextureID texture_id = nullptr;
const bool loaded = (hex_color != nullptr) ?
BitmapCache::load_from_svg_file_change_color(filename, width, height, texture_id, hex_color) :
IMTexture::load_from_svg_file(filename, width, height, texture_id);
if (!loaded)
return nullptr;
s_svg_textures.emplace(std::move(key), texture_id);
return texture_id;
}
void ImGuiWrapper::destroy_svg_textures()
{
for (const auto& texture : s_svg_textures) {
GLuint texture_id = (GLuint)(intptr_t)texture.second;
glsafe(::glDeleteTextures(1, &texture_id));
}
s_svg_textures.clear();
}
void ImGuiWrapper::destroy_font() void ImGuiWrapper::destroy_font()
{ {
if (m_font_texture != 0) { if (m_font_texture != 0) {
@@ -3505,6 +3468,7 @@ void ImGuiWrapper::filament_group(const std::string& filament_type, const char*
//ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); //ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
std::string id = std::to_string(static_cast<unsigned int> (filament_id + 1)); std::string id = std::to_string(static_cast<unsigned int> (filament_id + 1));
ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImDrawList* draw_list = ImGui::GetWindowDrawList();
static ImTextureID transparent;
ImVec2 text_size = ImGui::CalcTextSize(filament_type.c_str()); ImVec2 text_size = ImGui::CalcTextSize(filament_type.c_str());
// BBS image sizing based on text width (DPI scaling) // BBS image sizing based on text width (DPI scaling)
float img_width = ImGui::CalcTextSize("ABC").x; float img_width = ImGui::CalcTextSize("ABC").x;
@@ -3517,7 +3481,7 @@ void ImGuiWrapper::filament_group(const std::string& filament_type, const char*
if (rgba[3] == 0x00) { if (rgba[3] == 0x00) {
svg_path = "/images/outlined_rect_transparent.svg"; svg_path = "/images/outlined_rect_transparent.svg";
} }
ImTextureID transparent = svg_texture(Slic3r::resources_dir() + svg_path, img_size.x, img_size.y, hex_color); BitmapCache::load_from_svg_file_change_color(Slic3r::resources_dir() + svg_path, img_size.x, img_size.y, transparent, hex_color);
ImGui::BeginGroup(); ImGui::BeginGroup();
{ {
ImVec2 cursor_pos = ImGui::GetCursorScreenPos(); ImVec2 cursor_pos = ImGui::GetCursorScreenPos();
-8
View File
@@ -104,14 +104,6 @@ public:
// Hash of every draw list's vertices, indices and commands. // Hash of every draw list's vertices, indices and commands.
static ImGuiID draw_data_signature(const ImDrawData* draw_data); static ImGuiID draw_data_signature(const ImDrawData* draw_data);
// A GL texture holding an SVG icon rasterized at width x height, optionally recolored.
// Rasterizing an SVG is far too expensive to redo for every frame that draws the icon, and the
// texture the previous frame generated would leak, so the result is kept until the frame that
// finds the cache overgrown drops it (and rebuilds only what it still draws).
static ImTextureID svg_texture(const std::string& filename, unsigned width, unsigned height, const char* hex_color = nullptr);
// Deletes every texture svg_texture() handed out. Requires a current GL context.
static void destroy_svg_textures();
float scaled(float x) const { return x * m_font_size; } float scaled(float x) const { return x * m_font_size; }
ImVec2 scaled(float x, float y) const { return ImVec2(x * m_font_size, y * m_font_size); } ImVec2 scaled(float x, float y) const { return ImVec2(x * m_font_size, y * m_font_size); }
/// <summary> /// <summary>
+1 -2
View File
@@ -2225,12 +2225,11 @@ void NotificationManager::close_and_delete_self(PopNotification * self)
} }
void NotificationManager::remove_notification_of_type(const NotificationType type) { void NotificationManager::remove_notification_of_type(const NotificationType type) {
// Seven notification types may have several instances alive at once, so erase every match:
// stopping at the first one leaves the rest (and the ObjectIDs they hold) behind.
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) { for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
std::unique_ptr<PopNotification> &notification = *it; std::unique_ptr<PopNotification> &notification = *it;
if (notification->get_type() == type) { if (notification->get_type() == type) {
it = m_pop_notifications.erase(it); it = m_pop_notifications.erase(it);
break;
} else } else
++it; ++it;
} }