Merge branch 'master' into lm_sla_gizmo_clipping_plane

This commit is contained in:
Lukas Matena 2019-04-10 13:43:02 +02:00
commit 678c513cb9
86 changed files with 36832 additions and 31114 deletions

View file

@ -18,10 +18,10 @@ wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), -
#ifdef __APPLE__
m_user_drawn_background = false;
#endif /*__APPLE__*/
Bind(wxEVT_PAINT, ([this](wxPaintEvent e) { repaint(); }));
Bind(wxEVT_LEFT_DOWN, ([this](wxMouseEvent event) { mouse_event(event); }));
Bind(wxEVT_MOTION, ([this](wxMouseEvent event) { mouse_event(event); }));
Bind(wxEVT_SIZE, ([this](wxSizeEvent e) { Refresh(); }));
Bind(wxEVT_PAINT, ([this](wxPaintEvent &/* e */) { repaint(); }));
Bind(wxEVT_LEFT_DOWN, ([this](wxMouseEvent &event) { mouse_event(event); }));
Bind(wxEVT_MOTION, ([this](wxMouseEvent &event) { mouse_event(event); }));
Bind(wxEVT_SIZE, ([this](wxSizeEvent & /* e */) { Refresh(); }));
}
void Bed_2D::repaint()
{

View file

@ -227,6 +227,12 @@ const float GLVolume::HOVER_COLOR[4] = { 0.4f, 0.9f, 0.1f, 1.0f };
const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
const float GLVolume::DISABLED_COLOR[4] = { 0.25f, 0.25f, 0.25f, 1.0f };
const float GLVolume::MODEL_COLOR[4][4] = {
{ 1.0f, 1.0f, 0.0f, 1.f },
{ 1.0f, 0.5f, 0.5f, 1.f },
{ 0.5f, 1.0f, 0.5f, 1.f },
{ 0.5f, 0.5f, 1.0f, 1.f }
};
const float GLVolume::SLA_SUPPORT_COLOR[4] = { 0.75f, 0.75f, 0.75f, 1.0f };
const float GLVolume::SLA_PAD_COLOR[4] = { 0.0f, 0.2f, 0.0f, 1.0f };
@ -568,19 +574,12 @@ int GLVolumeCollection::load_object_volume(
const std::string &color_by,
bool use_VBOs)
{
static float colors[4][4] = {
{ 1.0f, 1.0f, 0.0f, 1.f },
{ 1.0f, 0.5f, 0.5f, 1.f },
{ 0.5f, 1.0f, 0.5f, 1.f },
{ 0.5f, 0.5f, 1.0f, 1.f }
};
const ModelVolume *model_volume = model_object->volumes[volume_idx];
const int extruder_id = model_volume->extruder_id();
const ModelInstance *instance = model_object->instances[instance_idx];
const TriangleMesh& mesh = model_volume->mesh;
float color[4];
memcpy(color, colors[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
/* if (model_volume->is_support_blocker()) {
color[0] = 1.0f;
color[1] = 0.2f;
@ -595,10 +594,7 @@ int GLVolumeCollection::load_object_volume(
this->volumes.emplace_back(new GLVolume(color));
GLVolume &v = *this->volumes.back();
v.set_color_from_model_volume(model_volume);
if (use_VBOs)
v.indexed_vertex_array.load_mesh_full_shading(mesh);
else
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
v.bounding_box = v.indexed_vertex_array.bounding_box();
@ -640,14 +636,10 @@ void GLVolumeCollection::load_object_auxiliary(
// Convex hull is required for out of print bed detection.
TriangleMesh convex_hull = mesh.convex_hull_3d();
for (const std::pair<size_t, size_t> &instance_idx : instances) {
const ModelInstance &model_instance = *print_object->model_object()->instances[instance_idx.first];
const SLAPrintObject::Instance &print_instance = print_object->instances()[instance_idx.second];
const ModelInstance &model_instance = *print_object->model_object()->instances[instance_idx.first];
this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
GLVolume &v = *this->volumes.back();
if (use_VBOs)
v.indexed_vertex_array.load_mesh_full_shading(mesh);
else
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
v.bounding_box = v.indexed_vertex_array.bounding_box();
v.indexed_vertex_array.finalize_geometry(use_VBOs);
@ -718,14 +710,8 @@ int GLVolumeCollection::load_wipe_tower_preview(
this->volumes.emplace_back(new GLVolume(color));
GLVolume &v = *this->volumes.back();
if (use_VBOs)
v.indexed_vertex_array.load_mesh_full_shading(mesh);
else
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
v.bounding_box = v.indexed_vertex_array.bounding_box();
v.indexed_vertex_array.finalize_geometry(use_VBOs);
@ -1861,12 +1847,7 @@ bool GLArrow::on_init(bool useVBOs)
triangles.emplace_back(7, 13, 6);
m_useVBOs = useVBOs;
if (m_useVBOs)
m_volume.indexed_vertex_array.load_mesh_full_shading(TriangleMesh(vertices, triangles));
else
m_volume.indexed_vertex_array.load_mesh_flat_shading(TriangleMesh(vertices, triangles));
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles), useVBOs);
m_volume.finalize_geometry(m_useVBOs);
return true;
}
@ -1981,12 +1962,7 @@ bool GLCurvedArrow::on_init(bool useVBOs)
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
m_useVBOs = useVBOs;
if (m_useVBOs)
m_volume.indexed_vertex_array.load_mesh_full_shading(TriangleMesh(vertices, triangles));
else
m_volume.indexed_vertex_array.load_mesh_flat_shading(TriangleMesh(vertices, triangles));
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles), useVBOs);
m_volume.bounding_box = m_volume.indexed_vertex_array.bounding_box();
m_volume.finalize_geometry(m_useVBOs);
return true;
@ -2021,10 +1997,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
TriangleMesh mesh = model.mesh();
mesh.repair();
if (m_useVBOs)
m_volume.indexed_vertex_array.load_mesh_full_shading(mesh);
else
m_volume.indexed_vertex_array.load_mesh_flat_shading(mesh);
m_volume.indexed_vertex_array.load_mesh(mesh, useVBOs);
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
set_color(color, 4);

View file

@ -116,6 +116,7 @@ public:
void load_mesh_flat_shading(const TriangleMesh &mesh);
void load_mesh_full_shading(const TriangleMesh &mesh);
void load_mesh(const TriangleMesh &mesh, bool use_VBOs) { use_VBOs ? this->load_mesh_full_shading(mesh) : this->load_mesh_flat_shading(mesh); }
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
@ -228,6 +229,7 @@ public:
static const float OUTSIDE_COLOR[4];
static const float SELECTED_OUTSIDE_COLOR[4];
static const float DISABLED_COLOR[4];
static const float MODEL_COLOR[4][4];
static const float SLA_SUPPORT_COLOR[4];
static const float SLA_PAD_COLOR[4];

View file

@ -42,9 +42,7 @@ AboutDialog::AboutDialog()
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
// auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png"));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192));
hsizer->Add(logo, 1, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);

View file

@ -15,6 +15,7 @@
#include "nanosvg/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"
#include "GUI_App.hpp"
namespace Slic3r { namespace GUI {
@ -24,16 +25,25 @@ void BitmapCache::clear()
delete bitmap.second;
}
static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image)
static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image, float scale = 1.0f)
{
#ifdef BROKEN_ALPHA
wxMemoryOutputStream stream;
image.SaveFile(stream, wxBITMAP_TYPE_PNG);
wxStreamBuffer *buf = stream.GetOutputStreamBuffer();
return wxBitmap::NewFromPNGData(buf->GetBufferStart(), buf->GetBufferSize());
#else
#ifdef __APPLE__
// This is a c-tor native to Mac OS. We need to let the Mac OS wxBitmap implementation
// know that the image may already be scaled appropriately for Retina,
// and thereby that it's not supposed to upscale it.
// Contrary to intuition, the `scale` argument isn't "please scale this to such and such"
// but rather "the wxImage is sized for backing scale such and such".
return wxBitmap(std::move(image), -1, scale);
#else
return wxBitmap(std::move(image));
#endif
#endif
}
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height)
@ -162,7 +172,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
#endif
}
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data)
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale /* = 1.0f */)
{
wxImage image(width, height);
image.InitAlpha();
@ -175,7 +185,7 @@ wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned i
*rgb ++ = *raw_data ++;
*alpha ++ = *raw_data ++;
}
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), scale));
}
wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int width, unsigned int height)
@ -183,6 +193,7 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid
std::string bitmap_key = bitmap_name + ( height !=0 ?
"-h" + std::to_string(height) :
"-w" + std::to_string(width));
auto it = m_map.find(bitmap_key);
if (it != m_map.end())
return it->second;
@ -203,11 +214,15 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
}
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int target_width, unsigned int target_height)
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_width, unsigned target_height, float scale /* = 1.0f */)
{
std::string bitmap_key = bitmap_name + (target_height != 0 ?
"-h" + std::to_string(target_height) :
"-w" + std::to_string(target_width));
std::string bitmap_key = bitmap_name + ( target_height !=0 ?
"-h" + std::to_string(target_height) :
"-w" + std::to_string(target_width))
+ (scale != 1.0f ? "-s" + std::to_string(scale) : "");
target_height != 0 ? target_height *= scale : target_width *= scale;
auto it = m_map.find(bitmap_key);
if (it != m_map.end())
return it->second;
@ -216,12 +231,12 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int tar
if (image == nullptr)
return nullptr;
float scale = target_height != 0 ?
float svg_scale = target_height != 0 ?
(float)target_height / image->height : target_width != 0 ?
(float)target_width / image->width : 1;
int width = (int)(scale * image->width + 0.5f);
int height = (int)(scale * image->height + 0.5f);
int width = (int)(svg_scale * image->width + 0.5f);
int height = (int)(svg_scale * image->height + 0.5f);
int n_pixels = width * height;
if (n_pixels <= 0) {
::nsvgDelete(image);
@ -235,15 +250,18 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int tar
}
std::vector<unsigned char> data(n_pixels * 4, 0);
::nsvgRasterize(rast, image, 0, 0, scale, data.data(), width, height, width * 4);
::nsvgRasterize(rast, image, 0, 0, svg_scale, data.data(), width, height, width * 4);
::nsvgDeleteRasterizer(rast);
::nsvgDelete(image);
return this->insert_raw_rgba(bitmap_key, width, height, data.data());
return this->insert_raw_rgba(bitmap_key, width, height, data.data(), scale);
}
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency)
{
width = width * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f;
height = height * 0.1f * Slic3r::GUI::wxGetApp().em_unit() + 0.5f;
wxImage image(width, height);
image.InitAlpha();
unsigned char* imgdata = image.GetData();

View file

@ -29,12 +29,12 @@ public:
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3);
wxBitmap* insert(const std::string &name, const std::vector<wxBitmap> &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); }
wxBitmap* insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end);
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data);
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale = 1.0f);
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
wxBitmap* load_png(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, float scale = 1.0f);
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }

View file

@ -1893,6 +1893,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
size_t idx = 0;
const SLAPrint *sla_print = this->sla_print();
std::vector<double> shift_zs(m_model->objects.size(), 0);
double relative_correction_z = sla_print->relative_correction().z();
if (relative_correction_z <= EPSILON)
relative_correction_z = 1.;
for (const SLAPrintObject *print_object : sla_print->objects()) {
SLASupportState &state = sla_support_state[idx ++];
const ModelObject *model_object = print_object->model_object();
@ -1906,7 +1909,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
assert(it != sla_print->model().objects.end());
object_idx = it - sla_print->model().objects.begin();
// Cache the Z offset to be applied to all volumes with this object_idx.
shift_zs[object_idx] = print_object->get_current_elevation();
shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
// Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
// pairs of <instance_idx, print_instance_idx>
std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
@ -2219,9 +2222,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
//#endif /* __APPLE__ */
if ((evt.GetModifiers() & ctrlMask) != 0) {
switch (keyCode) {
#ifdef __APPLE__
case 'a':
case 'A':
#else /* __APPLE__ */
case WXK_CONTROL_A:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
break;
#ifdef __APPLE__
@ -2310,6 +2316,9 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
{
if (!m_initialized)
return;
// Ignore the wheel events if the middle button is pressed.
if (evt.MiddleIsDown())
return;
@ -2563,8 +2572,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_selection.remove(m_hover_volume_id);
else
{
bool add_as_single = !already_selected && !ctrl_down;
m_selection.add(m_hover_volume_id, add_as_single);
m_selection.add(m_hover_volume_id, !ctrl_down);
m_mouse.drag.move_requires_threshold = !already_selected;
if (already_selected)
m_mouse.set_move_start_threshold_position_2D_as_invalid();
@ -3293,8 +3301,9 @@ bool GLCanvas3D::_init_toolbar()
bool GLCanvas3D::_set_current()
{
if ((m_canvas != nullptr) && (m_context != nullptr))
if (_is_shown_on_screen() && (m_context != nullptr)) {
return m_canvas->SetCurrent(*m_context);
}
return false;
}
@ -5056,97 +5065,44 @@ void GLCanvas3D::_load_shells_sla()
// nothing to render, return
return;
auto add_volume = [this](const SLAPrintObject &object, const SLAPrintObject::Instance& instance,
const TriangleMesh &mesh, const float color[4], bool outside_printer_detection_enabled) {
m_volumes.volumes.emplace_back(new GLVolume(color));
GLVolume& v = *m_volumes.volumes.back();
v.indexed_vertex_array.load_mesh(mesh, m_use_VBOs);
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
v.composite_id.volume_id = -1;
v.set_instance_offset(unscale(instance.shift(0), instance.shift(1), 0));
v.set_instance_rotation(Vec3d(0.0, 0.0, (double)instance.rotation));
v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.);
};
// adds objects' volumes
int obj_idx = 0;
for (const SLAPrintObject* obj : print->objects())
{
if (!obj->is_step_done(slaposSliceSupports))
continue;
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
// selects only instances which were sliced
const ModelObject* model_obj = obj->model_object();
const std::vector<SLAPrintObject::Instance>& sla_instances = obj->instances();
std::vector<int> instances_model_idxs(sla_instances.size());
for (int i = 0; i < (int)sla_instances.size(); ++i)
{
instances_model_idxs[i] = (int)sla_instances[i].instance_id.id;
}
std::vector<int> sliced_instance_idxs;
for (int i = 0; i < (int)model_obj->instances.size(); ++i)
{
if (std::find(instances_model_idxs.begin(), instances_model_idxs.end(), (int)model_obj->instances[i]->id().id) != instances_model_idxs.end())
sliced_instance_idxs.push_back(i);
}
m_volumes.load_object(model_obj, obj_idx, sliced_instance_idxs, "object", m_use_VBOs && m_initialized);
for (const SLAPrintObject::Instance& instance : sla_instances)
{
Vec3d offset = unscale(instance.shift(0), instance.shift(1), 0);
Vec3d rotation(0.0, 0.0, (double)instance.rotation);
unsigned int partial_volumes_count = (unsigned int)m_volumes.volumes.size();
// add supports
if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
{
const TriangleMesh& mesh = obj->support_mesh();
m_volumes.volumes.emplace_back(new GLVolume(GLVolume::SLA_SUPPORT_COLOR));
GLVolume& v = *m_volumes.volumes.back();
if (m_use_VBOs)
v.indexed_vertex_array.load_mesh_full_shading(mesh);
else
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
v.shader_outside_printer_detection_enabled = true;
v.composite_id.volume_id = -1;
v.set_instance_offset(offset);
v.set_instance_rotation(rotation);
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
if (obj->is_step_done(slaposSliceSupports)) {
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
for (const SLAPrintObject::Instance& instance : obj->instances()) {
add_volume(*obj, instance, obj->transformed_mesh(), GLVolume::MODEL_COLOR[0], true);
// Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
// through the update_volumes_colors_by_extruder() call.
m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id();
m_volumes.volumes.back()->composite_id.volume_id = 0;
if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
add_volume(*obj, instance, obj->support_mesh(), GLVolume::SLA_SUPPORT_COLOR, true);
if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool))
add_volume(*obj, instance, obj->pad_mesh(), GLVolume::SLA_PAD_COLOR, true);
}
// add pad
if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool))
{
const TriangleMesh& mesh = obj->pad_mesh();
m_volumes.volumes.emplace_back(new GLVolume(GLVolume::SLA_PAD_COLOR));
GLVolume& v = *m_volumes.volumes.back();
if (m_use_VBOs)
v.indexed_vertex_array.load_mesh_full_shading(mesh);
else
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
v.shader_outside_printer_detection_enabled = false;
v.composite_id.volume_id = -1;
v.set_instance_offset(offset);
v.set_instance_rotation(rotation);
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
}
// finalize volumes and sends geometry to gpu
for (unsigned int i = partial_volumes_count; i < m_volumes.volumes.size(); ++i)
{
double shift_z = obj->get_current_elevation();
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
GLVolume& v = *m_volumes.volumes[i];
// finalize volumes and sends geometry to gpu
v.bounding_box = v.indexed_vertex_array.bounding_box();
v.indexed_vertex_array.finalize_geometry(m_use_VBOs);
// apply shift z
v.set_sla_shift_z(shift_z);
}
++obj_idx;
}
// apply shift z
double shift_z = obj->get_current_elevation();
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
{
m_volumes.volumes[i]->set_sla_shift_z(shift_z);
}
}
update_volumes_colors_by_extruder();
#else
this->reload_scene(true, true);

View file

@ -19,6 +19,8 @@
#include <wx/wupdlock.h>
#include <wx/filefn.h>
#include <wx/sysopt.h>
#include <wx/msgdlg.h>
#include <wx/log.h>
#include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp"
@ -76,6 +78,52 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
static void register_dpi_event()
{
#ifdef WIN32
enum { WM_DPICHANGED_ = 0x02e0 };
wxWindow::MSWRegisterMessageHandler(WM_DPICHANGED_, [](wxWindow *win, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) {
const int dpi = wParam & 0xffff;
const auto rect = reinterpret_cast<PRECT>(lParam);
const wxRect wxrect(wxPoint(rect->top, rect->left), wxPoint(rect->bottom, rect->right));
DpiChangedEvent evt(EVT_DPI_CHANGED, dpi, wxrect);
win->GetEventHandler()->AddPendingEvent(evt);
return true;
});
#endif
}
static void generic_exception_handle()
{
// Note: Some wxWidgets APIs use wxLogError() to report errors, eg. wxImage
// - see https://docs.wxwidgets.org/3.1/classwx_image.html#aa249e657259fe6518d68a5208b9043d0
//
// wxLogError typically goes around exception handling and display an error dialog some time
// after an error is logged even if exception handling and OnExceptionInMainLoop() take place.
// This is why we use wxLogError() here as well instead of a custom dialog, because it accumulates
// errors if multiple have been collected and displays just one error message for all of them.
// Otherwise we would get multiple error messages for one missing png, for example.
//
// If a custom error message window (or some other solution) were to be used, it would be necessary
// to turn off wxLogError() usage in wx APIs, most notably in wxImage
// - see https://docs.wxwidgets.org/trunk/classwx_image.html#aa32e5d3507cc0f8c3330135bc0befc6a
try {
throw;
} catch (const std::exception &ex) {
wxLogError("Internal error: %s", ex.what());
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
throw;
} catch (...) {
wxLogError("Unknown internal error");
BOOST_LOG_TRIVIAL(error) << "Uncaught exception: Unknown error";
}
}
IMPLEMENT_APP(GUI_App)
GUI_App::GUI_App()
@ -85,6 +133,16 @@ GUI_App::GUI_App()
{}
bool GUI_App::OnInit()
{
try {
return on_init_inner();
} catch (...) {
generic_exception_handle();
return false;
}
}
bool GUI_App::on_init_inner()
{
// Verify resources path
const wxString resources_dir = from_u8(Slic3r::resources_dir());
@ -114,13 +172,7 @@ bool GUI_App::OnInit()
// just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
// supplied as argument to --datadir; in that case we should still run the wizard
try {
preset_bundle->setup_directories();
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
// Exit the application.
return false;
}
preset_bundle->setup_directories();
app_conf_exists = app_config->exists();
// load settings
@ -143,11 +195,13 @@ bool GUI_App::OnInit()
// Suppress the '- default -' presets.
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
try {
preset_bundle->load_presets(*app_config);
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
}
try {
preset_bundle->load_presets(*app_config);
} catch (const std::exception &ex) {
show_error(nullptr, from_u8(ex.what()));
}
register_dpi_event();
// Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
@ -164,8 +218,8 @@ bool GUI_App::OnInit()
Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
{
if (! plater_)
return;
if (! plater_)
return;
if (app_config->dirty() && app_config->get("autosave") == "1")
app_config->save();
@ -187,7 +241,7 @@ bool GUI_App::OnInit()
mainframe->Close();
}
} catch (const std::exception &ex) {
show_error(nullptr, ex.what());
show_error(nullptr, from_u8(ex.what()));
}
CallAfter([this] {
@ -732,18 +786,7 @@ void GUI_App::load_current_presets()
bool GUI_App::OnExceptionInMainLoop()
{
try {
throw;
} catch (const std::exception &ex) {
const std::string error = (boost::format("Uncaught exception: %1%") % ex.what()).str();
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
} catch (...) {
const char *error = "Uncaught exception: Unknown error";
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
}
generic_exception_handle();
return false;
}

View file

@ -169,6 +169,7 @@ public:
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
private:
bool on_init_inner();
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
void window_pos_sanitize(wxTopLevelWindow* window);

View file

@ -62,18 +62,18 @@ ObjectList::ObjectList(wxWindow* parent) :
// Fill CATEGORY_ICON
{
// ptFFF
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers.png"); // wxBitmap(from_u8(var("layers.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill.png"); // wxBitmap(from_u8(var("infill.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("building.png"); // wxBitmap(from_u8(var("building.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time.png"); // wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel.png"); // wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel.png"); // wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG);
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("box.png"); // wxBitmap(from_u8(var("box.png")), wxBITMAP_TYPE_PNG);
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time.png"); // wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wand.png"); // wxBitmap(from_u8(var("wand.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(this, "layers");
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(this, "infill");
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(this, "support");
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(this, "time");
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(this, "funnel");
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(this, "funnel");
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(this, "skirt+brim");
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(this, "time");
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(this, "wrench");
// ptSLA
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("building.png"); // wxBitmap(from_u8(var("building.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("brick.png"); // wxBitmap(from_u8(var("brick.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(this, "sla_supports");
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(this, "brick.png");
}
// create control
@ -88,6 +88,10 @@ ObjectList::ObjectList(wxWindow* parent) :
// before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object
// manipulator cache with the following call to selection_changed()
wxGetApp().obj_manipul()->emulate_kill_focus();
#else
// To avoid selection update from SetSelection() and UnselectAll() under osx
if (m_prevent_list_events)
return;
#endif // __APPLE__
/* For multiple selection with pressed SHIFT,
@ -137,6 +141,8 @@ ObjectList::ObjectList(wxWindow* parent) :
#ifdef __WXOSX__
Bind(wxEVT_KEY_DOWN, &ObjectList::OnChar, this);
#endif //__WXOSX__
Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { this->EnsureVisible(this->GetCurrentItem()); e.Skip(); }));
}
ObjectList::~ObjectList()
@ -386,17 +392,10 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const
void ObjectList::init_icons()
{
// m_bmp_modifiermesh = wxBitmap(from_u8(var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
// m_bmp_solidmesh = wxBitmap(from_u8(var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
// m_bmp_support_enforcer = wxBitmap(from_u8(var("support_enforcer_.png")), wxBITMAP_TYPE_PNG);
// m_bmp_support_blocker = wxBitmap(from_u8(var("support_blocker_.png")), wxBITMAP_TYPE_PNG);
m_bmp_modifiermesh = create_scaled_bitmap("lambda.png");
m_bmp_solidmesh = create_scaled_bitmap("object.png");
m_bmp_support_enforcer = create_scaled_bitmap("support_enforcer_.png");
m_bmp_support_blocker = create_scaled_bitmap("support_blocker_.png");
m_bmp_modifiermesh = create_scaled_bitmap(this, "lambda.png");
m_bmp_solidmesh = create_scaled_bitmap(this, "object.png");
m_bmp_support_enforcer = create_scaled_bitmap(this, "support_enforcer_.png");
m_bmp_support_blocker = create_scaled_bitmap(this, "support_blocker_.png");
m_bmp_vector.reserve(4); // bitmaps for different types of parts
@ -407,16 +406,13 @@ void ObjectList::init_icons()
m_objects_model->SetVolumeBitmaps(m_bmp_vector);
// init icon for manifold warning
// m_bmp_manifold_warning = wxBitmap(from_u8(var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
m_bmp_manifold_warning = create_scaled_bitmap("exclamation_mark_.png");
m_bmp_manifold_warning = create_scaled_bitmap(this, "exclamation_mark_.png");
// init bitmap for "Split to sub-objects" context menu
// m_bmp_split = wxBitmap(from_u8(var("split.png")), wxBITMAP_TYPE_PNG);
m_bmp_split = create_scaled_bitmap("split.png");
m_bmp_split = create_scaled_bitmap(this, "split_parts");
// init bitmap for "Add Settings" context menu
// m_bmp_cog = wxBitmap(from_u8(var("cog.png")), wxBITMAP_TYPE_PNG);
m_bmp_cog = create_scaled_bitmap("cog.png");
m_bmp_cog = create_scaled_bitmap(this, "cog");
}
@ -1983,7 +1979,7 @@ void ObjectList::update_selections()
if (selection.is_single_full_object() &&
m_objects_model->GetIdByItem(m_objects_model->GetParent(item)) == selection.get_object_idx())
return;
if (selection.is_single_volume() || selection.is_modifier()) {
if (selection.is_single_volume() || selection.is_any_modifier()) {
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
return;
@ -2018,7 +2014,7 @@ void ObjectList::update_selections()
}
}
}
else if (selection.is_single_volume() || selection.is_modifier() || selection.is_multiple_volume())
else if (selection.is_any_volume() || selection.is_any_modifier())
{
for (auto idx : selection.get_volume_idxs()) {
const auto gl_vol = selection.get_volume(idx);
@ -2077,23 +2073,8 @@ void ObjectList::update_selections()
select_items(sels);
/* Because of ScrollLines() and GetItemRect() functions are implemented
* only for GENERIC DataViewCtrl in current version of wxWidgets,
* use this part of code only for MSW
*/
#if defined(wxUSE_GENERICDATAVIEWCTRL)
// Scroll selected Item in the middle of an object list
if (GetSelection()) {
const wxRect& sel_rc = GetItemRect(GetSelection());
const wxRect& main_rc = GetClientRect();
if (sel_rc.GetBottom() <= main_rc.GetTop()+sel_rc.height ||
sel_rc.GetTop() >= main_rc.GetBottom() )
{
const wxRect& top_rc = GetItemRect(GetTopItem());
ScrollLines(int((sel_rc.y - top_rc.y) / top_rc.GetHeight()) - 0.5*GetCountPerPage());
}
}
#endif
this->EnsureVisible(this->GetCurrentItem());
}
void ObjectList::update_selections_on_canvas()
@ -2139,6 +2120,7 @@ void ObjectList::update_selections_on_canvas()
add_to_selection(item, selection, instance_idx, true);
wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->canvas3D()->render();
return;
}

View file

@ -92,8 +92,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
else if (option_name == "Size") {
line.near_label_widget = [this](wxWindow* parent) {
return new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition,
// wxBitmap(from_u8(var("one_layer_lock_on.png")), wxBITMAP_TYPE_PNG).GetSize());
create_scaled_bitmap("one_layer_lock_on.png").GetSize());
create_scaled_bitmap(m_parent, "one_layer_lock_on.png").GetSize());
};
}

View file

@ -77,8 +77,7 @@ void ObjectSettings::update_settings_list()
{
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
// auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG),
auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap("colorchange_delete_on.png"),
auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap(m_parent, "cross"/*"colorchange_delete_on.png"*/),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
#ifdef __WXMSW__
btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));

View file

@ -4,9 +4,14 @@
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#ifdef _WIN32
#include <Windows.h>
#endif
#include <wx/toplevel.h>
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/dcclient.h>
#include "libslic3r/Config.hpp"
@ -48,6 +53,64 @@ void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback)
#endif
}
wxDEFINE_EVENT(EVT_DPI_CHANGED, DpiChangedEvent);
#ifdef _WIN32
template<class F> typename F::FN winapi_get_function(const wchar_t *dll, const char *fn_name) {
static HINSTANCE dll_handle = LoadLibraryExW(dll, nullptr, 0);
if (dll_handle == nullptr) { return nullptr; }
return (F::FN)GetProcAddress(dll_handle, fn_name);
}
#endif
int get_dpi_for_window(wxWindow *window)
{
#ifdef _WIN32
enum MONITOR_DPI_TYPE_ {
// This enum is inlined here to avoid build-time dependency
MDT_EFFECTIVE_DPI_ = 0,
MDT_ANGULAR_DPI_ = 1,
MDT_RAW_DPI_ = 2,
MDT_DEFAULT_ = MDT_EFFECTIVE_DPI_,
};
// Need strong types for winapi_get_function() to work
struct GetDpiForWindow_t { typedef HRESULT (WINAPI *FN)(HWND hwnd); };
struct GetDpiForMonitor_t { typedef HRESULT (WINAPI *FN)(HMONITOR hmonitor, MONITOR_DPI_TYPE_ dpiType, UINT *dpiX, UINT *dpiY); };
static auto GetDpiForWindow_fn = winapi_get_function<GetDpiForWindow_t>(L"User32.dll", "GetDpiForWindow");
static auto GetDpiForMonitor_fn = winapi_get_function<GetDpiForMonitor_t>(L"Shcore.dll", "GetDpiForMonitor");
const HWND hwnd = window->GetHandle();
if (GetDpiForWindow_fn != nullptr) {
// We're on Windows 10, we have per-screen DPI settings
return GetDpiForWindow_fn(hwnd);
} else if (GetDpiForMonitor_fn != nullptr) {
// We're on Windows 8.1, we have per-system DPI
// Note: MonitorFromWindow() is available on all Windows.
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
UINT dpiX;
UINT dpiY;
return GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI_, &dpiX, &dpiY) == S_OK ? dpiX : DPI_DEFAULT;
} else {
// We're on Windows earlier than 8.1, use DC
const HDC hdc = GetDC(hwnd);
if (hdc == NULL) { return DPI_DEFAULT; }
return GetDeviceCaps(hdc, LOGPIXELSX);
}
#elif defined __linux__
// TODO
return DPI_DEFAULT;
#elif defined __APPLE__
// TODO
return DPI_DEFAULT;
#endif
}
CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
: wxPanel(parent, wxID_ANY)

View file

@ -8,10 +8,13 @@
#include <boost/optional.hpp>
#include <wx/frame.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/filedlg.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
#include <wx/dcclient.h>
#include <wx/debug.h>
class wxCheckBox;
@ -27,6 +30,68 @@ wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
enum { DPI_DEFAULT = 96 };
int get_dpi_for_window(wxWindow *window);
struct DpiChangedEvent : public wxEvent {
int dpi;
wxRect rect;
DpiChangedEvent(wxEventType eventType, int dpi, wxRect rect)
: wxEvent(0, eventType), dpi(dpi), rect(rect)
{}
virtual wxEvent *Clone() const
{
return new DpiChangedEvent(*this);
}
};
wxDECLARE_EVENT(EVT_DPI_CHANGED, DpiChangedEvent);
template<class P> class DPIAware : public P
{
public:
DPIAware(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition,
const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)
: P(parent, id, title, pos, size, style, name)
{
m_scale_factor = (float)get_dpi_for_window(this) / (float)DPI_DEFAULT;
recalc_font();
this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) {
m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;
on_dpi_changed(evt.rect);
});
}
virtual ~DPIAware() {}
float scale_factor() const { return m_scale_factor; }
int em_unit() const { return m_em_unit; }
int font_size() const { return m_font_size; }
protected:
virtual void on_dpi_changed(const wxRect &suggested_rect) = 0;
private:
int m_scale_factor;
int m_em_unit;
int m_font_size;
void recalc_font()
{
wxClientDC dc(this);
const auto metrics = dc.GetFontMetrics();
m_font_size = metrics.height;
m_em_unit = metrics.averageWidth;
}
};
typedef DPIAware<wxFrame> DPIFrame;
typedef DPIAware<wxDialog> DPIDialog;
class EventGuard
{

View file

@ -48,11 +48,9 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
{
if (selection.is_empty()) {
m_model_object = nullptr;
m_old_model_object = nullptr;
return;
}
m_old_model_object = m_model_object;
m_model_object = model_object;
m_active_instance = selection.get_instance_idx();
@ -67,9 +65,6 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S
editing_mode_reload_cache();
}
if (m_model_object != m_old_model_object)
m_editing_mode = false;
if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified)
get_data_from_backend();
@ -158,11 +153,16 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection, const
void GLGizmoSlaSupports::render_selection_rectangle() const
{
if (!m_selection_rectangle_active)
if (m_selection_rectangle_status == srOff)
return;
glsafe(::glLineWidth(1.5f));
float render_color[3] = {1.f, 0.f, 0.f};
float render_color[3] = {0.f, 1.f, 0.f};
if (m_selection_rectangle_status == srDeselect) {
render_color[0] = 1.f;
render_color[1] = 0.3f;
render_color[2] = 0.3f;
}
glsafe(::glColor3fv(render_color));
glsafe(::glPushAttrib(GL_TRANSFORM_BIT)); // remember current MatrixMode
@ -317,7 +317,7 @@ bool GLGizmoSlaSupports::is_point_clipped(const Vec3d& point, const Vec3d& direc
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
{
return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty())
&& ((m_model_object != m_old_model_object) || m_V.size()==0);
&& ((m_model_object->id() != m_current_mesh_model_id) || m_V.size()==0);
}
void GLGizmoSlaSupports::update_mesh()
@ -339,6 +339,8 @@ void GLGizmoSlaSupports::update_mesh()
F(i, 1) = 3*i+1;
F(i, 2) = 3*i+2;
}
m_current_mesh_model_id = m_model_object->id();
m_editing_mode = false;
m_AABB = igl::AABB<Eigen::MatrixXf,3>();
m_AABB.init(m_V, m_F);
@ -420,31 +422,35 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
// concludes that the event was not intended for it, it should return false.
bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
{
if (m_editing_mode) {
// left down - show the selection rectangle:
if (action == SLAGizmoEventType::LeftDown && shift_down) {
// left down with shift - show the selection rectangle:
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
if (m_hover_id == -1) {
m_selection_rectangle_active = true;
m_selection_rectangle_start_corner = mouse_position;
m_selection_rectangle_end_corner = mouse_position;
m_canvas_width = m_parent.get_canvas_size().get_width();
m_canvas_height = m_parent.get_canvas_size().get_height();
if (shift_down || alt_down) {
m_selection_rectangle_status = shift_down ? srSelect : srDeselect;
m_selection_rectangle_start_corner = mouse_position;
m_selection_rectangle_end_corner = mouse_position;
m_canvas_width = m_parent.get_canvas_size().get_width();
m_canvas_height = m_parent.get_canvas_size().get_height();
}
}
else {
if (m_editing_mode_cache[m_hover_id].selected)
unselect_point(m_hover_id);
else
select_point(m_hover_id);
else {
if (!alt_down)
select_point(m_hover_id);
}
}
return true;
}
// left down without selection rectangle - place point on the mesh:
if (action == SLAGizmoEventType::LeftDown && !m_selection_rectangle_active && !shift_down) {
if (action == SLAGizmoEventType::LeftDown && m_selection_rectangle_status == srOff && !shift_down) {
// If any point is in hover state, this should initiate its move - return control back to GLCanvas:
if (m_hover_id != -1)
return false;
@ -469,7 +475,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
}
// left up with selection rectangle - select points inside the rectangle:
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) && m_selection_rectangle_active) {
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp || action == SLAGizmoEventType::AltUp) && m_selection_rectangle_status != srOff) {
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
const Camera& camera = m_parent.get_camera();
const std::array<int, 4>& viewport = camera.get_viewport();
@ -537,11 +543,15 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
is_obscured = true;
}
if (!is_obscured)
select_point(i);
if (!is_obscured) {
if (m_selection_rectangle_status == srDeselect)
unselect_point(i);
else
select_point(i);
}
}
}
m_selection_rectangle_active = false;
m_selection_rectangle_status = srOff;
return true;
}
@ -559,8 +569,9 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
return true; // point has been placed and the button not released yet
// this prevents GLCanvas from starting scene rotation
if (m_selection_rectangle_active) {
if (m_selection_rectangle_status != srOff) {
m_selection_rectangle_end_corner = mouse_position;
m_selection_rectangle_status = shift_down ? srSelect : srDeselect;
return true;
}
@ -923,41 +934,44 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state()
{
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
if (is_mesh_update_necessary())
update_mesh();
if (is_mesh_update_necessary())
update_mesh();
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
// we'll now reload support points:
if (m_model_object)
editing_mode_reload_cache();
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
m_parent.toggle_model_objects_visibility(false);
if (m_model_object)
m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance);
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
// Set default head diameter from config.
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
}
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
m_clipping_plane_distance = 0.f;
}
m_old_state = m_state;
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
wxGetApp().CallAfter([this]() {
// Following is called through CallAfter, because otherwise there was a problem
// on OSX with the wxMessageDialog being shown several times when clicked into.
if (m_model_object) {
if (m_unsaved_changes) {
wxMessageDialog dlg(GUI::wxGetApp().mainframe, _(L("Do you want to save your manually edited support points ?\n")),
_(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES)
editing_mode_apply_changes();
else
editing_mode_discard_changes();
}
}
m_parent.toggle_model_objects_visibility(true);
m_editing_mode = false; // so it is not active next time the gizmo opens
m_editing_mode_cache.clear();
m_clipping_plane_distance = 0.f;
});
}
m_old_state = m_state;
}

View file

@ -24,7 +24,7 @@ class GLGizmoSlaSupports : public GLGizmoBase
{
private:
ModelObject* m_model_object = nullptr;
ModelObject* m_old_model_object = nullptr;
ModelID m_current_mesh_model_id = 0;
int m_active_instance = -1;
float m_active_instance_bb_radius; // to cache the bb
mutable float m_z_shift = 0.f;
@ -57,7 +57,7 @@ public:
#endif // ENABLE_SVG_ICONS
virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
void delete_selected_points(bool force = false);
ClippingPlane get_sla_clipping_plane() const;
@ -85,7 +85,12 @@ private:
mutable float m_old_clipping_plane_distance = 0.f;
mutable Vec3d m_old_direction_to_camera;
bool m_selection_rectangle_active = false;
enum SelectionRectangleStatus {
srOff = 0,
srSelect = 1,
srDeselect = 2
}m_selection_rectangle_status = srOff;
Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner;
bool m_wait_for_up_event = false;

View file

@ -10,6 +10,7 @@ enum class SLAGizmoEventType {
Delete,
SelectAll,
ShiftUp,
AltUp,
ApplyChanges,
DiscardChanges,
AutomaticGeneration,

View file

@ -455,14 +455,14 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Sele
}
// Returns true if the gizmo used the event to do something, false otherwise.
bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
{
if (!m_enabled)
return false;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end())
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down);
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
return false;
}
@ -559,7 +559,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
if (evt.LeftDown())
{
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown()))
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
// the gizmo got the event and took some action, there is no need to do anything more
processed = true;
else if (!selection.is_empty() && grabber_contains_mouse())
@ -586,7 +586,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
else if (evt.Dragging() && (canvas.get_move_volume_id() != -1) && (m_current == SlaSupports))
// don't allow dragging objects with the Sla gizmo on
processed = true;
else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown()))
else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
{
// the gizmo got the event and took some action, no need to do anything more here
canvas.set_as_dirty();
@ -673,7 +673,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
{
// in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither
// object moving or selecting is suppressed in that case
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown());
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
processed = true;
}
else if (evt.LeftUp() && (m_current == Flatten) && ((canvas.get_hover_volume_id() != -1) || grabber_contains_mouse()))
@ -726,7 +726,12 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
{
switch (keyCode)
{
#ifdef __APPLE__
case 'a':
case 'A':
#else /* __APPLE__ */
case WXK_CONTROL_A:
#endif /* __APPLE__ */
{
// Sla gizmo selects all support points
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::SelectAll))
@ -814,6 +819,10 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
if ((m_current == SlaSupports) && (keyCode == WXK_SHIFT) && gizmo_event(SLAGizmoEventType::ShiftUp))
// shift has been just released - SLA gizmo might want to close rectangular selection.
processed = true;
if ((m_current == SlaSupports) && (keyCode == WXK_ALT) && gizmo_event(SLAGizmoEventType::AltUp))
// alt has been just released - SLA gizmo might want to close rectangular selection.
processed = true;
}
if (processed)

View file

@ -146,7 +146,7 @@ public:
void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
ClippingPlane get_sla_clipping_plane() const;
void render_current_gizmo(const Selection& selection) const;

View file

@ -17,8 +17,7 @@ KBShortcutsDialog::KBShortcutsDialog()
auto main_sizer = new wxBoxSizer(wxVERTICAL);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_32px.png")), wxBITMAP_TYPE_PNG);
const wxBitmap logo_bmp = create_scaled_bitmap("Slic3r_32px.png");
const wxBitmap logo_bmp = create_scaled_bitmap(this, "Slic3r_32px.png", 32);
// fonts
wxFont head_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
@ -120,7 +119,7 @@ void KBShortcutsDialog::fill_shortcuts()
main_shortcuts.push_back(Shortcut("+" ,L("Add Instance to selected object ")));
main_shortcuts.push_back(Shortcut("-" ,L("Remove Instance from selected object")));
main_shortcuts.push_back(Shortcut("?" ,L("Show keyboard shortcuts list")));
main_shortcuts.push_back(Shortcut("Shift+LeftMouse", L("Select multiple object/Move multiple object")));
main_shortcuts.push_back(Shortcut(ctrl+"LeftMouse" ,L("Select multiple object/Move multiple object")));
m_full_shortcuts.push_back(std::make_pair( _(L("Main Shortcuts")), std::make_pair(main_shortcuts, 0) ));

View file

@ -32,7 +32,7 @@ namespace Slic3r {
namespace GUI {
MainFrame::MainFrame() :
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
{
// Load the icon either from the exe, or from the ico file.
@ -56,9 +56,13 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
// initialize default width_unit according to the width of the one symbol ("x") of the current system font
const wxSize size = GetTextExtent("m");
// wxGetApp().set_em_unit(size.x-1);
wxGetApp().set_em_unit(std::max<size_t>(10, size.x - 1));
/* Load default preset bitmaps before a tabpanel initialization,
* but after filling of an em_unit value
*/
wxGetApp().preset_bundle->load_default_preset_bitmaps(this);
// initialize tabpanel and menubar
init_tabpanel();
init_menubar();
@ -252,6 +256,11 @@ bool MainFrame::can_delete_all() const
return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false;
}
void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
{
// TODO
}
void MainFrame::init_menubar()
{
#ifdef __APPLE__
@ -264,9 +273,9 @@ void MainFrame::init_menubar()
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png");
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png");
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "save");
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png");
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "save");
fileMenu->AppendSeparator();
@ -388,11 +397,11 @@ void MainFrame::init_menubar()
windowMenu->AppendSeparator();
}
append_menu_item(windowMenu, wxID_HIGHEST + 2, _(L("P&rint Settings Tab")) + "\tCtrl+2", _(L("Show the print settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog.png");
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog");
append_menu_item(windowMenu, wxID_HIGHEST + 3, _(L("&Filament Settings Tab")) + "\tCtrl+3", _(L("Show the filament settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool.png");
append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")),
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer_empty.png");
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer");
if (m_plater) {
windowMenu->AppendSeparator();
wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")),

View file

@ -9,6 +9,7 @@
#include <string>
#include <map>
#include "GUI_Utils.hpp"
#include "Plater.hpp"
#include "Event.hpp"
@ -40,7 +41,7 @@ struct PresetTab {
PrinterTechnology technology;
};
class MainFrame : public wxFrame
class MainFrame : public DPIFrame
{
bool m_loaded {false};
@ -68,6 +69,9 @@ class MainFrame : public wxFrame
bool can_delete() const;
bool can_delete_all() const;
protected:
virtual void on_dpi_changed(const wxRect &suggested_rect);
public:
MainFrame();
~MainFrame() {}

View file

@ -23,15 +23,11 @@ namespace Slic3r {
namespace GUI {
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id) :
MsgDialog(parent, title, headline, create_scaled_bitmap("Slic3r_192px.png"), button_id)
{}
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) :
wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)),
content_sizer(new wxBoxSizer(wxVERTICAL)),
btn_sizer(new wxBoxSizer(wxHORIZONTAL))
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id, wxBitmap bitmap)
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
, boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT))
, content_sizer(new wxBoxSizer(wxVERTICAL))
, btn_sizer(new wxBoxSizer(wxHORIZONTAL))
{
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
@ -54,7 +50,11 @@ wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DI
rightsizer->Add(btn_sizer, 0, wxALIGN_RIGHT);
auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(bitmap));
if (! bitmap.IsOk()) {
bitmap = create_scaled_bitmap(this, "Slic3r_192px.png", 192);
}
logo = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
topsizer->Add(logo, 0, wxALL, BORDER);
topsizer->Add(rightsizer, 1, wxALL | wxEXPAND, BORDER);
@ -69,7 +69,6 @@ MsgDialog::~MsgDialog() {}
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
: MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")),
create_scaled_bitmap("Slic3r_192px_grayscale.png"),
wxID_NONE)
, msg(msg)
{
@ -97,6 +96,8 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
btn_ok->SetFocus();
btn_sizer->Add(btn_ok, 0, wxRIGHT, HORIZ_SPACING);
logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192));
SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit()));
Fit();
}

View file

@ -12,6 +12,7 @@
class wxBoxSizer;
class wxCheckBox;
class wxStaticBitmap;
namespace Slic3r {
@ -40,12 +41,12 @@ protected:
};
// button_id is an id of a button that can be added by default, use wxID_NONE to disable
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK);
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id = wxID_OK);
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK, wxBitmap bitmap = wxNullBitmap);
wxFont boldfont;
wxBoxSizer *content_sizer;
wxBoxSizer *btn_sizer;
wxStaticBitmap *logo;
};

View file

@ -286,7 +286,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
#ifdef __WINDOWS__
edit_btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif
edit_btn->SetBitmap(create_scaled_bitmap("cog.png"));
edit_btn->SetBitmap(create_scaled_bitmap(this, "cog"));
edit_btn->SetToolTip(_(L("Click to edit preset")));
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
@ -747,6 +747,7 @@ Sidebar::Sidebar(Plater *parent)
p->plater->export_gcode();
else
p->plater->reslice();
p->plater->select_view_3D("Preview");
});
p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); });
}
@ -2288,20 +2289,14 @@ unsigned int Plater::priv::update_background_process(bool force_validation)
this->sidebar->show_sliced_info_sizer(false);
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
// Otherwise they will be just refreshed.
switch (this->printer_technology) {
case ptFFF:
if (this->preview != nullptr)
// If the preview is not visible, the following line just invalidates the preview,
// but the G-code paths are calculated first once the preview is made visible.
this->preview->reload_print();
// We also need to reload 3D scene because of the wipe tower preview box
if (this->config->opt_bool("wipe_tower"))
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
break;
case ptSLA:
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
break;
}
if (this->preview != nullptr)
// If the preview is not visible, the following line just invalidates the preview,
// but the G-code paths or SLA preview are calculated first once the preview is made visible.
this->preview->reload_print();
// In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
// In SLA mode, we need to reload the 3D scene every time to show the support structures.
if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower")))
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
}
if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! this->background_process.empty()) {
@ -2603,25 +2598,21 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
this->statusbar()->set_progress(evt.status.percent);
this->statusbar()->set_status_text(_(L(evt.status.text)) + wxString::FromUTF8(""));
}
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SCENE) {
if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE || PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) {
switch (this->printer_technology) {
case ptFFF:
this->update_fff_scene();
break;
case ptSLA:
// If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
if (view3D->is_dragging())
delayed_scene_refresh = true;
else
this->update_sla_scene();
break;
}
}
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS) {
// Update SLA gizmo (reload_scene calls update_gizmos_data)
q->canvas3D()->reload_scene(true);
}
if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
// Update the SLA preview
} else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
// Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
this->preview->reload_print();
}
}
@ -2829,15 +2820,15 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
wxMenuItem* item_delete = nullptr;
if (is_part) {
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
[this](wxCommandEvent&) { q->remove_selected(); }, "remove");
sidebar->obj_list()->append_menu_item_export_stl(menu);
}
else {
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")),
[this](wxCommandEvent&) { q->increase_instances(); }, "add.png");
[this](wxCommandEvent&) { q->increase_instances(); }, "instance_add");
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")),
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
[this](wxCommandEvent&) { q->decrease_instances(); }, "instance_remove");
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
@ -2847,7 +2838,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
[this](wxCommandEvent&) { q->remove_selected(); }, "remove");
menu->AppendSeparator();
wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu);
@ -2902,11 +2893,11 @@ bool Plater::priv::complit_init_object_menu()
return false;
wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")),
[this](wxCommandEvent&) { split_object(); }, "shape_ungroup_o.png", &object_menu);
[this](wxCommandEvent&) { split_object(); }, "split_objects.png", &object_menu);
wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")),
[this](wxCommandEvent&) { split_volume(); }, "shape_ungroup_p.png", &object_menu);
[this](wxCommandEvent&) { split_volume(); }, "split_parts.png", &object_menu);
wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png");
wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object"))/*, "shape_ungroup.png"*/);
object_menu.AppendSeparator();
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
@ -3051,7 +3042,7 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
bool Plater::priv::can_delete() const
{
return !get_selection().is_empty();
return !get_selection().is_empty() && !get_selection().is_wipe_tower();
}
bool Plater::priv::can_delete_all() const
@ -3302,7 +3293,7 @@ void Plater::set_number_of_copies(/*size_t num*/)
bool Plater::is_selection_empty() const
{
return p->get_selection().is_empty();
return p->get_selection().is_empty() || p->get_selection().is_wipe_tower();
}
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)

View file

@ -4,6 +4,7 @@
#include "AppConfig.hpp"
#include "BitmapCache.hpp"
#include "I18N.hpp"
#include "wxExtensions.hpp"
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
@ -485,7 +486,7 @@ const std::vector<std::string>& Preset::sla_material_options()
s_opts = {
"initial_layer_height",
"exposure_time", "initial_exposure_time",
"material_correction_printing", "material_correction_curing",
"material_correction",
"material_notes",
"default_sla_material_profile",
"compatible_prints", "compatible_prints_condition",
@ -505,7 +506,9 @@ const std::vector<std::string>& Preset::sla_printer_options()
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
"display_orientation",
"fast_tilt_time", "slow_tilt_time", "area_fill",
"printer_correction",
"relative_correction",
"absolute_correction",
"gamma_correction",
"print_host", "printhost_apikey", "printhost_cafile",
"printer_notes",
"inherits"
@ -796,14 +799,14 @@ bool PresetCollection::delete_current_preset()
return true;
}
bool PresetCollection::load_bitmap_default(const std::string &file_name)
void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name)
{
return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
*m_bitmap_main_frame = create_scaled_bitmap(window, file_name);
}
bool PresetCollection::load_bitmap_add(const std::string &file_name)
void PresetCollection::load_bitmap_add(wxWindow *window, const std::string &file_name)
{
return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
*m_bitmap_add = create_scaled_bitmap(window, file_name);
}
const Preset* PresetCollection::get_selected_preset_parent() const

View file

@ -15,6 +15,7 @@ class wxBitmapComboBox;
class wxChoice;
class wxItemContainer;
class wxString;
class wxWindow;
namespace Slic3r {
@ -276,10 +277,10 @@ public:
bool delete_current_preset();
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
bool load_bitmap_default(const std::string &file_name);
void load_bitmap_default(wxWindow *window, const std::string &file_name);
// Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame.
bool load_bitmap_add(const std::string &file_name);
void load_bitmap_add(wxWindow *window, const std::string &file_name);
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; }

View file

@ -4,6 +4,7 @@
#include "BitmapCache.hpp"
#include "Plater.hpp"
#include "I18N.hpp"
#include "wxExtensions.hpp"
#include <algorithm>
#include <fstream>
@ -102,13 +103,14 @@ PresetBundle::PresetBundle() :
}
// Load the default preset bitmaps.
this->prints .load_bitmap_default("cog.png");
this->sla_prints .load_bitmap_default("package_green.png");
this->filaments .load_bitmap_default("spool.png");
this->sla_materials.load_bitmap_default("package_green.png");
this->printers .load_bitmap_default("printer_empty.png");
this->printers .load_bitmap_add("add.png");
this->load_compatible_bitmaps();
// #ys_FIXME_to_delete we'll load them later, using em_unit()
// this->prints .load_bitmap_default("cog");
// this->sla_prints .load_bitmap_default("package_green.png");
// this->filaments .load_bitmap_default("spool.png");
// this->sla_materials.load_bitmap_default("package_green.png");
// this->printers .load_bitmap_default("printer_empty.png");
// this->printers .load_bitmap_add("add.png");
// this->load_compatible_bitmaps();
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
this->prints .select_preset(0);
@ -394,49 +396,36 @@ void PresetBundle::export_selections(AppConfig &config)
config.set("presets", "printer", printers.get_selected_preset_name());
}
bool PresetBundle::load_compatible_bitmaps()
void PresetBundle::load_compatible_bitmaps(wxWindow *window)
{
const std::string path_bitmap_compatible = "flag-green-icon.png";
const std::string path_bitmap_incompatible = "flag-red-icon.png";
const std::string path_bitmap_lock = "sys_lock.png";//"lock.png";
const std::string path_bitmap_lock_open = "sys_unlock.png";//"lock_open.png";
bool loaded_compatible = m_bitmapCompatible ->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_incompatible = m_bitmapIncompatible->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_incompatible).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_lock = m_bitmapLock->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_lock).c_str()), wxBITMAP_TYPE_PNG);
bool loaded_lock_open = m_bitmapLockOpen->LoadFile(
wxString::FromUTF8(Slic3r::var(path_bitmap_lock_open).c_str()), wxBITMAP_TYPE_PNG);
if (loaded_compatible) {
prints .set_bitmap_compatible(m_bitmapCompatible);
filaments .set_bitmap_compatible(m_bitmapCompatible);
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
// printers .set_bitmap_compatible(m_bitmapCompatible);
}
if (loaded_incompatible) {
prints .set_bitmap_incompatible(m_bitmapIncompatible);
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
// printers .set_bitmap_incompatible(m_bitmapIncompatible);
}
if (loaded_lock) {
prints .set_bitmap_lock(m_bitmapLock);
filaments .set_bitmap_lock(m_bitmapLock);
sla_prints .set_bitmap_lock(m_bitmapLock);
sla_materials.set_bitmap_lock(m_bitmapLock);
printers .set_bitmap_lock(m_bitmapLock);
}
if (loaded_lock_open) {
prints .set_bitmap_lock_open(m_bitmapLock);
filaments .set_bitmap_lock_open(m_bitmapLock);
sla_prints .set_bitmap_lock_open(m_bitmapLock);
sla_materials.set_bitmap_lock_open(m_bitmapLock);
printers .set_bitmap_lock_open(m_bitmapLock);
}
return loaded_compatible && loaded_incompatible && loaded_lock && loaded_lock_open;
*m_bitmapCompatible = create_scaled_bitmap(window, "flag_green");
*m_bitmapIncompatible = create_scaled_bitmap(window, "flag_red");
*m_bitmapLock = create_scaled_bitmap(window, "lock_closed");
*m_bitmapLockOpen = create_scaled_bitmap(window, "sys_unlock.png");
prints .set_bitmap_compatible(m_bitmapCompatible);
filaments .set_bitmap_compatible(m_bitmapCompatible);
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
printers .set_bitmap_compatible(m_bitmapCompatible);
prints .set_bitmap_incompatible(m_bitmapIncompatible);
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
printers .set_bitmap_incompatible(m_bitmapIncompatible);
prints .set_bitmap_lock(m_bitmapLock);
filaments .set_bitmap_lock(m_bitmapLock);
sla_prints .set_bitmap_lock(m_bitmapLock);
sla_materials.set_bitmap_lock(m_bitmapLock);
printers .set_bitmap_lock(m_bitmapLock);
prints .set_bitmap_lock_open(m_bitmapLock);
filaments .set_bitmap_lock_open(m_bitmapLock);
sla_prints .set_bitmap_lock_open(m_bitmapLock);
sla_materials.set_bitmap_lock_open(m_bitmapLock);
printers .set_bitmap_lock_open(m_bitmapLock);
}
DynamicPrintConfig PresetBundle::full_config() const
@ -1438,6 +1427,17 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out
return true;
}
void PresetBundle::load_default_preset_bitmaps(wxWindow *window)
{
this->prints.load_bitmap_default(window, "cog");
this->sla_prints.load_bitmap_default(window, "cog");
this->filaments.load_bitmap_default(window, "spool.png");
this->sla_materials.load_bitmap_default(window, "resin");
this->printers.load_bitmap_default(window, "printer");
this->printers.load_bitmap_add(window, "add.png");
this->load_compatible_bitmaps(window);
}
void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
{
if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA ||

View file

@ -7,6 +7,8 @@
#include <set>
#include <boost/filesystem/path.hpp>
class wxWindow;
namespace Slic3r {
namespace GUI {
@ -127,6 +129,8 @@ public:
static bool parse_color(const std::string &scolor, unsigned char *rgb_out);
void load_default_preset_bitmaps(wxWindow *window);
private:
std::string load_system_presets();
// Merge one vendor's presets with the other vendor's presets, report duplicates.
@ -146,7 +150,7 @@ private:
// If it is not an external config, then the config will be stored into the user profile directory.
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config);
void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree);
bool load_compatible_bitmaps();
void load_compatible_bitmaps(wxWindow *window);
DynamicPrintConfig full_fff_config() const;
DynamicPrintConfig full_sla_config() const;

View file

@ -109,19 +109,20 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection)
if (is_wipe_tower() && volume->is_wipe_tower)
return;
bool keep_instance_mode = (m_mode == Instance) && !as_single_selection && (is_single_full_instance() || is_multiple_full_instance());
bool keep_instance_mode = (m_mode == Instance) && !as_single_selection;
bool already_contained = contains_volume(volume_idx);
// resets the current list if needed
bool needs_reset = as_single_selection;
bool needs_reset = as_single_selection && !already_contained;
needs_reset |= volume->is_wipe_tower;
needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
needs_reset |= !keep_instance_mode && !is_modifier() && volume->is_modifier;
needs_reset |= is_modifier() && !volume->is_modifier;
needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier;
needs_reset |= is_any_modifier() && !volume->is_modifier;
if (needs_reset)
clear();
if (!contains_volume(volume_idx))
if (!already_contained || needs_reset)
{
if (!keep_instance_mode)
m_mode = volume->is_modifier ? Volume : Instance;
@ -482,30 +483,6 @@ void Selection::translate(const Vec3d& displacement, bool local)
m_bounding_box_dirty = true;
}
static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
return
// From the current coordinate system to world.
Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
// From world to the initial coordinate system.
Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
}
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle();
#ifndef NDEBUG
if (std::abs(angle) > 1e-8) {
assert(std::abs(axis.x()) < 1e-8);
assert(std::abs(axis.y()) < 1e-8);
}
#endif /* NDEBUG */
return (axis.z() < 0) ? -angle : angle;
}
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
{
@ -548,7 +525,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
assert(is_approx(rotation.z(), 0.0));
const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
const Vec3d &rotation = first_volume.get_instance_rotation();
double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
}
else {
@ -1538,7 +1515,7 @@ void Selection::render_sidebar_size_hint(Axis axis, double length) const
#ifndef NDEBUG
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle();
if (std::abs(angle) < 1e-8)
@ -1618,7 +1595,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
break;
case SYNC_ROTATION_GENERAL:
// generic rotation -> update instance z with the delta of the rotation.
double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
break;
}

View file

@ -213,7 +213,7 @@ public:
bool is_empty() const { return m_type == Empty; }
bool is_wipe_tower() const { return m_type == WipeTower; }
bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
bool is_any_modifier() const { return is_single_modifier() || is_multiple_modifier(); }
bool is_single_modifier() const { return m_type == SingleModifier; }
bool is_multiple_modifier() const { return m_type == MultipleModifier; }
bool is_single_full_instance() const;
@ -222,6 +222,7 @@ public:
bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
bool is_single_volume() const { return m_type == SingleVolume; }
bool is_multiple_volume() const { return m_type == MultipleVolume; }
bool is_any_volume() const { return is_single_volume() || is_multiple_volume(); }
bool is_mixed() const { return m_type == Mixed; }
bool is_from_single_instance() const { return get_instance_idx() != -1; }
bool is_from_single_object() const;

View file

@ -52,9 +52,7 @@ SysInfoDialog::SysInfoDialog()
main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10);
// logo
// wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG);
// auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png"));
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192));
hsizer->Add(logo, 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);

View file

@ -116,20 +116,16 @@ void Tab::create_preset_tab()
//buttons
wxBitmap bmpMenu;
// bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG);
bmpMenu = create_scaled_bitmap("disk.png");
bmpMenu = create_scaled_bitmap(this, "save");
m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_save_preset->SetBackgroundColour(color);
// bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG);
bmpMenu = create_scaled_bitmap("delete.png");
bmpMenu = create_scaled_bitmap(this, "cross"/*"delete.png"*/);
m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
m_show_incompatible_presets = false;
// m_bmp_show_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG);
// m_bmp_hide_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG);
m_bmp_show_incompatible_presets = create_scaled_bitmap("flag-red-icon.png");
m_bmp_hide_incompatible_presets = create_scaled_bitmap("flag-green-icon.png");
m_bmp_show_incompatible_presets = create_scaled_bitmap(this, "flag_red");
m_bmp_hide_incompatible_presets = create_scaled_bitmap(this, "flag_green");
m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color);
@ -152,18 +148,13 @@ void Tab::create_preset_tab()
// Determine the theme color of OS (dark or light)
auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
// m_bmp_value_lock .LoadFile(from_u8(var("sys_lock.png")), wxBITMAP_TYPE_PNG);
// m_bmp_value_unlock .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG);
m_bmp_value_lock = create_scaled_bitmap("sys_lock.png");
m_bmp_value_unlock = create_scaled_bitmap(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png");
m_bmp_value_lock = create_scaled_bitmap(this, luma >= 128 ? "lock_closed" : "lock_closed_white");
m_bmp_value_unlock = create_scaled_bitmap(this, "lock_open");
m_bmp_non_system = &m_bmp_white_bullet;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
// m_bmp_value_revert .LoadFile(from_u8(var(luma >= 128 ? "action_undo.png" : "action_undo_grey.png")), wxBITMAP_TYPE_PNG);
// m_bmp_white_bullet .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
// m_bmp_question .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
m_bmp_value_revert = create_scaled_bitmap(luma >= 128 ? "action_undo.png" : "action_undo_grey.png");
m_bmp_white_bullet = create_scaled_bitmap("bullet_white.png");
m_bmp_question = create_scaled_bitmap("question_mark_01.png");
m_bmp_value_revert = create_scaled_bitmap(this, "undo");
m_bmp_white_bullet = create_scaled_bitmap(this, "bullet_white.png");
m_bmp_question = create_scaled_bitmap(this, "question");
fill_icon_descriptions();
set_tooltips_text();
@ -292,7 +283,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
// Add a new icon to the icon list.
// wxIcon img_icon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG);
// m_icons->Add(img_icon);
m_icons->Add(create_scaled_bitmap(icon));
m_icons->Add(create_scaled_bitmap(this, icon));
icon_idx = ++m_icon_count;
m_icon_index[icon] = icon_idx;
}
@ -954,7 +945,7 @@ void TabPrint::build()
m_presets = &m_preset_bundle->prints;
load_initial_data();
auto page = add_options_page(_(L("Layers and perimeters")), "layers.png");
auto page = add_options_page(_(L("Layers and perimeters")), "layers");
auto optgroup = page->new_optgroup(_(L("Layer height")));
optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("first_layer_height");
@ -987,7 +978,7 @@ void TabPrint::build()
optgroup->append_single_option_line("seam_position");
optgroup->append_single_option_line("external_perimeters_first");
page = add_options_page(_(L("Infill")), "infill.png");
page = add_options_page(_(L("Infill")), "infill");
optgroup = page->new_optgroup(_(L("Infill")));
optgroup->append_single_option_line("fill_density");
optgroup->append_single_option_line("fill_pattern");
@ -1006,7 +997,7 @@ void TabPrint::build()
optgroup->append_single_option_line("only_retract_when_crossing_perimeters");
optgroup->append_single_option_line("infill_first");
page = add_options_page(_(L("Skirt and brim")), "box.png");
page = add_options_page(_(L("Skirt and brim")), "skirt+brim");
optgroup = page->new_optgroup(_(L("Skirt")));
optgroup->append_single_option_line("skirts");
optgroup->append_single_option_line("skirt_distance");
@ -1016,7 +1007,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Brim")));
optgroup->append_single_option_line("brim_width");
page = add_options_page(_(L("Support material")), "building.png");
page = add_options_page(_(L("Support material")), "support");
optgroup = page->new_optgroup(_(L("Support material")));
optgroup->append_single_option_line("support_material");
optgroup->append_single_option_line("support_material_auto");
@ -1041,7 +1032,7 @@ void TabPrint::build()
optgroup->append_single_option_line("dont_support_bridges");
optgroup->append_single_option_line("support_material_synchronize_layers");
page = add_options_page(_(L("Speed")), "time.png");
page = add_options_page(_(L("Speed")), "time");
optgroup = page->new_optgroup(_(L("Speed for print moves")));
optgroup->append_single_option_line("perimeter_speed");
optgroup->append_single_option_line("small_perimeter_speed");
@ -1075,7 +1066,7 @@ void TabPrint::build()
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative");
#endif /* HAS_PRESSURE_EQUALIZER */
page = add_options_page(_(L("Multiple Extruders")), "funnel.png");
page = add_options_page(_(L("Multiple Extruders")), "funnel");
optgroup = page->new_optgroup(_(L("Extruders")));
optgroup->append_single_option_line("perimeter_extruder");
optgroup->append_single_option_line("infill_extruder");
@ -1125,7 +1116,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Other")));
optgroup->append_single_option_line("clip_multipart_objects");
page = add_options_page(_(L("Output options")), "page_white_go.png");
page = add_options_page(_(L("Output options")), "output+page_white");
optgroup = page->new_optgroup(_(L("Sequential printing")));
optgroup->append_single_option_line("complete_objects");
line = { _(L("Extruder clearance (mm)")), "" };
@ -1520,7 +1511,7 @@ void TabFilament::build()
const int gcode_field_height = 15 * m_em_unit; // 150
const int notes_field_height = 25 * m_em_unit; // 250
page = add_options_page(_(L("Custom G-code")), "cog.png");
page = add_options_page(_(L("Custom G-code")), "cog");
optgroup = page->new_optgroup(_(L("Start G-code")), 0);
Option option = optgroup->get_option("start_filament_gcode");
option.opt.full_width = true;
@ -1641,7 +1632,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots,
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
btn->SetBitmap(create_scaled_bitmap(this, "zoom.png"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -1660,7 +1651,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")),
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap("wrench.png"));
btn->SetBitmap(create_scaled_bitmap(this, "wrench.png"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -1696,9 +1687,8 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG));
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
btn->SetBitmap(create_scaled_bitmap(this, "zoom.png"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -1769,15 +1759,14 @@ void TabPrinter::build_fff()
m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto page = add_options_page(_(L("General")), "printer");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(wxGetApp().small_font());
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
btn->SetBitmap(create_scaled_bitmap(this, "printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -1906,7 +1895,7 @@ void TabPrinter::build_fff()
const int gcode_field_height = 15 * m_em_unit; // 150
const int notes_field_height = 25 * m_em_unit; // 250
page = add_options_page(_(L("Custom G-code")), "cog.png");
page = add_options_page(_(L("Custom G-code")), "cog");
optgroup = page->new_optgroup(_(L("Start G-code")), 0);
option = optgroup->get_option("start_gcode");
option.opt.full_width = true;
@ -1971,15 +1960,14 @@ void TabPrinter::build_sla()
{
if (!m_pages.empty())
m_pages.resize(0);
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto page = add_options_page(_(L("General")), "printer");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent) {
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(wxGetApp().small_font());
// btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
btn->SetBitmap(create_scaled_bitmap(this, "printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -2018,16 +2006,19 @@ void TabPrinter::build_sla()
optgroup->append_single_option_line("area_fill");
optgroup = page->new_optgroup(_(L("Corrections")));
line = Line{ m_config->def()->get("printer_correction")->full_label, "" };
std::vector<std::string> axes{ "X", "Y", "Z" };
line = Line{ m_config->def()->get("relative_correction")->full_label, "" };
// std::vector<std::string> axes{ "X", "Y", "Z" };
std::vector<std::string> axes{ "XY", "Z" };
int id = 0;
for (auto& axis : axes) {
auto opt = optgroup->get_option("printer_correction", id);
auto opt = optgroup->get_option("relative_correction", id);
opt.opt.label = axis;
line.append_option(opt);
++id;
}
optgroup->append_line(line);
optgroup->append_single_option_line("absolute_correction");
optgroup->append_single_option_line("gamma_correction");
optgroup = page->new_optgroup(_(L("Print Host upload")));
build_printhost(optgroup.get());
@ -2081,7 +2072,7 @@ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::s
PageShp TabPrinter::build_kinematics_page()
{
auto page = add_options_page(_(L("Machine limits")), "cog.png", true);
auto page = add_options_page(_(L("Machine limits")), "cog", true);
if (m_use_silent_mode) {
// Legend for OptionsGroups
@ -2173,7 +2164,7 @@ void TabPrinter::build_extruder_pages()
}
if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material") && !m_has_single_extruder_MM_page) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png", true);
auto page = add_options_page(_(L("Single extruder MM setup")), "printer", true);
auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
optgroup->append_single_option_line("cooling_tube_retraction");
optgroup->append_single_option_line("cooling_tube_length");
@ -2189,7 +2180,7 @@ void TabPrinter::build_extruder_pages()
//# build page
char buf[512];
sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
auto page = add_options_page(from_u8(buf), "funnel.png", true);
auto page = add_options_page(from_u8(buf), "funnel", true);
m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page);
auto optgroup = page->new_optgroup(_(L("Size")));
@ -2921,8 +2912,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
deps.btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
// deps.btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
deps.btn->SetBitmap(create_scaled_bitmap("printer_empty.png"));
deps.btn->SetBitmap(create_scaled_bitmap(this, "printer"));
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL);
@ -3113,8 +3103,7 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
bmp_name = mode == comExpert ? "mode_expert_.png" :
mode == comAdvanced ? "mode_middle_.png" : "mode_simple_.png";
}
// auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG));
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(bmp_name));
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(parent, bmp_name));
bmp->SetBackgroundStyle(wxBG_STYLE_PAINT);
return bmp;
};
@ -3222,7 +3211,7 @@ void TabSLAMaterial::build()
m_presets = &m_preset_bundle->sla_materials;
load_initial_data();
auto page = add_options_page(_(L("Material")), "package_green.png");
auto page = add_options_page(_(L("Material")), "resin");
auto optgroup = page->new_optgroup(_(L("Layers")));
// optgroup->append_single_option_line("layer_height");
@ -3234,7 +3223,7 @@ void TabSLAMaterial::build()
optgroup = page->new_optgroup(_(L("Corrections")));
optgroup->label_width = 19 * m_em_unit;//190;
std::vector<std::string> corrections = { "material_correction_printing", "material_correction_curing" };
std::vector<std::string> corrections = {"material_correction"};
std::vector<std::string> axes{ "X", "Y", "Z" };
for (auto& opt_key : corrections) {
auto line = Line{ m_config->def()->get(opt_key)->full_label, "" };
@ -3312,13 +3301,13 @@ void TabSLAPrint::build()
m_presets = &m_preset_bundle->sla_prints;
load_initial_data();
auto page = add_options_page(_(L("Layers and perimeters")), "package_green.png");
auto page = add_options_page(_(L("Layers and perimeters")), "layers");
auto optgroup = page->new_optgroup(_(L("Layers")));
optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("faded_layers");
page = add_options_page(_(L("Supports")), "building.png");
page = add_options_page(_(L("Supports")), "sla_supports");
optgroup = page->new_optgroup(_(L("Supports")));
optgroup->append_single_option_line("supports_enable");
@ -3356,17 +3345,17 @@ void TabSLAPrint::build()
// optgroup->append_single_option_line("pad_edge_radius");
optgroup->append_single_option_line("pad_wall_slope");
page = add_options_page(_(L("Advanced")), "wrench.png");
page = add_options_page(_(L("Advanced")), "wrench");
optgroup = page->new_optgroup(_(L("Slicing")));
optgroup->append_single_option_line("slice_closing_radius");
page = add_options_page(_(L("Output options")), "page_white_go.png");
page = add_options_page(_(L("Output options")), "output+page_white");
optgroup = page->new_optgroup(_(L("Output file")));
Option option = optgroup->get_option("output_filename_format");
option.opt.full_width = true;
optgroup->append_single_option_line(option);
page = add_options_page(_(L("Dependencies")), "wrench.png");
page = add_options_page(_(L("Dependencies")), "wrench");
optgroup = page->new_optgroup(_(L("Profile dependencies")));
Line line = optgroup->create_single_option_line("compatible_printers");//Line { _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent) {

View file

@ -15,6 +15,7 @@
#include "GUI_App.hpp"
#include "I18N.hpp"
#include "ConfigWizard.hpp"
#include "wxExtensions.hpp"
namespace Slic3r {
namespace GUI {
@ -108,8 +109,10 @@ MsgUpdateConfig::~MsgUpdateConfig() {}
// MsgDataIncompatible
MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, wxString> &incompats) :
MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG), wxID_NONE)
MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxID_NONE)
{
logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192));
auto *text = new wxStaticText(this, wxID_ANY, _(L(
"This version of Slic3r PE is not compatible with currently installed configuration bundles.\n"
"This probably happened as a result of running an older Slic3r PE after using a newer one.\n\n"

View file

@ -1,5 +1,7 @@
#include "wxExtensions.hpp"
#include <stdexcept>
#include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp"
@ -44,7 +46,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler)
{
const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(icon) : wxNullBitmap;
const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(nullptr, icon) : wxNullBitmap; // FIXME: pass window ptr
return append_menu_item(menu, id, string, description, cb, bmp, event_handler);
}
@ -55,7 +57,7 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
wxMenuItem* item = new wxMenuItem(menu, id, string, description);
if (!icon.empty())
item->SetBitmap(create_scaled_bitmap(icon));
item->SetBitmap(create_scaled_bitmap(nullptr, icon)); // FIXME: pass window ptr
item->SetSubMenu(sub_menu);
menu->Append(item);
@ -418,33 +420,51 @@ void PrusaCollapsiblePaneMSW::Collapse(bool collapse)
}
#endif //__WXMSW__
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/)
{
static Slic3r::GUI::BitmapCache cache;
#ifdef __APPLE__
const float scale_factor = win != nullptr ? win->GetContentScaleFactor() : 1.0f;
#else
(void)(win);
const float scale_factor = 1.0f;
#endif
unsigned int height, width = height = 0;
unsigned int& scale_base = is_horizontal ? width : height;
scale_base = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * px_cnt * 0.1f + 0.5f);
std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", "");
// Try loading an SVG first, then PNG if SVG is not found:
wxBitmap *bmp = cache.load_svg(bmp_name, width, height, scale_factor);
if (bmp == nullptr) {
bmp = cache.load_png(bmp_name, width, height);
}
if (bmp == nullptr) {
// Neither SVG nor PNG has been found, raise error
throw std::runtime_error("Could not load bitmap: " + bmp_name);
}
return *bmp;
}
// *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModelNode
// ----------------------------------------------------------------------------
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
wxBitmap create_scaled_bitmap(const std::string& bmp_name_in, const bool is_horizontal /* = false*/)
{
static Slic3r::GUI::BitmapCache cache;
unsigned int height, width = height = 0;
unsigned int& scale_base = is_horizontal ? width : height;
scale_base = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * 1.6f + 0.5f);
std::string bmp_name = bmp_name_in;
boost::replace_last(bmp_name, ".png", "");
wxBitmap *bmp = cache.load_svg(bmp_name, width, height);
if (bmp == nullptr)
bmp = cache.load_png(bmp_name, width, height);
return *bmp;
}
void PrusaObjectDataViewModelNode::set_object_action_icon() {
m_action_icon = create_scaled_bitmap("add_object.png");
m_action_icon = create_scaled_bitmap(nullptr, "add_object.png"); // FIXME: pass window ptr
}
void PrusaObjectDataViewModelNode::set_part_action_icon() {
m_action_icon = create_scaled_bitmap(m_type == itVolume ? "cog.png" : "brick_go.png");
m_action_icon = create_scaled_bitmap(nullptr, m_type == itVolume ? "cog.png" : "brick_go.png"); // FIXME: pass window ptr
}
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
@ -1486,20 +1506,20 @@ PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent,
if (!is_osx)
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("right_half_circle.png") : create_scaled_bitmap("up_half_circle.png", true));
m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("left_half_circle.png" ) : create_scaled_bitmap("down_half_circle.png", true));
m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "right_half_circle.png") : create_scaled_bitmap(this, "up_half_circle.png", 16, true));
m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "left_half_circle.png" ) : create_scaled_bitmap(this, "down_half_circle.png", 16, true));
m_thumb_size = m_bmp_thumb_lower.GetSize();
m_bmp_add_tick_on = create_scaled_bitmap("colorchange_add_on.png");
m_bmp_add_tick_off = create_scaled_bitmap("colorchange_add_off.png");
m_bmp_del_tick_on = create_scaled_bitmap("colorchange_delete_on.png");
m_bmp_del_tick_off = create_scaled_bitmap("colorchange_delete_off.png");
m_bmp_add_tick_on = create_scaled_bitmap(this, "colorchange_add_on.png");
m_bmp_add_tick_off = create_scaled_bitmap(this, "colorchange_add_off.png");
m_bmp_del_tick_on = create_scaled_bitmap(this, "colorchange_delete_on.png");
m_bmp_del_tick_off = create_scaled_bitmap(this, "colorchange_delete_off.png");
m_tick_icon_dim = m_bmp_add_tick_on.GetSize().x;
m_bmp_one_layer_lock_on = create_scaled_bitmap("one_layer_lock_on.png");
m_bmp_one_layer_lock_off = create_scaled_bitmap("one_layer_lock_off.png");
m_bmp_one_layer_unlock_on = create_scaled_bitmap("one_layer_unlock_on.png");
m_bmp_one_layer_unlock_off = create_scaled_bitmap("one_layer_unlock_off.png");
m_bmp_one_layer_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png");
m_bmp_one_layer_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png");
m_bmp_one_layer_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png");
m_bmp_one_layer_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png");
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetSize().x;
m_selection = ssUndef;
@ -2323,10 +2343,10 @@ PrusaLockButton::PrusaLockButton( wxWindow *parent,
const wxSize& size /*= wxDefaultSize*/):
wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER)
{
m_bmp_lock_on = create_scaled_bitmap("one_layer_lock_on.png");
m_bmp_lock_off = create_scaled_bitmap("one_layer_lock_off.png");
m_bmp_unlock_on = create_scaled_bitmap("one_layer_unlock_on.png");
m_bmp_unlock_off = create_scaled_bitmap("one_layer_unlock_off.png");
m_bmp_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png");
m_bmp_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png");
m_bmp_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png");
m_bmp_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png");
#ifdef __WXMSW__
@ -2384,7 +2404,7 @@ PrusaModeButton::PrusaModeButton( wxWindow *parent,
#ifdef __WXMSW__
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#endif // __WXMSW__
m_bmp_off = create_scaled_bitmap("mode_off_sq.png");
m_bmp_off = create_scaled_bitmap(this, "mode_off_sq.png");
m_tt_focused = wxString::Format(_(L("Switch to the %s mode")), mode);
m_tt_selected = wxString::Format(_(L("Current mode is %s")), mode);
@ -2434,9 +2454,9 @@ PrusaModeSizer::PrusaModeSizer(wxWindow *parent, int hgap/* = 10*/) :
SetFlexibleDirection(wxHORIZONTAL);
std::vector<std::pair<wxString, wxBitmap>> buttons = {
{_(L("Simple")), create_scaled_bitmap("mode_simple_sq.png")},
{_(L("Advanced")), create_scaled_bitmap("mode_middle_sq.png")},
{_(L("Expert")), create_scaled_bitmap("mode_expert_sq.png")}
{_(L("Simple")), create_scaled_bitmap(parent, "mode_simple_sq.png")},
{_(L("Advanced")), create_scaled_bitmap(parent, "mode_middle_sq.png")},
{_(L("Expert")), create_scaled_bitmap(parent, "mode_expert_sq.png")}
};
mode_btns.reserve(3);

View file

@ -31,7 +31,7 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
wxBitmap create_scaled_bitmap(const std::string& bmp_name, const bool is_horizontal = false);
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{