mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 00:01:09 -06:00
Flip Y changed back to BOTTOM_LEFT
Merge remote-tracking branch 'origin/master' into feature_slice_to_png
This commit is contained in:
commit
93ae3a0f1a
50 changed files with 1244 additions and 860 deletions
|
@ -22,11 +22,6 @@
|
|||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/spin_mutex.h>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
#include "GUI.hpp"
|
||||
|
@ -540,8 +535,8 @@ double GLVolume::layer_height_texture_z_to_row_id() const
|
|||
|
||||
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
|
||||
{
|
||||
GLTexture *tex = this->layer_height_texture.get();
|
||||
if (tex == nullptr)
|
||||
LayersTexture *tex = this->layer_height_texture.get();
|
||||
if (tex == nullptr)
|
||||
// No layer_height_texture is assigned to this GLVolume, therefore the layer height texture cannot be filled.
|
||||
return;
|
||||
|
||||
|
@ -588,8 +583,8 @@ std::vector<int> GLVolumeCollection::load_object(
|
|||
};
|
||||
|
||||
// Object will have a single common layer height texture for all volumes.
|
||||
std::shared_ptr<GLTexture> layer_height_texture = std::make_shared<GLTexture>();
|
||||
|
||||
std::shared_ptr<LayersTexture> layer_height_texture = std::make_shared<LayersTexture>();
|
||||
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++ volume_idx) {
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
|
@ -743,7 +738,7 @@ void GLVolumeCollection::render_legacy() const
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
|
||||
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state)
|
||||
{
|
||||
if (config == nullptr)
|
||||
return false;
|
||||
|
@ -757,18 +752,31 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
|
|||
// Allow the objects to protrude below the print bed
|
||||
print_volume.min.z = -1e10;
|
||||
|
||||
bool contained = true;
|
||||
ModelInstance::EPrintVolumeState state = ModelInstance::PVS_Inside;
|
||||
bool all_contained = true;
|
||||
|
||||
for (GLVolume* volume : this->volumes)
|
||||
{
|
||||
if ((volume != nullptr) && !volume->is_modifier)
|
||||
{
|
||||
bool state = print_volume.contains(volume->transformed_bounding_box());
|
||||
contained &= state;
|
||||
volume->is_outside = !state;
|
||||
const BoundingBoxf3& bb = volume->transformed_bounding_box();
|
||||
bool contained = print_volume.contains(bb);
|
||||
all_contained &= contained;
|
||||
|
||||
volume->is_outside = !contained;
|
||||
|
||||
if ((state == ModelInstance::PVS_Inside) && volume->is_outside)
|
||||
state = ModelInstance::PVS_Fully_Outside;
|
||||
|
||||
if ((state == ModelInstance::PVS_Fully_Outside) && volume->is_outside && print_volume.intersects(bb))
|
||||
state = ModelInstance::PVS_Partly_Outside;
|
||||
}
|
||||
}
|
||||
|
||||
return contained;
|
||||
if (out_state != nullptr)
|
||||
*out_state = state;
|
||||
|
||||
return all_contained;
|
||||
}
|
||||
|
||||
void GLVolumeCollection::reset_outside_state()
|
||||
|
@ -1576,246 +1584,8 @@ void _3DScene::point3_to_verts(const Point3& point, double width, double height,
|
|||
thick_point_to_verts(point, width, height, volume);
|
||||
}
|
||||
|
||||
_3DScene::LegendTexture _3DScene::s_legend_texture;
|
||||
_3DScene::WarningTexture _3DScene::s_warning_texture;
|
||||
GUI::GLCanvas3DManager _3DScene::s_canvas_mgr;
|
||||
|
||||
unsigned int _3DScene::TextureBase::finalize()
|
||||
{
|
||||
if ((m_tex_id == 0) && !m_data.empty()) {
|
||||
// sends buffer to gpu
|
||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
::glGenTextures(1, &m_tex_id);
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_tex_id);
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_tex_width, (GLsizei)m_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)m_data.data());
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
m_data.clear();
|
||||
}
|
||||
return (m_tex_width > 0 && m_tex_height > 0) ? m_tex_id : 0;
|
||||
}
|
||||
|
||||
void _3DScene::TextureBase::_destroy_texture()
|
||||
{
|
||||
if (m_tex_id > 0)
|
||||
{
|
||||
::glDeleteTextures(1, &m_tex_id);
|
||||
m_tex_id = 0;
|
||||
m_tex_height = 0;
|
||||
m_tex_width = 0;
|
||||
}
|
||||
m_data.clear();
|
||||
}
|
||||
|
||||
|
||||
const unsigned char _3DScene::WarningTexture::Background_Color[3] = { 9, 91, 134 };
|
||||
const unsigned char _3DScene::WarningTexture::Opacity = 255;
|
||||
|
||||
// Generate a texture data, but don't load it into the GPU yet, as the GPU context may not yet be valid.
|
||||
bool _3DScene::WarningTexture::generate(const std::string& msg)
|
||||
{
|
||||
// Mark the texture as released, but don't release the texture from the GPU yet.
|
||||
m_tex_width = m_tex_height = 0;
|
||||
m_data.clear();
|
||||
|
||||
if (msg.empty())
|
||||
return false;
|
||||
|
||||
wxMemoryDC memDC;
|
||||
// select default font
|
||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
|
||||
// calculates texture size
|
||||
wxCoord w, h;
|
||||
memDC.GetTextExtent(msg, &w, &h);
|
||||
m_tex_width = (unsigned int)w;
|
||||
m_tex_height = (unsigned int)h;
|
||||
|
||||
// generates bitmap
|
||||
wxBitmap bitmap(m_tex_width, m_tex_height);
|
||||
|
||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||
bitmap.UseAlpha();
|
||||
#endif
|
||||
|
||||
memDC.SelectObject(bitmap);
|
||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||
memDC.Clear();
|
||||
|
||||
memDC.SetTextForeground(*wxWHITE);
|
||||
|
||||
// draw message
|
||||
memDC.DrawText(msg, 0, 0);
|
||||
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
|
||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||
{
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||
|
||||
// prepare buffer
|
||||
m_data.assign(4 * m_tex_width * m_tex_height, 0);
|
||||
for (unsigned int h = 0; h < m_tex_height; ++h)
|
||||
{
|
||||
unsigned int hh = h * m_tex_width;
|
||||
unsigned char* px_ptr = m_data.data() + 4 * hh;
|
||||
for (unsigned int w = 0; w < m_tex_width; ++w)
|
||||
{
|
||||
*px_ptr++ = image.GetRed(w, h);
|
||||
*px_ptr++ = image.GetGreen(w, h);
|
||||
*px_ptr++ = image.GetBlue(w, h);
|
||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const unsigned char _3DScene::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
|
||||
const unsigned char _3DScene::LegendTexture::Background_Color[3] = { 9, 91, 134 };
|
||||
const unsigned char _3DScene::LegendTexture::Opacity = 255;
|
||||
|
||||
// Generate a texture data, but don't load it into the GPU yet, as the GPU context may not yet be valid.
|
||||
bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
// Mark the texture as released, but don't release the texture from the GPU yet.
|
||||
m_tex_width = m_tex_height = 0;
|
||||
m_data.clear();
|
||||
|
||||
// collects items to render
|
||||
auto title = _(preview_data.get_legend_title());
|
||||
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
|
||||
|
||||
unsigned int items_count = (unsigned int)items.size();
|
||||
if (items_count == 0)
|
||||
// nothing to render, return
|
||||
return false;
|
||||
|
||||
wxMemoryDC memDC;
|
||||
// select default font
|
||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
|
||||
// calculates texture size
|
||||
wxCoord w, h;
|
||||
memDC.GetTextExtent(title, &w, &h);
|
||||
unsigned int title_width = (unsigned int)w;
|
||||
unsigned int title_height = (unsigned int)h;
|
||||
|
||||
unsigned int max_text_width = 0;
|
||||
unsigned int max_text_height = 0;
|
||||
for (const GCodePreviewData::LegendItem& item : items)
|
||||
{
|
||||
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
|
||||
max_text_width = std::max(max_text_width, (unsigned int)w);
|
||||
max_text_height = std::max(max_text_height, (unsigned int)h);
|
||||
}
|
||||
|
||||
m_tex_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
|
||||
m_tex_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
|
||||
if (items_count > 1)
|
||||
m_tex_height += (items_count - 1) * Px_Square_Contour;
|
||||
|
||||
// generates bitmap
|
||||
wxBitmap bitmap(m_tex_width, m_tex_height);
|
||||
|
||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||
bitmap.UseAlpha();
|
||||
#endif
|
||||
|
||||
memDC.SelectObject(bitmap);
|
||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||
memDC.Clear();
|
||||
|
||||
memDC.SetTextForeground(*wxWHITE);
|
||||
|
||||
// draw title
|
||||
unsigned int title_x = Px_Border;
|
||||
unsigned int title_y = Px_Border;
|
||||
memDC.DrawText(title, title_x, title_y);
|
||||
|
||||
// draw icons contours as background
|
||||
unsigned int squares_contour_x = Px_Border;
|
||||
unsigned int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
|
||||
unsigned int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
|
||||
unsigned int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
|
||||
if (items_count > 1)
|
||||
squares_contour_height += (items_count - 1) * Px_Square_Contour;
|
||||
|
||||
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
|
||||
wxPen pen(color);
|
||||
wxBrush brush(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
|
||||
|
||||
// draw items (colored icon + text)
|
||||
unsigned int icon_x = squares_contour_x + Px_Square_Contour;
|
||||
unsigned int icon_x_inner = icon_x + 1;
|
||||
unsigned int icon_y = squares_contour_y + Px_Square_Contour;
|
||||
unsigned int icon_y_step = Px_Square + Px_Square_Contour;
|
||||
|
||||
unsigned int text_x = icon_x + Px_Square + Px_Text_Offset;
|
||||
unsigned int text_y_offset = (Px_Square - max_text_height) / 2;
|
||||
|
||||
unsigned int px_inner_square = Px_Square - 2;
|
||||
|
||||
for (const GCodePreviewData::LegendItem& item : items)
|
||||
{
|
||||
// draw darker icon perimeter
|
||||
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
|
||||
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
|
||||
dark_hsv.value *= 0.75;
|
||||
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
|
||||
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
|
||||
pen.SetColour(color);
|
||||
brush.SetColour(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
|
||||
|
||||
// draw icon interior
|
||||
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
|
||||
pen.SetColour(color);
|
||||
brush.SetColour(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
|
||||
|
||||
// draw text
|
||||
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
|
||||
|
||||
// update y
|
||||
icon_y += icon_y_step;
|
||||
}
|
||||
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
|
||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||
{
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||
|
||||
// prepare buffer
|
||||
m_data.assign(4 * m_tex_width * m_tex_height, 0);
|
||||
for (unsigned int h = 0; h < m_tex_height; ++h)
|
||||
{
|
||||
unsigned int hh = h * m_tex_width;
|
||||
unsigned char* px_ptr = m_data.data() + 4 * hh;
|
||||
for (unsigned int w = 0; w < m_tex_width; ++w)
|
||||
{
|
||||
*px_ptr++ = image.GetRed(w, h);
|
||||
*px_ptr++ = image.GetGreen(w, h);
|
||||
*px_ptr++ = image.GetBlue(w, h);
|
||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void _3DScene::init_gl()
|
||||
{
|
||||
s_canvas_mgr.init_gl();
|
||||
|
@ -1881,7 +1651,7 @@ void _3DScene::update_volumes_selection(wxGLCanvas* canvas, const std::vector<in
|
|||
s_canvas_mgr.update_volumes_selection(canvas, selections);
|
||||
}
|
||||
|
||||
bool _3DScene::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config)
|
||||
int _3DScene::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config)
|
||||
{
|
||||
return s_canvas_mgr.check_volumes_outside_state(canvas, config);
|
||||
}
|
||||
|
@ -2218,54 +1988,9 @@ void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* pr
|
|||
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
||||
}
|
||||
|
||||
void _3DScene::generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
s_legend_texture.generate(preview_data, tool_colors);
|
||||
}
|
||||
|
||||
unsigned int _3DScene::get_legend_texture_width()
|
||||
{
|
||||
return s_legend_texture.get_texture_width();
|
||||
}
|
||||
|
||||
unsigned int _3DScene::get_legend_texture_height()
|
||||
{
|
||||
return s_legend_texture.get_texture_height();
|
||||
}
|
||||
|
||||
void _3DScene::reset_legend_texture()
|
||||
{
|
||||
s_legend_texture.reset_texture();
|
||||
}
|
||||
|
||||
unsigned int _3DScene::finalize_legend_texture()
|
||||
{
|
||||
return s_legend_texture.finalize();
|
||||
}
|
||||
|
||||
unsigned int _3DScene::get_warning_texture_width()
|
||||
{
|
||||
return s_warning_texture.get_texture_width();
|
||||
}
|
||||
|
||||
unsigned int _3DScene::get_warning_texture_height()
|
||||
{
|
||||
return s_warning_texture.get_texture_height();
|
||||
}
|
||||
|
||||
void _3DScene::generate_warning_texture(const std::string& msg)
|
||||
{
|
||||
s_warning_texture.generate(msg);
|
||||
}
|
||||
|
||||
void _3DScene::reset_warning_texture()
|
||||
{
|
||||
s_warning_texture.reset_texture();
|
||||
}
|
||||
|
||||
unsigned int _3DScene::finalize_warning_texture()
|
||||
{
|
||||
return s_warning_texture.finalize();
|
||||
s_canvas_mgr.reset_legend_texture();
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../../libslic3r/Line.hpp"
|
||||
#include "../../libslic3r/TriangleMesh.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../libslic3r/Model.hpp"
|
||||
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
||||
|
||||
class wxBitmap;
|
||||
|
@ -199,10 +200,10 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class GLTexture
|
||||
class LayersTexture
|
||||
{
|
||||
public:
|
||||
GLTexture() : width(0), height(0), levels(0), cells(0) {}
|
||||
LayersTexture() : width(0), height(0), levels(0), cells(0) {}
|
||||
|
||||
// Texture data
|
||||
std::vector<char> data;
|
||||
|
@ -341,7 +342,7 @@ public:
|
|||
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
||||
|
||||
/************************************************ Layer height texture ****************************************************/
|
||||
std::shared_ptr<GLTexture> layer_height_texture;
|
||||
std::shared_ptr<LayersTexture> layer_height_texture;
|
||||
// Data to render this volume using the layer height texture
|
||||
LayerHeightTextureData layer_height_texture_data;
|
||||
|
||||
|
@ -422,7 +423,9 @@ public:
|
|||
print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z;
|
||||
}
|
||||
|
||||
bool check_outside_state(const DynamicPrintConfig* config);
|
||||
// returns true if all the volumes are completely contained in the print volume
|
||||
// returns the containment state in the given out_state, if non-null
|
||||
bool check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state);
|
||||
void reset_outside_state();
|
||||
|
||||
void update_colors_by_extruder(const DynamicPrintConfig* config);
|
||||
|
@ -437,65 +440,6 @@ private:
|
|||
|
||||
class _3DScene
|
||||
{
|
||||
class TextureBase
|
||||
{
|
||||
protected:
|
||||
unsigned int m_tex_id;
|
||||
unsigned int m_tex_width;
|
||||
unsigned int m_tex_height;
|
||||
|
||||
// generate() fills in m_data with the pixels, while finalize() moves the data to the GPU before rendering.
|
||||
std::vector<unsigned char> m_data;
|
||||
|
||||
public:
|
||||
TextureBase() : m_tex_id(0), m_tex_width(0), m_tex_height(0) {}
|
||||
virtual ~TextureBase() { _destroy_texture(); }
|
||||
|
||||
// If not loaded, load the texture data into the GPU. Return a texture ID or 0 if the texture has zero size.
|
||||
unsigned int finalize();
|
||||
|
||||
unsigned int get_texture_id() const { return m_tex_id; }
|
||||
unsigned int get_texture_width() const { return m_tex_width; }
|
||||
unsigned int get_texture_height() const { return m_tex_height; }
|
||||
|
||||
void reset_texture() { _destroy_texture(); }
|
||||
|
||||
private:
|
||||
void _destroy_texture();
|
||||
};
|
||||
|
||||
class WarningTexture : public TextureBase
|
||||
{
|
||||
static const unsigned char Background_Color[3];
|
||||
static const unsigned char Opacity;
|
||||
|
||||
public:
|
||||
WarningTexture() : TextureBase() {}
|
||||
|
||||
// Generate a texture data, but don't load it into the GPU yet, as the glcontext may not be valid yet.
|
||||
bool generate(const std::string& msg);
|
||||
};
|
||||
|
||||
class LegendTexture : public TextureBase
|
||||
{
|
||||
static const unsigned int Px_Title_Offset = 5;
|
||||
static const unsigned int Px_Text_Offset = 5;
|
||||
static const unsigned int Px_Square = 20;
|
||||
static const unsigned int Px_Square_Contour = 1;
|
||||
static const unsigned int Px_Border = Px_Square / 2;
|
||||
static const unsigned char Squares_Border_Color[3];
|
||||
static const unsigned char Background_Color[3];
|
||||
static const unsigned char Opacity;
|
||||
|
||||
public:
|
||||
LegendTexture() : TextureBase() {}
|
||||
|
||||
// Generate a texture data, but don't load it into the GPU yet, as the glcontext may not be valid yet.
|
||||
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
};
|
||||
|
||||
static LegendTexture s_legend_texture;
|
||||
static WarningTexture s_warning_texture;
|
||||
static GUI::GLCanvas3DManager s_canvas_mgr;
|
||||
|
||||
public:
|
||||
|
@ -516,7 +460,7 @@ public:
|
|||
static void deselect_volumes(wxGLCanvas* canvas);
|
||||
static void select_volume(wxGLCanvas* canvas, unsigned int id);
|
||||
static void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
static bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config);
|
||||
static int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config);
|
||||
static bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
|
||||
static bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
|
||||
|
||||
|
@ -597,21 +541,7 @@ public:
|
|||
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
// generates the legend texture in dependence of the current shown view type
|
||||
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
static unsigned int get_legend_texture_width();
|
||||
static unsigned int get_legend_texture_height();
|
||||
|
||||
static void reset_legend_texture();
|
||||
static unsigned int finalize_legend_texture();
|
||||
|
||||
static unsigned int get_warning_texture_width();
|
||||
static unsigned int get_warning_texture_height();
|
||||
|
||||
// generates a warning texture containing the given message
|
||||
static void generate_warning_texture(const std::string& msg);
|
||||
static void reset_warning_texture();
|
||||
static unsigned int finalize_warning_texture();
|
||||
|
||||
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
||||
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
||||
|
|
|
@ -65,22 +65,27 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
|
|||
auto namefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
namefont.SetWeight(wxFONTWEIGHT_BOLD);
|
||||
|
||||
// wxGrid appends widgets by rows, but we need to construct them in columns.
|
||||
// These vectors are used to hold the elements so that they can be appended in the right order.
|
||||
std::vector<wxStaticText*> titles;
|
||||
std::vector<wxStaticBitmap*> bitmaps;
|
||||
std::vector<wxPanel*> variants_panels;
|
||||
|
||||
for (const auto &model : models) {
|
||||
auto *panel = new wxPanel(this);
|
||||
auto *col_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel->SetSizer(col_sizer);
|
||||
|
||||
auto *title = new wxStaticText(panel, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||
title->SetFont(namefont);
|
||||
col_sizer->Add(title, 0, wxBOTTOM, 3);
|
||||
|
||||
auto bitmap_file = wxString::Format("printers/%s_%s.png", vendor.id, model.id);
|
||||
wxBitmap bitmap(GUI::from_u8(Slic3r::var(bitmap_file.ToStdString())), wxBITMAP_TYPE_PNG);
|
||||
auto *bitmap_widget = new wxStaticBitmap(panel, wxID_ANY, bitmap);
|
||||
col_sizer->Add(bitmap_widget, 0, wxBOTTOM, 3);
|
||||
|
||||
col_sizer->AddSpacer(20);
|
||||
auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||
title->SetFont(namefont);
|
||||
title->Wrap(std::max((int)MODEL_MIN_WRAP, bitmap.GetWidth()));
|
||||
titles.push_back(title);
|
||||
|
||||
auto *bitmap_widget = new wxStaticBitmap(this, wxID_ANY, bitmap);
|
||||
bitmaps.push_back(bitmap_widget);
|
||||
|
||||
auto *variants_panel = new wxPanel(this);
|
||||
auto *variants_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
variants_panel->SetSizer(variants_sizer);
|
||||
const auto model_id = model.id;
|
||||
|
||||
bool default_variant = true; // Mark the first variant as default in the GUI
|
||||
|
@ -88,22 +93,26 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
|
|||
const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
|
||||
(default_variant ? _(L("(default)")) : wxString()));
|
||||
default_variant = false;
|
||||
auto *cbox = new Checkbox(panel, label, model_id, variant.name);
|
||||
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
||||
const size_t idx = cboxes.size();
|
||||
cboxes.push_back(cbox);
|
||||
bool enabled = appconfig_vendors.get_variant("PrusaResearch", model_id, variant.name);
|
||||
variants_checked += enabled;
|
||||
cbox->SetValue(enabled);
|
||||
col_sizer->Add(cbox, 0, wxBOTTOM, 3);
|
||||
variants_sizer->Add(cbox, 0, wxBOTTOM, 3);
|
||||
cbox->Bind(wxEVT_CHECKBOX, [this, idx](wxCommandEvent &event) {
|
||||
if (idx >= this->cboxes.size()) { return; }
|
||||
this->on_checkbox(this->cboxes[idx], event.IsChecked());
|
||||
});
|
||||
}
|
||||
|
||||
printer_grid->Add(panel);
|
||||
variants_panels.push_back(variants_panel);
|
||||
}
|
||||
|
||||
for (auto title : titles) { printer_grid->Add(title, 0, wxBOTTOM, 3); }
|
||||
for (auto bitmap : bitmaps) { printer_grid->Add(bitmap, 0, wxBOTTOM, 20); }
|
||||
for (auto vp : variants_panels) { printer_grid->Add(vp); }
|
||||
|
||||
auto *all_none_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto *sel_all = new wxButton(this, wxID_ANY, _(L("Select all")));
|
||||
auto *sel_none = new wxButton(this, wxID_ANY, _(L("Select none")));
|
||||
|
@ -214,7 +223,7 @@ void ConfigWizardPage::enable_next(bool enable) { parent->p->enable_next(enable)
|
|||
|
||||
// Wizard pages
|
||||
|
||||
PageWelcome::PageWelcome(ConfigWizard *parent) :
|
||||
PageWelcome::PageWelcome(ConfigWizard *parent, bool check_first_variant) :
|
||||
ConfigWizardPage(parent, wxString::Format(_(L("Welcome to the Slic3r %s")), ConfigWizard::name()), _(L("Welcome"))),
|
||||
printer_picker(nullptr),
|
||||
others_buttons(new wxPanel(parent)),
|
||||
|
@ -238,7 +247,10 @@ PageWelcome::PageWelcome(ConfigWizard *parent) :
|
|||
AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors;
|
||||
|
||||
printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors);
|
||||
printer_picker->select_one(0, true); // Select the default (first) model/variant on the Prusa vendor
|
||||
if (check_first_variant) {
|
||||
// Select the default (first) model/variant on the Prusa vendor
|
||||
printer_picker->select_one(0, true);
|
||||
}
|
||||
printer_picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
|
||||
appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
|
||||
this->on_variant_checked();
|
||||
|
@ -779,7 +791,6 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||
app_config->set("version_check", page_update->version_check ? "1" : "0");
|
||||
app_config->set("preset_update", page_update->preset_update ? "1" : "0");
|
||||
app_config->reset_selections();
|
||||
// ^ TODO: replace with appropriate printer selection
|
||||
preset_bundle->load_presets(*app_config);
|
||||
} else {
|
||||
for (ConfigWizardPage *page = page_firmware; page != nullptr; page = page->page_next()) {
|
||||
|
@ -831,7 +842,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
|
|||
p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING);
|
||||
p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING);
|
||||
|
||||
p->add_page(p->page_welcome = new PageWelcome(this));
|
||||
p->add_page(p->page_welcome = new PageWelcome(this, reason == RR_DATA_EMPTY || reason == RR_DATA_LEGACY));
|
||||
p->add_page(p->page_update = new PageUpdate(this));
|
||||
p->add_page(p->page_vendors = new PageVendors(this));
|
||||
p->add_page(p->page_firmware = new PageFirmware(this));
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace GUI {
|
|||
|
||||
enum {
|
||||
WRAP_WIDTH = 500,
|
||||
MODEL_MIN_WRAP = 150,
|
||||
|
||||
DIALOG_MARGIN = 15,
|
||||
INDEX_MARGIN = 40,
|
||||
|
@ -103,7 +104,7 @@ struct PageWelcome: ConfigWizardPage
|
|||
wxPanel *others_buttons;
|
||||
wxCheckBox *cbox_reset;
|
||||
|
||||
PageWelcome(ConfigWizard *parent);
|
||||
PageWelcome(ConfigWizard *parent, bool check_first_variant);
|
||||
|
||||
virtual wxPanel* extra_buttons() { return others_buttons; }
|
||||
virtual void on_page_set();
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/spin_mutex.h>
|
||||
|
@ -1381,7 +1385,8 @@ void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& b
|
|||
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
_render_current_gizmo(box);
|
||||
if (box.radius() > 0.0)
|
||||
_render_current_gizmo(box);
|
||||
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity();
|
||||
|
@ -1456,6 +1461,224 @@ float GLCanvas3D::Gizmos::_get_total_overlay_height() const
|
|||
return height;
|
||||
}
|
||||
|
||||
const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 9, 91, 134 };
|
||||
const unsigned char GLCanvas3D::WarningTexture::Opacity = 255;
|
||||
|
||||
bool GLCanvas3D::WarningTexture::generate(const std::string& msg)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (msg.empty())
|
||||
return false;
|
||||
|
||||
wxMemoryDC memDC;
|
||||
// select default font
|
||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
|
||||
// calculates texture size
|
||||
wxCoord w, h;
|
||||
memDC.GetTextExtent(msg, &w, &h);
|
||||
m_width = (int)w;
|
||||
m_height = (int)h;
|
||||
|
||||
// generates bitmap
|
||||
wxBitmap bitmap(m_width, m_height);
|
||||
|
||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||
bitmap.UseAlpha();
|
||||
#endif
|
||||
|
||||
memDC.SelectObject(bitmap);
|
||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||
memDC.Clear();
|
||||
|
||||
memDC.SetTextForeground(*wxWHITE);
|
||||
|
||||
// draw message
|
||||
memDC.DrawText(msg, 0, 0);
|
||||
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
|
||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||
|
||||
// prepare buffer
|
||||
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
||||
for (int h = 0; h < m_height; ++h)
|
||||
{
|
||||
int hh = h * m_width;
|
||||
unsigned char* px_ptr = data.data() + 4 * hh;
|
||||
for (int w = 0; w < m_width; ++w)
|
||||
{
|
||||
*px_ptr++ = image.GetRed(w, h);
|
||||
*px_ptr++ = image.GetGreen(w, h);
|
||||
*px_ptr++ = image.GetBlue(w, h);
|
||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||
}
|
||||
}
|
||||
|
||||
// sends buffer to gpu
|
||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
::glGenTextures(1, &m_id);
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const unsigned char GLCanvas3D::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
|
||||
const unsigned char GLCanvas3D::LegendTexture::Background_Color[3] = { 9, 91, 134 };
|
||||
const unsigned char GLCanvas3D::LegendTexture::Opacity = 255;
|
||||
|
||||
bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
reset();
|
||||
|
||||
// collects items to render
|
||||
auto title = _(preview_data.get_legend_title());
|
||||
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
|
||||
|
||||
unsigned int items_count = (unsigned int)items.size();
|
||||
if (items_count == 0)
|
||||
// nothing to render, return
|
||||
return false;
|
||||
|
||||
wxMemoryDC memDC;
|
||||
// select default font
|
||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
|
||||
// calculates texture size
|
||||
wxCoord w, h;
|
||||
memDC.GetTextExtent(title, &w, &h);
|
||||
int title_width = (int)w;
|
||||
int title_height = (int)h;
|
||||
|
||||
int max_text_width = 0;
|
||||
int max_text_height = 0;
|
||||
for (const GCodePreviewData::LegendItem& item : items)
|
||||
{
|
||||
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
|
||||
max_text_width = std::max(max_text_width, (int)w);
|
||||
max_text_height = std::max(max_text_height, (int)h);
|
||||
}
|
||||
|
||||
m_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
|
||||
m_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
|
||||
if (items_count > 1)
|
||||
m_height += (items_count - 1) * Px_Square_Contour;
|
||||
|
||||
// generates bitmap
|
||||
wxBitmap bitmap(m_width, m_height);
|
||||
|
||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||
bitmap.UseAlpha();
|
||||
#endif
|
||||
|
||||
memDC.SelectObject(bitmap);
|
||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||
memDC.Clear();
|
||||
|
||||
memDC.SetTextForeground(*wxWHITE);
|
||||
|
||||
// draw title
|
||||
int title_x = Px_Border;
|
||||
int title_y = Px_Border;
|
||||
memDC.DrawText(title, title_x, title_y);
|
||||
|
||||
// draw icons contours as background
|
||||
int squares_contour_x = Px_Border;
|
||||
int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
|
||||
int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
|
||||
int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
|
||||
if (items_count > 1)
|
||||
squares_contour_height += (items_count - 1) * Px_Square_Contour;
|
||||
|
||||
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
|
||||
wxPen pen(color);
|
||||
wxBrush brush(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
|
||||
|
||||
// draw items (colored icon + text)
|
||||
int icon_x = squares_contour_x + Px_Square_Contour;
|
||||
int icon_x_inner = icon_x + 1;
|
||||
int icon_y = squares_contour_y + Px_Square_Contour;
|
||||
int icon_y_step = Px_Square + Px_Square_Contour;
|
||||
|
||||
int text_x = icon_x + Px_Square + Px_Text_Offset;
|
||||
int text_y_offset = (Px_Square - max_text_height) / 2;
|
||||
|
||||
int px_inner_square = Px_Square - 2;
|
||||
|
||||
for (const GCodePreviewData::LegendItem& item : items)
|
||||
{
|
||||
// draw darker icon perimeter
|
||||
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
|
||||
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
|
||||
dark_hsv.value *= 0.75;
|
||||
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
|
||||
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
|
||||
pen.SetColour(color);
|
||||
brush.SetColour(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
|
||||
|
||||
// draw icon interior
|
||||
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
|
||||
pen.SetColour(color);
|
||||
brush.SetColour(color);
|
||||
memDC.SetPen(pen);
|
||||
memDC.SetBrush(brush);
|
||||
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
|
||||
|
||||
// draw text
|
||||
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
|
||||
|
||||
// update y
|
||||
icon_y += icon_y_step;
|
||||
}
|
||||
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
|
||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||
wxImage image = bitmap.ConvertToImage();
|
||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||
|
||||
// prepare buffer
|
||||
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
||||
for (int h = 0; h < m_height; ++h)
|
||||
{
|
||||
int hh = h * m_width;
|
||||
unsigned char* px_ptr = data.data() + 4 * hh;
|
||||
for (int w = 0; w < m_width; ++w)
|
||||
{
|
||||
*px_ptr++ = image.GetRed(w, h);
|
||||
*px_ptr++ = image.GetGreen(w, h);
|
||||
*px_ptr++ = image.GetBlue(w, h);
|
||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||
}
|
||||
}
|
||||
|
||||
// sends buffer to gpu
|
||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
::glGenTextures(1, &m_id);
|
||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
|
||||
{
|
||||
GizmosMap::const_iterator it = m_gizmos.find(m_current);
|
||||
|
@ -1655,9 +1878,11 @@ void GLCanvas3D::update_volumes_selection(const std::vector<int>& selections)
|
|||
}
|
||||
}
|
||||
|
||||
bool GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
|
||||
int GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
|
||||
{
|
||||
return m_volumes.check_outside_state(config);
|
||||
ModelInstance::EPrintVolumeState state;
|
||||
m_volumes.check_outside_state(config, &state);
|
||||
return (int)state;
|
||||
}
|
||||
|
||||
bool GLCanvas3D::move_volume_up(unsigned int id)
|
||||
|
@ -1905,7 +2130,7 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
|
|||
|
||||
void GLCanvas3D::update_gizmos_data()
|
||||
{
|
||||
if (!m_gizmos.is_running())
|
||||
if (!m_gizmos.is_enabled())
|
||||
return;
|
||||
|
||||
int id = _get_first_selected_object_id();
|
||||
|
@ -1917,26 +2142,16 @@ void GLCanvas3D::update_gizmos_data()
|
|||
ModelInstance* model_instance = model_object->instances[0];
|
||||
if (model_instance != nullptr)
|
||||
{
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case Gizmos::Scale:
|
||||
{
|
||||
m_gizmos.set_scale(model_instance->scaling_factor);
|
||||
break;
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
m_gizmos.set_angle_z(model_instance->rotation);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_gizmos.set_scale(model_instance->scaling_factor);
|
||||
m_gizmos.set_angle_z(model_instance->rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gizmos.set_scale(1.0f);
|
||||
m_gizmos.set_angle_z(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3D::render()
|
||||
|
@ -2051,8 +2266,12 @@ void GLCanvas3D::reload_scene(bool force)
|
|||
m_objects_volumes_idxs.push_back(load_object(*m_model, obj_idx));
|
||||
}
|
||||
|
||||
// 1st call to reset if no objects left
|
||||
update_gizmos_data();
|
||||
update_volumes_selection(m_objects_selections);
|
||||
// 2nd call to restore if something selected
|
||||
if (!m_objects_selections.empty())
|
||||
update_gizmos_data();
|
||||
|
||||
if (m_config->has("nozzle_diameter"))
|
||||
{
|
||||
|
@ -2082,25 +2301,28 @@ void GLCanvas3D::reload_scene(bool force)
|
|||
// checks for geometry outside the print volume to render it accordingly
|
||||
if (!m_volumes.empty())
|
||||
{
|
||||
bool contained = m_volumes.check_outside_state(m_config);
|
||||
ModelInstance::EPrintVolumeState state;
|
||||
bool contained = m_volumes.check_outside_state(m_config, &state);
|
||||
|
||||
if (!contained)
|
||||
{
|
||||
enable_warning_texture(true);
|
||||
_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
||||
m_on_enable_action_buttons_callback.call(false);
|
||||
_generate_warning_texture(L("Detected object outside print volume"));
|
||||
m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
|
||||
}
|
||||
else
|
||||
{
|
||||
enable_warning_texture(false);
|
||||
m_volumes.reset_outside_state();
|
||||
_3DScene::reset_warning_texture();
|
||||
_reset_warning_texture();
|
||||
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
enable_warning_texture(false);
|
||||
_3DScene::reset_warning_texture();
|
||||
_reset_warning_texture();
|
||||
m_on_enable_action_buttons_callback.call(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2490,11 +2712,11 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
|
|||
_load_gcode_unretractions(preview_data);
|
||||
|
||||
if (m_volumes.empty())
|
||||
_3DScene::reset_legend_texture();
|
||||
reset_legend_texture();
|
||||
else
|
||||
{
|
||||
_3DScene::generate_legend_texture(preview_data, tool_colors);
|
||||
|
||||
_generate_legend_texture(preview_data, tool_colors);
|
||||
|
||||
// removes empty volumes
|
||||
m_volumes.volumes.erase(std::remove_if(m_volumes.volumes.begin(), m_volumes.volumes.end(),
|
||||
[](const GLVolume* volume) { return volume->print_zs.empty(); }), m_volumes.volumes.end());
|
||||
|
@ -3103,6 +3325,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
{
|
||||
deselect_volumes();
|
||||
_on_select(-1);
|
||||
update_gizmos_data();
|
||||
}
|
||||
}
|
||||
else if (evt.LeftUp() && m_gizmos.is_dragging())
|
||||
|
@ -3130,6 +3353,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
m_mouse.set_start_position_3D_as_invalid();
|
||||
m_mouse.set_start_position_2D_as_invalid();
|
||||
m_mouse.dragging = false;
|
||||
m_dirty = true;
|
||||
}
|
||||
else if (evt.Moving())
|
||||
{
|
||||
|
@ -3181,6 +3405,14 @@ Point GLCanvas3D::get_local_mouse_position() const
|
|||
return Point(mouse_pos.x, mouse_pos.y);
|
||||
}
|
||||
|
||||
void GLCanvas3D::reset_legend_texture()
|
||||
{
|
||||
if (!set_current())
|
||||
return;
|
||||
|
||||
m_legend_texture.reset();
|
||||
}
|
||||
|
||||
bool GLCanvas3D::_is_shown_on_screen() const
|
||||
{
|
||||
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
||||
|
@ -3272,7 +3504,7 @@ BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const
|
|||
BoundingBoxf3 bb;
|
||||
for (const GLVolume* volume : m_volumes.volumes)
|
||||
{
|
||||
if ((volume != nullptr) && volume->selected)
|
||||
if ((volume != nullptr) && !volume->is_wipe_tower && volume->selected)
|
||||
bb.merge(volume->transformed_bounding_box());
|
||||
}
|
||||
return bb;
|
||||
|
@ -3441,6 +3673,7 @@ void GLCanvas3D::_picking_pass() const
|
|||
::glDisable(GL_MULTISAMPLE);
|
||||
|
||||
::glDisable(GL_BLEND);
|
||||
::glEnable(GL_DEPTH_TEST);
|
||||
|
||||
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
@ -3549,7 +3782,7 @@ void GLCanvas3D::_render_objects() const
|
|||
{
|
||||
const BoundingBoxf3& bed_bb = m_bed.get_bounding_box();
|
||||
m_volumes.set_print_box((float)bed_bb.min.x, (float)bed_bb.min.y, 0.0f, (float)bed_bb.max.x, (float)bed_bb.max.y, (float)m_config->opt_float("max_print_height"));
|
||||
m_volumes.check_outside_state(m_config);
|
||||
m_volumes.check_outside_state(m_config, nullptr);
|
||||
}
|
||||
// do not cull backfaces to show broken geometry, if any
|
||||
::glDisable(GL_CULL_FACE);
|
||||
|
@ -3588,11 +3821,11 @@ void GLCanvas3D::_render_warning_texture() const
|
|||
return;
|
||||
|
||||
// If the warning texture has not been loaded into the GPU, do it now.
|
||||
unsigned int tex_id = _3DScene::finalize_warning_texture();
|
||||
unsigned int tex_id = m_warning_texture.get_id();
|
||||
if (tex_id > 0)
|
||||
{
|
||||
unsigned int w = _3DScene::get_warning_texture_width();
|
||||
unsigned int h = _3DScene::get_warning_texture_height();
|
||||
int w = m_warning_texture.get_width();
|
||||
int h = m_warning_texture.get_height();
|
||||
if ((w > 0) && (h > 0))
|
||||
{
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
@ -3621,11 +3854,11 @@ void GLCanvas3D::_render_legend_texture() const
|
|||
return;
|
||||
|
||||
// If the legend texture has not been loaded into the GPU, do it now.
|
||||
unsigned int tex_id = _3DScene::finalize_legend_texture();
|
||||
unsigned int tex_id = m_legend_texture.get_id();
|
||||
if (tex_id > 0)
|
||||
{
|
||||
unsigned int w = _3DScene::get_legend_texture_width();
|
||||
unsigned int h = _3DScene::get_legend_texture_height();
|
||||
int w = m_legend_texture.get_width();
|
||||
int h = m_legend_texture.get_height();
|
||||
if ((w > 0) && (h > 0))
|
||||
{
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
|
@ -4539,5 +4772,29 @@ std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& col
|
|||
return output;
|
||||
}
|
||||
|
||||
void GLCanvas3D::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||
{
|
||||
if (!set_current())
|
||||
return;
|
||||
|
||||
m_legend_texture.generate(preview_data, tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_generate_warning_texture(const std::string& msg)
|
||||
{
|
||||
if (!set_current())
|
||||
return;
|
||||
|
||||
m_warning_texture.generate(msg);
|
||||
}
|
||||
|
||||
void GLCanvas3D::_reset_warning_texture()
|
||||
{
|
||||
if (!set_current())
|
||||
return;
|
||||
|
||||
m_warning_texture.reset();
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -394,9 +394,35 @@ public:
|
|||
GLGizmoBase* _get_current() const;
|
||||
};
|
||||
|
||||
class WarningTexture : public GUI::GLTexture
|
||||
{
|
||||
static const unsigned char Background_Color[3];
|
||||
static const unsigned char Opacity;
|
||||
|
||||
public:
|
||||
bool generate(const std::string& msg);
|
||||
};
|
||||
|
||||
class LegendTexture : public GUI::GLTexture
|
||||
{
|
||||
static const int Px_Title_Offset = 5;
|
||||
static const int Px_Text_Offset = 5;
|
||||
static const int Px_Square = 20;
|
||||
static const int Px_Square_Contour = 1;
|
||||
static const int Px_Border = Px_Square / 2;
|
||||
static const unsigned char Squares_Border_Color[3];
|
||||
static const unsigned char Background_Color[3];
|
||||
static const unsigned char Opacity;
|
||||
|
||||
public:
|
||||
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
};
|
||||
|
||||
private:
|
||||
wxGLCanvas* m_canvas;
|
||||
wxGLContext* m_context;
|
||||
LegendTexture m_legend_texture;
|
||||
WarningTexture m_warning_texture;
|
||||
wxTimer* m_timer;
|
||||
Camera m_camera;
|
||||
Bed m_bed;
|
||||
|
@ -469,7 +495,7 @@ public:
|
|||
void deselect_volumes();
|
||||
void select_volume(unsigned int id);
|
||||
void update_volumes_selection(const std::vector<int>& selections);
|
||||
bool check_volumes_outside_state(const DynamicPrintConfig* config) const;
|
||||
int check_volumes_outside_state(const DynamicPrintConfig* config) const;
|
||||
bool move_volume_up(unsigned int id);
|
||||
bool move_volume_down(unsigned int id);
|
||||
|
||||
|
@ -578,6 +604,8 @@ public:
|
|||
Size get_canvas_size() const;
|
||||
Point get_local_mouse_position() const;
|
||||
|
||||
void reset_legend_texture();
|
||||
|
||||
private:
|
||||
bool _is_shown_on_screen() const;
|
||||
void _force_zoom_to_bed();
|
||||
|
@ -643,6 +671,13 @@ private:
|
|||
void _on_move(const std::vector<int>& volume_idxs);
|
||||
void _on_select(int volume_idx);
|
||||
|
||||
// generates the legend texture in dependence of the current shown view type
|
||||
void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
|
||||
// generates a warning texture containing the given message
|
||||
void _generate_warning_texture(const std::string& msg);
|
||||
void _reset_warning_texture();
|
||||
|
||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||
};
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std::
|
|||
it->second->update_volumes_selection(selections);
|
||||
}
|
||||
|
||||
bool GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const
|
||||
int GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const
|
||||
{
|
||||
CanvasesMap::const_iterator it = _get_canvas(canvas);
|
||||
return (it != m_canvases.end()) ? it->second->check_volumes_outside_state(config) : false;
|
||||
|
@ -550,6 +550,15 @@ void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePrevie
|
|||
it->second->load_gcode_preview(*preview_data, str_tool_colors);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::reset_legend_texture()
|
||||
{
|
||||
for (CanvasesMap::value_type& canvas : m_canvases)
|
||||
{
|
||||
if (canvas.second != nullptr)
|
||||
canvas.second->reset_legend_texture();
|
||||
}
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void deselect_volumes(wxGLCanvas* canvas);
|
||||
void select_volume(wxGLCanvas* canvas, unsigned int id);
|
||||
void update_volumes_selection(wxGLCanvas* canvas, const std::vector<int>& selections);
|
||||
bool check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const;
|
||||
int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const;
|
||||
bool move_volume_up(wxGLCanvas* canvas, unsigned int id);
|
||||
bool move_volume_down(wxGLCanvas* canvas, unsigned int id);
|
||||
|
||||
|
@ -137,6 +137,8 @@ public:
|
|||
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||
|
||||
void reset_legend_texture();
|
||||
|
||||
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
|
|
@ -79,7 +79,8 @@ bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmap
|
|||
if (generate_mipmaps)
|
||||
{
|
||||
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
|
||||
_generate_mipmaps(image);
|
||||
unsigned int levels_count = _generate_mipmaps(image);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1 + levels_count);
|
||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
else
|
||||
|
@ -149,14 +150,14 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo
|
|||
::glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void GLTexture::_generate_mipmaps(wxImage& image)
|
||||
unsigned int GLTexture::_generate_mipmaps(wxImage& image)
|
||||
{
|
||||
int w = image.GetWidth();
|
||||
int h = image.GetHeight();
|
||||
GLint level = 0;
|
||||
std::vector<unsigned char> data(w * h * 4, 0);
|
||||
|
||||
while ((w > 1) && (h > 1))
|
||||
while ((w > 1) || (h > 1))
|
||||
{
|
||||
++level;
|
||||
|
||||
|
@ -183,6 +184,8 @@ void GLTexture::_generate_mipmaps(wxImage& image)
|
|||
|
||||
::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||
}
|
||||
|
||||
return (unsigned int)level;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace GUI {
|
|||
|
||||
class GLTexture
|
||||
{
|
||||
private:
|
||||
protected:
|
||||
unsigned int m_id;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
@ -18,7 +18,7 @@ namespace GUI {
|
|||
|
||||
public:
|
||||
GLTexture();
|
||||
~GLTexture();
|
||||
virtual ~GLTexture();
|
||||
|
||||
bool load_from_file(const std::string& filename, bool generate_mipmaps);
|
||||
void reset();
|
||||
|
@ -26,12 +26,13 @@ namespace GUI {
|
|||
unsigned int get_id() const;
|
||||
int get_width() const;
|
||||
int get_height() const;
|
||||
|
||||
const std::string& get_source() const;
|
||||
|
||||
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
|
||||
|
||||
private:
|
||||
void _generate_mipmaps(wxImage& image);
|
||||
protected:
|
||||
unsigned int _generate_mipmaps(wxImage& image);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -268,7 +268,7 @@ void PresetBundle::load_installed_printers(const AppConfig &config)
|
|||
}
|
||||
|
||||
// Load selections (current print, current filaments, current printer) from config.ini
|
||||
// This is done just once on application start up.
|
||||
// This is done on application start up or after updates are applied.
|
||||
void PresetBundle::load_selections(const AppConfig &config)
|
||||
{
|
||||
// Update visibility of presets based on application vendor / model / variant configuration.
|
||||
|
|
|
@ -1742,27 +1742,27 @@ PageShp TabPrinter::build_kinematics_page()
|
|||
}
|
||||
|
||||
std::vector<std::string> axes{ "x", "y", "z", "e" };
|
||||
auto optgroup = page->new_optgroup(_(L("Maximum accelerations")));
|
||||
for (const std::string &axis : axes) {
|
||||
append_option_line(optgroup, "machine_max_acceleration_" + axis);
|
||||
}
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Maximum feedrates")));
|
||||
auto optgroup = page->new_optgroup(_(L("Maximum feedrates")));
|
||||
for (const std::string &axis : axes) {
|
||||
append_option_line(optgroup, "machine_max_feedrate_" + axis);
|
||||
}
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Starting Acceleration")));
|
||||
optgroup = page->new_optgroup(_(L("Maximum accelerations")));
|
||||
for (const std::string &axis : axes) {
|
||||
append_option_line(optgroup, "machine_max_acceleration_" + axis);
|
||||
}
|
||||
append_option_line(optgroup, "machine_max_acceleration_extruding");
|
||||
append_option_line(optgroup, "machine_max_acceleration_retracting");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Advanced")));
|
||||
append_option_line(optgroup, "machine_min_extruding_rate");
|
||||
append_option_line(optgroup, "machine_min_travel_rate");
|
||||
optgroup = page->new_optgroup(_(L("Jerk limits")));
|
||||
for (const std::string &axis : axes) {
|
||||
append_option_line(optgroup, "machine_max_jerk_" + axis);
|
||||
}
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Minimum feedrates")));
|
||||
append_option_line(optgroup, "machine_min_extruding_rate");
|
||||
append_option_line(optgroup, "machine_min_travel_rate");
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
|
@ -322,10 +322,13 @@ Updates PresetUpdater::priv::get_config_updates() const
|
|||
|
||||
const auto ver_current = idx.find(vp.config_version);
|
||||
if (ver_current == idx.end()) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Preset bundle (`%1%`) version not found in index: %2%") % idx.vendor() % vp.config_version.to_string();
|
||||
continue;
|
||||
auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str();
|
||||
BOOST_LOG_TRIVIAL(error) << message;
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
|
||||
// Getting a recommended version from the latest index, wich may have been downloaded
|
||||
// from the internet, or installed / updated from the installation resources.
|
||||
const auto recommended = idx.recommended();
|
||||
if (recommended == idx.end()) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % idx.vendor();
|
||||
|
@ -353,25 +356,34 @@ Updates PresetUpdater::priv::get_config_updates() const
|
|||
}
|
||||
|
||||
auto path_src = cache_path / (idx.vendor() + ".ini");
|
||||
auto path_in_rsrc = rsrc_path / (idx.vendor() + ".ini");
|
||||
if (! fs::exists(path_src)) {
|
||||
auto path_in_rsrc = rsrc_path / (idx.vendor() + ".ini");
|
||||
if (! fs::exists(path_in_rsrc)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update, but bundle found in neither cache nor resources")
|
||||
% idx.vendor();;
|
||||
% idx.vendor();
|
||||
continue;
|
||||
} else {
|
||||
path_src = std::move(path_in_rsrc);
|
||||
path_in_rsrc.clear();
|
||||
}
|
||||
}
|
||||
|
||||
const auto new_vp = VendorProfile::from_ini(path_src, false);
|
||||
auto new_vp = VendorProfile::from_ini(path_src, false);
|
||||
bool found = false;
|
||||
if (new_vp.config_version == recommended->config_version) {
|
||||
updates.updates.emplace_back(std::move(path_src), std::move(bundle_path), *recommended);
|
||||
} else {
|
||||
found = true;
|
||||
} else if (! path_in_rsrc.empty() && fs::exists(path_in_rsrc)) {
|
||||
new_vp = VendorProfile::from_ini(path_in_rsrc, false);
|
||||
if (new_vp.config_version == recommended->config_version) {
|
||||
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(bundle_path), *recommended);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (! found)
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources")
|
||||
% idx.vendor()
|
||||
% recommended->config_version.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,10 +542,21 @@ bool PresetUpdater::config_update() const
|
|||
std::unordered_map<std::string, wxString> incompats_map;
|
||||
for (const auto &incompat : updates.incompats) {
|
||||
auto vendor = incompat.name();
|
||||
auto restrictions = wxString::Format(_(L("requires min. %s and max. %s")),
|
||||
incompat.version.min_slic3r_version.to_string(),
|
||||
incompat.version.max_slic3r_version.to_string()
|
||||
);
|
||||
|
||||
const auto min_slic3r = incompat.version.min_slic3r_version;
|
||||
const auto max_slic3r = incompat.version.max_slic3r_version;
|
||||
wxString restrictions;
|
||||
if (min_slic3r != Semver::zero() && max_slic3r != Semver::inf()) {
|
||||
restrictions = wxString::Format(_(L("requires min. %s and max. %s")),
|
||||
min_slic3r.to_string(),
|
||||
max_slic3r.to_string()
|
||||
);
|
||||
} else if (min_slic3r != Semver::zero()) {
|
||||
restrictions = wxString::Format(_(L("requires min. %s")), min_slic3r.to_string());
|
||||
} else {
|
||||
restrictions = wxString::Format(_(L("requires max. %s")), max_slic3r.to_string());
|
||||
}
|
||||
|
||||
incompats_map.emplace(std::make_pair(std::move(vendor), std::move(restrictions)));
|
||||
}
|
||||
|
||||
|
@ -545,9 +568,10 @@ bool PresetUpdater::config_update() const
|
|||
BOOST_LOG_TRIVIAL(info) << "User wants to re-configure...";
|
||||
p->perform_updates(std::move(updates));
|
||||
GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT);
|
||||
if (! wizard.run(GUI::get_preset_bundle(), this)) {
|
||||
if (! wizard.run(GUI::get_preset_bundle(), this)) {
|
||||
return false;
|
||||
}
|
||||
GUI::load_current_presets();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye...";
|
||||
return false;
|
||||
|
@ -577,7 +601,6 @@ bool PresetUpdater::config_update() const
|
|||
|
||||
// Reload global configuration
|
||||
auto *app_config = GUI::get_app_config();
|
||||
app_config->reset_selections();
|
||||
GUI::get_preset_bundle()->load_presets(*app_config);
|
||||
GUI::load_current_presets();
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue