mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-27 02:31:10 -06:00
Merge branch 'master' into lm_drilling_backend_rebased
This commit is contained in:
commit
a1d4dab999
63 changed files with 3891 additions and 3327 deletions
|
|
@ -10,7 +10,7 @@
|
|||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Slicing.hpp"
|
||||
#include "libslic3r/GCode/Analyzer.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/BitmapCache.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
|
|
@ -792,14 +792,14 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con
|
|||
for (unsigned int i = 0; i < colors_count; ++i)
|
||||
{
|
||||
const std::string& txt_color = config->opt_string("extruder_colour", i);
|
||||
if (PresetBundle::parse_color(txt_color, rgb))
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
{
|
||||
colors[i].set(txt_color, rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string& txt_color = config->opt_string("filament_colour", i);
|
||||
if (PresetBundle::parse_color(txt_color, rgb))
|
||||
if (Slic3r::GUI::BitmapCache::parse_color(txt_color, rgb))
|
||||
colors[i].set(txt_color, rgb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include "BitmapCache.hpp"
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#include "GUI.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#if ! defined(WIN32) && ! defined(__APPLE__)
|
||||
|
|
@ -20,6 +23,16 @@
|
|||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
BitmapCache::BitmapCache()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// Note: win->GetContentScaleFactor() is not used anymore here because it tends to
|
||||
// return bogus results quite often (such as 1.0 on Retina or even 0.0).
|
||||
// We're using the max scaling factor across all screens because it's very likely to be good enough.
|
||||
m_scale = mac_max_scaling_factor();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BitmapCache::clear()
|
||||
{
|
||||
for (std::pair<const std::string, wxBitmap*> &bitmap : m_map)
|
||||
|
|
@ -55,6 +68,14 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_
|
|||
auto it = m_map.find(bitmap_key);
|
||||
if (it == m_map.end()) {
|
||||
bitmap = new wxBitmap(width, height);
|
||||
#ifdef __APPLE__
|
||||
// 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".
|
||||
// So, 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.
|
||||
bitmap->CreateScaled(width, height, -1, m_scale);
|
||||
#endif
|
||||
m_map[bitmap_key] = bitmap;
|
||||
} else {
|
||||
bitmap = it->second;
|
||||
|
|
@ -100,8 +121,13 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
|
|||
size_t width = 0;
|
||||
size_t height = 0;
|
||||
for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
|
||||
#ifdef __APPLE__
|
||||
width += bmp->GetScaledWidth();
|
||||
height = std::max<size_t>(height, bmp->GetScaledHeight());
|
||||
#else
|
||||
width += bmp->GetWidth();
|
||||
height = std::max<size_t>(height, bmp->GetHeight());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BROKEN_ALPHA
|
||||
|
|
@ -167,7 +193,12 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
|
|||
for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) {
|
||||
if (bmp->GetWidth() > 0)
|
||||
memDC.DrawBitmap(*bmp, x, 0, true);
|
||||
#ifdef __APPLE__
|
||||
// we should "move" with step equal to non-scaled width
|
||||
x += bmp->GetScaledWidth();
|
||||
#else
|
||||
x += bmp->GetWidth();
|
||||
#endif
|
||||
}
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
|
|
@ -175,7 +206,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
|
|||
#endif
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale /* = 1.0f */, const bool grayscale/* = false*/)
|
||||
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, const bool grayscale/* = false*/)
|
||||
{
|
||||
wxImage image(width, height);
|
||||
image.InitAlpha();
|
||||
|
|
@ -192,7 +223,7 @@ wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned w
|
|||
if (grayscale)
|
||||
image = image.ConvertToGreyscale(m_gs, m_gs, m_gs);
|
||||
|
||||
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), scale));
|
||||
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), m_scale));
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned width, unsigned height,
|
||||
|
|
@ -227,12 +258,12 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned width,
|
|||
}
|
||||
|
||||
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_width, unsigned target_height,
|
||||
float scale /* = 1.0f */, const bool grayscale/* = false*/, const bool dark_mode/* = false*/)
|
||||
const bool grayscale/* = false*/, const bool dark_mode/* = false*/)
|
||||
{
|
||||
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) : "")
|
||||
+ (m_scale != 1.0f ? "-s" + std::to_string(m_scale) : "")
|
||||
+ (grayscale ? "-gs" : "");
|
||||
|
||||
/* For the Dark mode of any platform, we should draw icons in respect to OS background
|
||||
|
|
@ -272,7 +303,7 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
|
|||
if (image == nullptr)
|
||||
return nullptr;
|
||||
|
||||
target_height != 0 ? target_height *= scale : target_width *= scale;
|
||||
target_height != 0 ? target_height *= m_scale : target_width *= m_scale;
|
||||
|
||||
float svg_scale = target_height != 0 ?
|
||||
(float)target_height / image->height : target_width != 0 ?
|
||||
|
|
@ -297,11 +328,16 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
|
|||
::nsvgDeleteRasterizer(rast);
|
||||
::nsvgDelete(image);
|
||||
|
||||
return this->insert_raw_rgba(bitmap_key, width, height, data.data(), scale, grayscale);
|
||||
return this->insert_raw_rgba(bitmap_key, width, height, data.data(), grayscale);
|
||||
}
|
||||
|
||||
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency)
|
||||
//we make scaled solid bitmaps only for the cases, when its will be used with scaled SVG icon in one output bitmap
|
||||
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling/* = false*/)
|
||||
{
|
||||
double scale = suppress_scaling ? 1.0f : m_scale;
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
|
||||
wxImage image(width, height);
|
||||
image.InitAlpha();
|
||||
unsigned char* imgdata = image.GetData();
|
||||
|
|
@ -312,7 +348,32 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
|
|||
*imgdata ++ = b;
|
||||
*imgalpha ++ = transparency;
|
||||
}
|
||||
return wxImage_to_wxBitmap_with_alpha(std::move(image));
|
||||
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
|
||||
}
|
||||
|
||||
|
||||
static inline int hex_digit_to_int(const char c)
|
||||
{
|
||||
return
|
||||
(c >= '0' && c <= '9') ? int(c - '0') :
|
||||
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
|
||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||
}
|
||||
|
||||
bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
|
||||
{
|
||||
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;
|
||||
if (scolor.size() != 7 || scolor.front() != '#')
|
||||
return false;
|
||||
const char* c = scolor.data() + 1;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
int digit1 = hex_digit_to_int(*c++);
|
||||
int digit2 = hex_digit_to_int(*c++);
|
||||
if (digit1 == -1 || digit2 == -1)
|
||||
return false;
|
||||
rgb_out[i] = (unsigned char)(digit1 * 16 + digit2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
|||
|
|
@ -1,24 +1,22 @@
|
|||
#ifndef SLIC3R_GUI_BITMAP_CACHE_HPP
|
||||
#define SLIC3R_GUI_BITMAP_CACHE_HPP
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Config.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class BitmapCache
|
||||
{
|
||||
public:
|
||||
BitmapCache() {}
|
||||
BitmapCache();
|
||||
~BitmapCache() { clear(); }
|
||||
void clear();
|
||||
double scale() { return m_scale; }
|
||||
|
||||
wxBitmap* find(const std::string &name) { auto it = m_map.find(name); return (it == m_map.end()) ? nullptr : it->second; }
|
||||
const wxBitmap* find(const std::string &name) const { return const_cast<BitmapCache*>(this)->find(name); }
|
||||
|
|
@ -29,20 +27,23 @@ 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 width, unsigned height, const unsigned char *raw_data, float scale = 1.0f, const bool grayscale = false);
|
||||
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, const bool grayscale = false);
|
||||
|
||||
// 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 width = 0, unsigned height = 0, const bool grayscale = false);
|
||||
// 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 width = 0, unsigned height = 0, float scale = 1.0f, const bool grayscale = false, const bool dark_mode = false);
|
||||
wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false);
|
||||
|
||||
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); }
|
||||
static wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
|
||||
/*static */wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false);
|
||||
/*static */wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3], bool suppress_scaling = false) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }
|
||||
/*static */wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
|
||||
|
||||
static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
|
||||
|
||||
private:
|
||||
std::map<std::string, wxBitmap*> m_map;
|
||||
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
|
||||
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
|
||||
double m_scale = 1.0; // value, used for correct scaling of SVG icons on Retina display
|
||||
};
|
||||
|
||||
} // GUI
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
static const float GIMBALL_LOCK_THETA_MAX = 180.0f;
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
// phi / theta angles to orient the camera.
|
||||
static const float VIEW_DEFAULT[2] = { 45.0f, 45.0f };
|
||||
|
|
@ -66,13 +68,10 @@ std::string Camera::get_type_as_string() const
|
|||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Unknown:
|
||||
return "unknown";
|
||||
case Perspective:
|
||||
return "perspective";
|
||||
case Unknown: return "unknown";
|
||||
case Perspective: return "perspective";
|
||||
default:
|
||||
case Ortho:
|
||||
return "orthographic";
|
||||
case Ortho: return "orthographic";
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -88,10 +87,7 @@ void Camera::set_type(EType type)
|
|||
|
||||
void Camera::set_type(const std::string& type)
|
||||
{
|
||||
if (type == "1")
|
||||
set_type(Perspective);
|
||||
else
|
||||
set_type(Ortho);
|
||||
set_type((type == "1") ? Perspective : Ortho);
|
||||
}
|
||||
|
||||
void Camera::select_next_type()
|
||||
|
|
@ -157,17 +153,17 @@ void Camera::select_view(const std::string& direction)
|
|||
if (direction == "iso")
|
||||
set_default_orientation();
|
||||
else if (direction == "left")
|
||||
m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
|
||||
look_at(m_target - m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
|
||||
else if (direction == "right")
|
||||
m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
|
||||
look_at(m_target + m_distance * Vec3d::UnitX(), m_target, Vec3d::UnitZ());
|
||||
else if (direction == "top")
|
||||
m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY());
|
||||
look_at(m_target + m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY());
|
||||
else if (direction == "bottom")
|
||||
m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitZ(), m_target, -Vec3d::UnitY());
|
||||
look_at(m_target - m_distance * Vec3d::UnitZ(), m_target, -Vec3d::UnitY());
|
||||
else if (direction == "front")
|
||||
m_view_matrix = look_at(m_target - m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
|
||||
look_at(m_target - m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
|
||||
else if (direction == "rear")
|
||||
m_view_matrix = look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
|
||||
look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ());
|
||||
}
|
||||
#else
|
||||
bool Camera::select_view(const std::string& direction)
|
||||
|
|
@ -244,17 +240,27 @@ void Camera::apply_view_matrix() const
|
|||
|
||||
void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) const
|
||||
{
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
set_distance(DefaultDistance);
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
double w = 0.0;
|
||||
double h = 0.0;
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double old_distance = m_distance;
|
||||
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
||||
if (m_distance != old_distance)
|
||||
// the camera has been moved re-apply view matrix
|
||||
apply_view_matrix();
|
||||
#else
|
||||
while (true)
|
||||
{
|
||||
m_frustrum_zs = calc_tight_frustrum_zs_around(box);
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
if (near_z > 0.0)
|
||||
m_frustrum_zs.first = std::min(m_frustrum_zs.first, near_z);
|
||||
m_frustrum_zs.first = std::max(std::min(m_frustrum_zs.first, near_z), FrustrumMinNearZ);
|
||||
|
||||
if (far_z > 0.0)
|
||||
m_frustrum_zs.second = std::max(m_frustrum_zs.second, far_z);
|
||||
|
|
@ -262,12 +268,9 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
|||
w = 0.5 * (double)m_viewport[2];
|
||||
h = 0.5 * (double)m_viewport[3];
|
||||
|
||||
if (m_zoom != 0.0)
|
||||
{
|
||||
double inv_zoom = 1.0 / m_zoom;
|
||||
w *= inv_zoom;
|
||||
h *= inv_zoom;
|
||||
}
|
||||
double inv_zoom = get_inv_zoom();
|
||||
w *= inv_zoom;
|
||||
h *= inv_zoom;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
|
|
@ -288,6 +291,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
|||
}
|
||||
}
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
if (m_type == Perspective)
|
||||
{
|
||||
double fov_deg = Geometry::rad2deg(2.0 * std::atan(h / m_frustrum_zs.first));
|
||||
|
|
@ -307,6 +311,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
|||
else
|
||||
break;
|
||||
}
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
glsafe(::glMatrixMode(GL_PROJECTION));
|
||||
glsafe(::glLoadIdentity());
|
||||
|
|
@ -331,14 +336,22 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa
|
|||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor)
|
||||
#else
|
||||
void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor)
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#else
|
||||
void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
// Calculate the zoom factor needed to adjust the view around the given box.
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double zoom = calc_zoom_to_bounding_box_factor(box, margin_factor);
|
||||
#else
|
||||
double zoom = calc_zoom_to_bounding_box_factor(box, canvas_w, canvas_h, margin_factor);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#else
|
||||
double zoom = calc_zoom_to_bounding_box_factor(box, canvas_w, canvas_h);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
|
@ -355,10 +368,18 @@ void Camera::zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h)
|
|||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor)
|
||||
#else
|
||||
void Camera::zoom_to_volumes(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, double margin_factor)
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
{
|
||||
Vec3d center;
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double zoom = calc_zoom_to_volumes_factor(volumes, center, margin_factor);
|
||||
#else
|
||||
double zoom = calc_zoom_to_volumes_factor(volumes, canvas_w, canvas_h, center, margin_factor);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
if (zoom > 0.0)
|
||||
{
|
||||
m_zoom = zoom;
|
||||
|
|
@ -396,6 +417,7 @@ void Camera::debug_render() const
|
|||
float deltaZ = farZ - nearZ;
|
||||
float zoom = (float)m_zoom;
|
||||
float fov = (float)get_fov();
|
||||
std::array<int, 4>viewport = get_viewport();
|
||||
float gui_scale = (float)get_gui_scale();
|
||||
|
||||
ImGui::InputText("Type", type.data(), type.length(), ImGuiInputTextFlags_ReadOnly);
|
||||
|
|
@ -415,6 +437,8 @@ void Camera::debug_render() const
|
|||
ImGui::InputFloat("Zoom", &zoom, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::InputFloat("Fov", &fov, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::Separator();
|
||||
ImGui::InputInt4("Viewport", viewport.data(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::Separator();
|
||||
ImGui::InputFloat("GUI scale", &gui_scale, 0.0f, 0.0f, "%.6f", ImGuiInputTextFlags_ReadOnly);
|
||||
imgui.end();
|
||||
}
|
||||
|
|
@ -434,10 +458,31 @@ void Camera::translate_world(const Vec3d& displacement)
|
|||
|
||||
void Camera::rotate_on_sphere(double delta_azimut_rad, double delta_zenit_rad)
|
||||
{
|
||||
// FIXME -> The following is a HACK !!!
|
||||
// When the value of the zenit rotation is large enough, the following call to rotate() shows
|
||||
// numerical instability introducing some scaling into m_view_matrix (verified by checking
|
||||
// that the camera space unit vectors are no more unit).
|
||||
// See also https://dev.prusa3d.com/browse/SPE-1082
|
||||
// We split the zenit rotation into a set of smaller rotations which are then applied.
|
||||
static const double MAX_ALLOWED = Geometry::deg2rad(0.1);
|
||||
unsigned int zenit_steps_count = 1 + (unsigned int)(std::abs(delta_zenit_rad) / MAX_ALLOWED);
|
||||
double zenit_step = delta_zenit_rad / (double)zenit_steps_count;
|
||||
|
||||
Vec3d target = m_target;
|
||||
translate_world(-target);
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(delta_zenit_rad, get_dir_right()));
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()));
|
||||
|
||||
if (zenit_step != 0.0)
|
||||
{
|
||||
Vec3d right = get_dir_right();
|
||||
for (unsigned int i = 0; i < zenit_steps_count; ++i)
|
||||
{
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(zenit_step, right));
|
||||
}
|
||||
}
|
||||
|
||||
if (delta_azimut_rad != 0.0)
|
||||
m_view_matrix.rotate(Eigen::AngleAxisd(delta_azimut_rad, Vec3d::UnitZ()));
|
||||
|
||||
translate_world(target);
|
||||
}
|
||||
|
||||
|
|
@ -457,49 +502,77 @@ void Camera::rotate_local_around_pivot(const Vec3d& rotation_rad, const Vec3d& p
|
|||
m_view_matrix.rotate(Eigen::AngleAxisd(rotation_rad(2), get_dir_forward()));
|
||||
translate_world(center);
|
||||
}
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
|
||||
double Camera::min_zoom() const
|
||||
{
|
||||
return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box, (int)m_viewport[2], (int)m_viewport[3]);
|
||||
}
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box);
|
||||
#else
|
||||
return 0.7 * calc_zoom_to_bounding_box_factor(m_scene_box, m_viewport[2], m_viewport[3]);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
}
|
||||
|
||||
std::pair<double, double> Camera::calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const
|
||||
{
|
||||
std::pair<double, double> ret;
|
||||
auto& [near_z, far_z] = ret;
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
while (true)
|
||||
{
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
// box in eye space
|
||||
BoundingBoxf3 eye_box = box.transformed(m_view_matrix);
|
||||
ret.first = -eye_box.max(2);
|
||||
ret.second = -eye_box.min(2);
|
||||
near_z = -eye_box.max(2);
|
||||
far_z = -eye_box.min(2);
|
||||
|
||||
// apply margin
|
||||
ret.first -= FrustrumZMargin;
|
||||
ret.second += FrustrumZMargin;
|
||||
near_z -= FrustrumZMargin;
|
||||
far_z += FrustrumZMargin;
|
||||
|
||||
// ensure min size
|
||||
if (ret.second - ret.first < FrustrumMinZRange)
|
||||
if (far_z - near_z < FrustrumMinZRange)
|
||||
{
|
||||
double mid_z = 0.5 * (ret.first + ret.second);
|
||||
double mid_z = 0.5 * (near_z + far_z);
|
||||
double half_size = 0.5 * FrustrumMinZRange;
|
||||
ret.first = mid_z - half_size;
|
||||
ret.second = mid_z + half_size;
|
||||
near_z = mid_z - half_size;
|
||||
far_z = mid_z + half_size;
|
||||
}
|
||||
|
||||
if (ret.first >= FrustrumMinNearZ)
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
if (near_z < FrustrumMinNearZ)
|
||||
{
|
||||
float delta = FrustrumMinNearZ - near_z;
|
||||
set_distance(m_distance + delta);
|
||||
near_z += delta;
|
||||
far_z += delta;
|
||||
}
|
||||
else if ((near_z > 2.0 * FrustrumMinNearZ) && (m_distance > DefaultDistance))
|
||||
{
|
||||
float delta = m_distance - DefaultDistance;
|
||||
set_distance(DefaultDistance);
|
||||
near_z -= delta;
|
||||
far_z -= delta;
|
||||
}
|
||||
#else
|
||||
if (near_z >= FrustrumMinNearZ)
|
||||
break;
|
||||
|
||||
// ensure min Near Z
|
||||
set_distance(m_distance + FrustrumMinNearZ - ret.first);
|
||||
// ensure min near z
|
||||
set_distance(m_distance + FrustrumMinNearZ - near_z);
|
||||
}
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, double margin_factor) const
|
||||
#else
|
||||
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor) const
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#else
|
||||
double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
|
@ -511,8 +584,10 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
|||
// project the box vertices on a plane perpendicular to the camera forward axis
|
||||
// then calculates the vertices coordinate on this plane along the camera xy axes
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
// ensure that the view matrix is updated
|
||||
apply_view_matrix();
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
Vec3d right = get_dir_right();
|
||||
Vec3d up = get_dir_up();
|
||||
|
|
@ -569,11 +644,19 @@ double Camera::calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int ca
|
|||
dx *= margin_factor;
|
||||
dy *= margin_factor;
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
return std::min((double)m_viewport[2] / dx, (double)m_viewport[3] / dy);
|
||||
#else
|
||||
return std::min((double)canvas_w / dx, (double)canvas_h / dy);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& center, double margin_factor) const
|
||||
#else
|
||||
double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, Vec3d& center, double margin_factor) const
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
{
|
||||
if (volumes.empty())
|
||||
return -1.0;
|
||||
|
|
@ -581,8 +664,10 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canv
|
|||
// project the volumes vertices on a plane perpendicular to the camera forward axis
|
||||
// then calculates the vertices coordinate on this plane along the camera xy axes
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
// ensure that the view matrix is updated
|
||||
apply_view_matrix();
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
|
||||
Vec3d right = get_dir_right();
|
||||
Vec3d up = get_dir_up();
|
||||
|
|
@ -634,46 +719,57 @@ double Camera::calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canv
|
|||
if ((dx <= 0.0) || (dy <= 0.0))
|
||||
return -1.0f;
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
return std::min((double)m_viewport[2] / dx, (double)m_viewport[3] / dy);
|
||||
#else
|
||||
return std::min((double)canvas_w / dx, (double)canvas_h / dy);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
void Camera::set_distance(double distance) const
|
||||
{
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
if (m_distance != distance)
|
||||
{
|
||||
m_view_matrix.translate((distance - m_distance) * get_dir_forward());
|
||||
m_distance = distance;
|
||||
}
|
||||
#else
|
||||
m_distance = distance;
|
||||
apply_view_matrix();
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
}
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
Transform3d Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up) const
|
||||
void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up)
|
||||
{
|
||||
Vec3d unit_z = (position - target).normalized();
|
||||
Vec3d unit_x = up.cross(unit_z).normalized();
|
||||
Vec3d unit_y = unit_z.cross(unit_x).normalized();
|
||||
|
||||
Transform3d matrix;
|
||||
m_target = target;
|
||||
Vec3d new_position = m_target + m_distance * unit_z;
|
||||
|
||||
matrix(0, 0) = unit_x(0);
|
||||
matrix(0, 1) = unit_x(1);
|
||||
matrix(0, 2) = unit_x(2);
|
||||
matrix(0, 3) = -unit_x.dot(position);
|
||||
m_view_matrix(0, 0) = unit_x(0);
|
||||
m_view_matrix(0, 1) = unit_x(1);
|
||||
m_view_matrix(0, 2) = unit_x(2);
|
||||
m_view_matrix(0, 3) = -unit_x.dot(new_position);
|
||||
|
||||
matrix(1, 0) = unit_y(0);
|
||||
matrix(1, 1) = unit_y(1);
|
||||
matrix(1, 2) = unit_y(2);
|
||||
matrix(1, 3) = -unit_y.dot(position);
|
||||
m_view_matrix(1, 0) = unit_y(0);
|
||||
m_view_matrix(1, 1) = unit_y(1);
|
||||
m_view_matrix(1, 2) = unit_y(2);
|
||||
m_view_matrix(1, 3) = -unit_y.dot(new_position);
|
||||
|
||||
matrix(2, 0) = unit_z(0);
|
||||
matrix(2, 1) = unit_z(1);
|
||||
matrix(2, 2) = unit_z(2);
|
||||
matrix(2, 3) = -unit_z.dot(position);
|
||||
m_view_matrix(2, 0) = unit_z(0);
|
||||
m_view_matrix(2, 1) = unit_z(1);
|
||||
m_view_matrix(2, 2) = unit_z(2);
|
||||
m_view_matrix(2, 3) = -unit_z.dot(new_position);
|
||||
|
||||
matrix(3, 0) = 0.0;
|
||||
matrix(3, 1) = 0.0;
|
||||
matrix(3, 2) = 0.0;
|
||||
matrix(3, 3) = 1.0;
|
||||
|
||||
return matrix;
|
||||
m_view_matrix(3, 0) = 0.0;
|
||||
m_view_matrix(3, 1) = 0.0;
|
||||
m_view_matrix(3, 2) = 0.0;
|
||||
m_view_matrix(3, 3) = 1.0;
|
||||
}
|
||||
|
||||
void Camera::set_default_orientation()
|
||||
|
|
|
|||
|
|
@ -48,11 +48,7 @@ private:
|
|||
mutable double m_gui_scale;
|
||||
|
||||
mutable std::array<int, 4> m_viewport;
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
Transform3d m_view_matrix;
|
||||
#else
|
||||
mutable Transform3d m_view_matrix;
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
mutable Transform3d m_projection_matrix;
|
||||
mutable std::pair<double, double> m_frustrum_zs;
|
||||
|
||||
|
|
@ -71,7 +67,11 @@ public:
|
|||
const Vec3d& get_target() const { return m_target; }
|
||||
void set_target(const Vec3d& target);
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double get_distance() const { return (get_position() - m_target).norm(); }
|
||||
#else
|
||||
double get_distance() const { return m_distance; }
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
double get_gui_scale() const { return m_gui_scale; }
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
|
|
@ -115,8 +115,13 @@ public:
|
|||
void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0) const;
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
void zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor);
|
||||
void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
||||
#else
|
||||
void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToBoxMarginFactor);
|
||||
void zoom_to_volumes(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToVolumesMarginFactor);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#else
|
||||
void zoom_to_box(const BoundingBoxf3& box, int canvas_w, int canvas_h);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
|
@ -141,25 +146,29 @@ public:
|
|||
|
||||
// returns true if the camera z axis (forward) is pointing in the negative direction of the world z axis
|
||||
bool is_looking_downward() const { return get_dir_forward().dot(Vec3d::UnitZ()) < 0.0; }
|
||||
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
double max_zoom() const { return 100.0; }
|
||||
double min_zoom() const;
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
|
||||
private:
|
||||
// returns tight values for nearZ and farZ plane around the given bounding box
|
||||
// the camera MUST be outside of the bounding box in eye coordinate of the given box
|
||||
std::pair<double, double> calc_tight_frustrum_zs_around(const BoundingBoxf3& box) const;
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor) const;
|
||||
double calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, Vec3d& center, double margin_factor = DefaultZoomToVolumesMarginFactor) const;
|
||||
#else
|
||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h, double margin_factor = DefaultZoomToBoxMarginFactor) const;
|
||||
double calc_zoom_to_volumes_factor(const GLVolumePtrs& volumes, int canvas_w, int canvas_h, Vec3d& center, double margin_factor = DefaultZoomToVolumesMarginFactor) const;
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#else
|
||||
double calc_zoom_to_bounding_box_factor(const BoundingBoxf3& box, int canvas_w, int canvas_h) const;
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
void set_distance(double distance) const;
|
||||
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
Transform3d look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up) const;
|
||||
void look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up);
|
||||
void set_default_orientation();
|
||||
Vec3d validate_target(const Vec3d& target) const;
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
|
|
|
|||
|
|
@ -52,28 +52,26 @@ Control::Control( wxWindow *parent,
|
|||
if (!is_osx)
|
||||
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
|
||||
|
||||
const float scale_factor = get_svg_scale_factor(this);
|
||||
|
||||
m_bmp_thumb_higher = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "right_half_circle.png") : ScalableBitmap(this, "thumb_up"));
|
||||
m_bmp_thumb_lower = (style == wxSL_HORIZONTAL ? ScalableBitmap(this, "left_half_circle.png" ) : ScalableBitmap(this, "thumb_down"));
|
||||
m_thumb_size = m_bmp_thumb_lower.bmp().GetSize()*(1.0/scale_factor);
|
||||
m_thumb_size = m_bmp_thumb_lower.GetBmpSize();
|
||||
|
||||
m_bmp_add_tick_on = ScalableBitmap(this, "colorchange_add");
|
||||
m_bmp_add_tick_off = ScalableBitmap(this, "colorchange_add_f");
|
||||
m_bmp_del_tick_on = ScalableBitmap(this, "colorchange_del");
|
||||
m_bmp_del_tick_off = ScalableBitmap(this, "colorchange_del_f");
|
||||
m_tick_icon_dim = int((float)m_bmp_add_tick_on.bmp().GetSize().x / scale_factor);
|
||||
m_tick_icon_dim = m_bmp_add_tick_on.GetBmpWidth();
|
||||
|
||||
m_bmp_one_layer_lock_on = ScalableBitmap(this, "lock_closed");
|
||||
m_bmp_one_layer_lock_off = ScalableBitmap(this, "lock_closed_f");
|
||||
m_bmp_one_layer_unlock_on = ScalableBitmap(this, "lock_open");
|
||||
m_bmp_one_layer_unlock_off = ScalableBitmap(this, "lock_open_f");
|
||||
m_lock_icon_dim = int((float)m_bmp_one_layer_lock_on.bmp().GetSize().x / scale_factor);
|
||||
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetBmpWidth();
|
||||
|
||||
m_bmp_revert = ScalableBitmap(this, "undo");
|
||||
m_revert_icon_dim = int((float)m_bmp_revert.bmp().GetSize().x / scale_factor);
|
||||
m_revert_icon_dim = m_bmp_revert.GetBmpWidth();
|
||||
m_bmp_cog = ScalableBitmap(this, "cog");
|
||||
m_cog_icon_dim = int((float)m_bmp_cog.bmp().GetSize().x / scale_factor);
|
||||
m_cog_icon_dim = m_bmp_cog.GetBmpWidth();
|
||||
|
||||
m_selection = ssUndef;
|
||||
m_ticks.set_pause_print_msg(_utf8(L("Place bearings in slots and resume")));
|
||||
|
|
@ -554,16 +552,9 @@ void Control::draw_ticks(wxDC& dc)
|
|||
|
||||
// Draw icon for "Pause print" or "Custom Gcode"
|
||||
if (tick.gcode != ColorChangeCode && tick.gcode != ToolChangeCode)
|
||||
icon = create_scaled_bitmap(this, tick.gcode == PausePrintCode ? "pause_print" : "edit_gcode");
|
||||
else
|
||||
{
|
||||
if ((tick.gcode == ColorChangeCode && (
|
||||
(m_ticks.mode == t_mode::SingleExtruder && m_mode == t_mode::MultiExtruder ) ||
|
||||
(m_ticks.mode == t_mode::MultiExtruder && m_mode == t_mode::SingleExtruder) )) ||
|
||||
(tick.gcode == ToolChangeCode &&
|
||||
(m_ticks.mode == t_mode::MultiAsSingle && m_mode != t_mode::MultiAsSingle ) ))
|
||||
icon = create_scaled_bitmap(this, "error_tick");
|
||||
}
|
||||
icon = create_scaled_bitmap(tick.gcode == PausePrintCode ? "pause_print" : "edit_gcode");
|
||||
else if (m_ticks.is_conflict_tick(tick, m_mode, m_only_extruder, m_values[tick.tick]))
|
||||
icon = create_scaled_bitmap("error_tick");
|
||||
|
||||
if (!icon.IsNull())
|
||||
{
|
||||
|
|
@ -753,7 +744,7 @@ bool Control::is_point_in_rect(const wxPoint& pt, const wxRect& rect)
|
|||
rect.GetTop() <= pt.y && pt.y <= rect.GetBottom();
|
||||
}
|
||||
|
||||
int Control::is_point_near_tick(const wxPoint& pt)
|
||||
int Control::get_tick_near_point(const wxPoint& pt)
|
||||
{
|
||||
for (auto tick : m_ticks.ticks) {
|
||||
const wxCoord pos = get_position_from_value(tick.tick);
|
||||
|
|
@ -833,7 +824,7 @@ void Control::OnLeftDown(wxMouseEvent& event)
|
|||
detect_selected_slider(pos);
|
||||
|
||||
if (!m_selection) {
|
||||
const int tick_val = is_point_near_tick(pos);
|
||||
const int tick_val = get_tick_near_point(pos);
|
||||
/* Set current thumb position to the nearest tick (if it is)
|
||||
* OR to a value corresponding to the mouse click
|
||||
* */
|
||||
|
|
@ -896,20 +887,70 @@ wxString Control::get_tooltip(IconFocus icon_focus)
|
|||
{
|
||||
const int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||
const auto tick_code_it = m_ticks.ticks.find(TickCode{tick});
|
||||
tooltip = tick_code_it == m_ticks.ticks.end() ? (m_mode == t_mode::MultiAsSingle ?
|
||||
_(L("For add change extruder use left mouse button click")) :
|
||||
_(L("For add color change use left mouse button click")) ) + "\n" +
|
||||
_(L("For add another code use right mouse button click")) :
|
||||
tick_code_it->gcode == ColorChangeCode ? ( m_mode == t_mode::SingleExtruder ?
|
||||
_(L("For Delete color change use left mouse button click\n"
|
||||
"For Edit color use right mouse button click")) :
|
||||
from_u8((boost::format(_utf8(L("Delete color change for Extruder %1%"))) % tick_code_it->extruder).str()) ):
|
||||
tick_code_it->gcode == PausePrintCode ?
|
||||
_(L("Delete pause")) :
|
||||
tick_code_it->gcode == ToolChangeCode ?
|
||||
from_u8((boost::format(_utf8(L("Delete extruder change to \"%1%\""))) % tick_code_it->extruder).str()) :
|
||||
from_u8((boost::format(_utf8(L("For Delete \"%1%\" code use left mouse button click\n"
|
||||
"For Edit \"%1%\" code use right mouse button click"))) % tick_code_it->gcode ).str());
|
||||
|
||||
/* Note: just on OSX!!!
|
||||
* Right click event causes a little scrolling.
|
||||
* So, as a workaround we use Ctrl+LeftMouseClick instead of RightMouseClick
|
||||
* Show this information in tooltip
|
||||
* */
|
||||
|
||||
if (tick_code_it == m_ticks.ticks.end()) // tick doesn't exist
|
||||
{
|
||||
// Show mode as a first string of tooltop
|
||||
tooltip = " " + _(L("Slider(print) mode")) + ": ";
|
||||
tooltip += (m_mode == t_mode::SingleExtruder ? CustomGCode::SingleExtruderMode :
|
||||
m_mode == t_mode::MultiAsSingle ? CustomGCode::MultiAsSingleMode :
|
||||
CustomGCode::MultiExtruderMode );
|
||||
tooltip += "\n\n";
|
||||
|
||||
// Show list of actions with new tick
|
||||
tooltip += ( m_mode == t_mode::MultiAsSingle ?
|
||||
_(L("For add change extruder use left mouse button click")) :
|
||||
_(L("For add color change use left mouse button click")) ) + " " +
|
||||
_(L("OR pres \"+\" key")) + "\n" + (
|
||||
is_osx ?
|
||||
_(L("For add another code use Ctrl + Left mouse button click")) :
|
||||
_(L("For add another code use right mouse button click")) );
|
||||
}
|
||||
else // tick exists
|
||||
{
|
||||
// Show custom Gcode as a first string of tooltop
|
||||
tooltip = " ";
|
||||
tooltip += tick_code_it->gcode == ColorChangeCode ? (
|
||||
m_mode == t_mode::SingleExtruder ?
|
||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
||||
from_u8((boost::format(_utf8(L("Color change (\"%1%\") for Extruder %2%"))) %
|
||||
tick_code_it->gcode % tick_code_it->extruder).str()) ) :
|
||||
tick_code_it->gcode == PausePrintCode ?
|
||||
from_u8((boost::format(_utf8(L("Pause print (\"%1%\")"))) % tick_code_it->gcode ).str()) :
|
||||
tick_code_it->gcode == ToolChangeCode ?
|
||||
from_u8((boost::format(_utf8(L("Extruder(tool) is changed to Extruder \"%1%\""))) % tick_code_it->extruder ).str()) :
|
||||
from_u8((boost::format(_utf8(L("\"%1%\""))) % tick_code_it->gcode ).str()) ;
|
||||
|
||||
// If tick is marked as a conflict (exclamation icon),
|
||||
// we should to explain why
|
||||
ConflictType conflict = m_ticks.is_conflict_tick(*tick_code_it, m_mode, m_only_extruder, m_values[tick]);
|
||||
if (conflict != ctNone)
|
||||
tooltip += "\n\n" + _(L("Note")) + "! ";
|
||||
if (conflict == ctModeConflict)
|
||||
tooltip += _(L("G-code of this tick has a conflict with slider(print) mode.\n"
|
||||
"Any its editing will cause a changes of DoubleSlider data."));
|
||||
else if (conflict == ctMeaninglessColorChange)
|
||||
tooltip += _(L("There is a color change for extruder that wouldn't be used till the end of printing.\n"
|
||||
"This code wouldn't be processed during GCode generation."));
|
||||
else if (conflict == ctMeaninglessToolChange)
|
||||
tooltip += _(L("There is a extruder change to the same extruder.\n"
|
||||
"This code wouldn't be processed during GCode generation."));
|
||||
else if (conflict == ctRedundant)
|
||||
tooltip += _(L("There is a color change for extruder that has not been used before.\n"
|
||||
"Check your choice to avoid redundant color changes."));
|
||||
|
||||
// Show list of actions with existing tick
|
||||
tooltip += "\n\n" + _(L("For Delete tick use left mouse button click OR pres \"-\" key")) + "\n" + (
|
||||
is_osx ?
|
||||
_(L("For Edit tick use Ctrl + Left mouse button click")) :
|
||||
_(L("For Edit tick use right mouse button click")) );
|
||||
}
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
|
|
@ -988,7 +1029,7 @@ void Control::append_change_extruder_menu_item(wxMenu* menu, bool switch_current
|
|||
_(L("Change extruder (N/A)"));
|
||||
|
||||
wxMenuItem* change_extruder_menu_item = menu->AppendSubMenu(change_extruder_menu, change_extruder_menu_name, _(L("Use another extruder")));
|
||||
change_extruder_menu_item->SetBitmap(create_scaled_bitmap(this, active_extruders[1] > 0 ? "edit_uni" : "change_extruder"));
|
||||
change_extruder_menu_item->SetBitmap(create_scaled_bitmap(active_extruders[1] > 0 ? "edit_uni" : "change_extruder"));
|
||||
|
||||
GUI::wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this, change_extruder_menu_item](wxUpdateUIEvent& evt) {
|
||||
enable_menu_item(evt, [this]() {return m_mode == t_mode::MultiAsSingle; }, change_extruder_menu_item, this); },
|
||||
|
|
@ -1001,7 +1042,8 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren
|
|||
const int extruders_cnt = GUI::wxGetApp().extruders_edited_cnt();
|
||||
if (extruders_cnt > 1)
|
||||
{
|
||||
std::set<int> used_extruders_for_tick = get_used_extruders_for_tick(m_selection == ssLower ? m_lower_value : m_higher_value);
|
||||
int tick = m_selection == ssLower ? m_lower_value : m_higher_value;
|
||||
std::set<int> used_extruders_for_tick = m_ticks.get_used_extruders_for_tick(tick, m_only_extruder, m_values[tick]);
|
||||
|
||||
wxMenu* add_color_change_menu = new wxMenu();
|
||||
|
||||
|
|
@ -1014,14 +1056,14 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren
|
|||
|
||||
append_menu_item(add_color_change_menu, wxID_ANY, item_name, "",
|
||||
[this, i](wxCommandEvent&) { add_code_as_tick(ColorChangeCode, i); }, "", menu,
|
||||
[is_used_extruder]() { return is_used_extruder; }, GUI::wxGetApp().plater());
|
||||
[]() { return true; }, GUI::wxGetApp().plater());
|
||||
}
|
||||
|
||||
const wxString menu_name = switch_current_code ?
|
||||
from_u8((boost::format(_utf8(L("Switch code to Color change (%1%) for:"))) % ColorChangeCode).str()) :
|
||||
from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % ColorChangeCode).str());
|
||||
wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
|
||||
add_color_change_menu_item->SetBitmap(create_scaled_bitmap(this, "colorchange_add_m"));
|
||||
add_color_change_menu_item->SetBitmap(create_scaled_bitmap("colorchange_add_m"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1220,7 +1262,7 @@ std::array<int, 2> Control::get_active_extruders_for_tick(int tick) const
|
|||
|
||||
auto it = m_ticks.ticks.lower_bound(TickCode{tick});
|
||||
|
||||
if (it->tick == tick) // current tick exists
|
||||
if (it != m_ticks.ticks.end() && it->tick == tick) // current tick exists
|
||||
extruders[1] = it->extruder;
|
||||
|
||||
while (it != m_ticks.ticks.begin()) {
|
||||
|
|
@ -1235,10 +1277,10 @@ std::array<int, 2> Control::get_active_extruders_for_tick(int tick) const
|
|||
}
|
||||
|
||||
// Get used extruders for tick.
|
||||
// Means all extruders(toools) will be used during printing from current tick to the end
|
||||
std::set<int> Control::get_used_extruders_for_tick(int tick) const
|
||||
// Means all extruders(tools) which will be used during printing from current tick to the end
|
||||
std::set<int> TickCodeInfo::get_used_extruders_for_tick(int tick, int only_extruder, double print_z) const
|
||||
{
|
||||
if (m_mode == t_mode::MultiExtruder)
|
||||
if (mode == t_mode::MultiExtruder)
|
||||
{
|
||||
// #ys_FIXME: get tool ordering from _correct_ place
|
||||
const ToolOrdering& tool_ordering = GUI::wxGetApp().plater()->fff_print().get_tool_ordering();
|
||||
|
|
@ -1248,7 +1290,7 @@ std::set<int> Control::get_used_extruders_for_tick(int tick) const
|
|||
|
||||
std::set<int> used_extruders;
|
||||
|
||||
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), LayerTools(m_values[tick]));
|
||||
auto it_layer_tools = std::lower_bound(tool_ordering.begin(), tool_ordering.end(), LayerTools(print_z));
|
||||
for (; it_layer_tools != tool_ordering.end(); ++it_layer_tools)
|
||||
{
|
||||
const std::vector<unsigned>& extruders = it_layer_tools->extruders;
|
||||
|
|
@ -1259,12 +1301,11 @@ std::set<int> Control::get_used_extruders_for_tick(int tick) const
|
|||
return used_extruders;
|
||||
}
|
||||
|
||||
const int default_initial_extruder = m_mode == t_mode::MultiAsSingle ? std::max(m_only_extruder, 1) : 1;
|
||||
if (m_ticks.empty())
|
||||
const int default_initial_extruder = mode == t_mode::MultiAsSingle ? std::max(only_extruder, 1) : 1;
|
||||
if (ticks.empty())
|
||||
return {default_initial_extruder};
|
||||
|
||||
std::set<int> used_extruders;
|
||||
const std::set<TickCode>& ticks = m_ticks.ticks;
|
||||
|
||||
auto it_start = ticks.lower_bound(TickCode{tick});
|
||||
auto it = it_start;
|
||||
|
|
@ -1341,7 +1382,7 @@ void Control::OnRightUp(wxMouseEvent& event)
|
|||
append_menu_item(&menu, wxID_ANY, it->gcode == ColorChangeCode ? _(L("Edit color")) :
|
||||
it->gcode == PausePrintCode ? _(L("Edit pause print message")) :
|
||||
_(L("Edit custom G-code")), "",
|
||||
[this](wxCommandEvent&) { edit_tick(); }, "edit_uni", &menu);
|
||||
[this](wxCommandEvent&) { edit_tick(); }, "edit_uni", &menu, []() {return true; }, this);
|
||||
|
||||
if (it->gcode == ColorChangeCode && m_mode == t_mode::MultiAsSingle)
|
||||
append_change_extruder_menu_item(&menu, true);
|
||||
|
|
@ -1350,7 +1391,7 @@ void Control::OnRightUp(wxMouseEvent& event)
|
|||
it->gcode == ToolChangeCode ? _(L("Delete tool change")) :
|
||||
it->gcode == PausePrintCode ? _(L("Delete pause print")) :
|
||||
_(L("Delete custom G-code")), "",
|
||||
[this](wxCommandEvent&) { delete_current_tick();}, "colorchange_del_f", &menu);
|
||||
[this](wxCommandEvent&) { delete_current_tick();}, "colorchange_del_f", &menu, []() {return true; }, this);
|
||||
|
||||
GUI::wxGetApp().plater()->PopupMenu(&menu);
|
||||
|
||||
|
|
@ -1379,6 +1420,28 @@ static std::string get_new_color(const std::string& color)
|
|||
return "";
|
||||
}
|
||||
|
||||
// To avoid get an empty string from wxTextEntryDialog
|
||||
// Let disable OK button, if TextCtrl is empty
|
||||
static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg)
|
||||
{
|
||||
// detect TextCtrl and OK button
|
||||
wxTextCtrl* textctrl {nullptr};
|
||||
wxWindowList& dlg_items = dlg->GetChildren();
|
||||
for (auto item : dlg_items) {
|
||||
textctrl = dynamic_cast<wxTextCtrl*>(item);
|
||||
if (textctrl)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!textctrl)
|
||||
return;
|
||||
|
||||
wxButton* btn_OK = static_cast<wxButton*>(dlg->FindWindowById(wxID_OK));
|
||||
btn_OK->Bind(wxEVT_UPDATE_UI, [textctrl](wxUpdateUIEvent& evt) {
|
||||
evt.Enable(!textctrl->IsEmpty());
|
||||
}, btn_OK->GetId());
|
||||
}
|
||||
|
||||
static std::string get_custom_code(const std::string& code_in, double height)
|
||||
{
|
||||
wxString msg_text = from_u8(_utf8(L("Enter custom G-code used on current layer"))) + ":";
|
||||
|
|
@ -1387,7 +1450,9 @@ static std::string get_custom_code(const std::string& code_in, double height)
|
|||
// get custom gcode
|
||||
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, code_in,
|
||||
wxTextEntryDialogStyle | wxTE_MULTILINE);
|
||||
if (dlg.ShowModal() != wxID_OK || dlg.GetValue().IsEmpty())
|
||||
upgrade_text_entry_dialog(&dlg);
|
||||
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return "";
|
||||
|
||||
return dlg.GetValue().ToStdString();
|
||||
|
|
@ -1401,6 +1466,8 @@ static std::string get_pause_print_msg(const std::string& msg_in, double height)
|
|||
// get custom gcode
|
||||
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, from_u8(msg_in),
|
||||
wxTextEntryDialogStyle);
|
||||
upgrade_text_entry_dialog(&dlg);
|
||||
|
||||
if (dlg.ShowModal() != wxID_OK || dlg.GetValue().IsEmpty())
|
||||
return "";
|
||||
|
||||
|
|
@ -1759,6 +1826,61 @@ bool TickCodeInfo::has_tick_with_code(const std::string& gcode)
|
|||
return false;
|
||||
}
|
||||
|
||||
ConflictType TickCodeInfo::is_conflict_tick(const TickCode& tick, t_mode out_mode, int only_extruder, double print_z)
|
||||
{
|
||||
if ((tick.gcode == ColorChangeCode && (
|
||||
(mode == t_mode::SingleExtruder && out_mode == t_mode::MultiExtruder ) ||
|
||||
(mode == t_mode::MultiExtruder && out_mode == t_mode::SingleExtruder) )) ||
|
||||
(tick.gcode == ToolChangeCode &&
|
||||
(mode == t_mode::MultiAsSingle && out_mode != t_mode::MultiAsSingle)) )
|
||||
return ctModeConflict;
|
||||
|
||||
// check ColorChange tick
|
||||
if (tick.gcode == ColorChangeCode)
|
||||
{
|
||||
// We should mark a tick as a "MeaninglessColorChange",
|
||||
// if it has a ColorChange for unused extruder from current print to end of the print
|
||||
std::set<int> used_extruders_for_tick = get_used_extruders_for_tick(tick.tick, only_extruder, print_z);
|
||||
|
||||
if (used_extruders_for_tick.find(tick.extruder) == used_extruders_for_tick.end())
|
||||
return ctMeaninglessColorChange;
|
||||
|
||||
// We should mark a tick as a "Redundant",
|
||||
// if it has a ColorChange for extruder that has not been used before
|
||||
if (mode == t_mode::MultiAsSingle && tick.extruder != std::max<int>(only_extruder, 1) )
|
||||
{
|
||||
auto it = ticks.lower_bound( tick );
|
||||
if (it == ticks.begin() && it->gcode == ToolChangeCode && tick.extruder == it->extruder)
|
||||
return ctNone;
|
||||
|
||||
while (it != ticks.begin()) {
|
||||
--it;
|
||||
if (it->gcode == ToolChangeCode && tick.extruder == it->extruder)
|
||||
return ctNone;
|
||||
}
|
||||
|
||||
return ctRedundant;
|
||||
}
|
||||
}
|
||||
|
||||
// check ToolChange tick
|
||||
if (mode == t_mode::MultiAsSingle && tick.gcode == ToolChangeCode)
|
||||
{
|
||||
// We should mark a tick as a "MeaninglessToolChange",
|
||||
// if it has a ToolChange to the same extruder
|
||||
|
||||
auto it = ticks.find(tick);
|
||||
if (it == ticks.begin())
|
||||
return tick.extruder == std::max<int>(only_extruder, 1) ? ctMeaninglessToolChange : ctNone;
|
||||
|
||||
--it;
|
||||
if (it->gcode == ToolChangeCode && tick.extruder == it->extruder)
|
||||
return ctMeaninglessToolChange;
|
||||
}
|
||||
|
||||
return ctNone;
|
||||
}
|
||||
|
||||
} // DoubleSlider
|
||||
|
||||
} // Slic3r
|
||||
|
|
|
|||
|
|
@ -39,6 +39,15 @@ enum IconFocus {
|
|||
ifCog
|
||||
};
|
||||
|
||||
enum ConflictType
|
||||
{
|
||||
ctNone,
|
||||
ctModeConflict,
|
||||
ctMeaninglessColorChange,
|
||||
ctMeaninglessToolChange,
|
||||
ctRedundant
|
||||
};
|
||||
|
||||
using t_mode = CustomGCode::Mode;
|
||||
|
||||
struct TickCode
|
||||
|
|
@ -73,7 +82,13 @@ public:
|
|||
void switch_code(const std::string& code_from, const std::string& code_to);
|
||||
bool switch_code_for_tick(std::set<TickCode>::iterator it, const std::string& code_to, const int extruder);
|
||||
void erase_all_ticks_with_code(const std::string& gcode);
|
||||
bool has_tick_with_code(const std::string& gcode);
|
||||
|
||||
bool has_tick_with_code(const std::string& gcode);
|
||||
ConflictType is_conflict_tick(const TickCode& tick, t_mode out_mode, int only_extruder, double print_z);
|
||||
|
||||
// Get used extruders for tick.
|
||||
// Means all extruders(tools) which will be used during printing from current tick to the end
|
||||
std::set<int> get_used_extruders_for_tick(int tick, int only_extruder, double print_z) const;
|
||||
|
||||
void suppress_plus (bool suppress) { m_suppress_plus = suppress; }
|
||||
void suppress_minus(bool suppress) { m_suppress_minus = suppress; }
|
||||
|
|
@ -230,7 +245,7 @@ protected:
|
|||
private:
|
||||
|
||||
bool is_point_in_rect(const wxPoint& pt, const wxRect& rect);
|
||||
int is_point_near_tick(const wxPoint& pt);
|
||||
int get_tick_near_point(const wxPoint& pt);
|
||||
|
||||
double get_scroll_step();
|
||||
wxString get_label(const SelectedSlider& selection) const;
|
||||
|
|
@ -251,10 +266,6 @@ private:
|
|||
// Use those values to disable selection of active extruders
|
||||
std::array<int, 2> get_active_extruders_for_tick(int tick) const;
|
||||
|
||||
// Get used extruders for tick.
|
||||
// Means all extruders(toools) will be used during printing from current tick to the end
|
||||
std::set<int> get_used_extruders_for_tick(int tick) const;
|
||||
|
||||
void post_ticks_changed_event(const std::string& gcode = "");
|
||||
bool check_ticks_changed_event(const std::string& gcode);
|
||||
|
||||
|
|
|
|||
|
|
@ -1256,6 +1256,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
|||
wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent);
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
|
||||
|
|
@ -1710,6 +1711,13 @@ void GLCanvas3D::render()
|
|||
}
|
||||
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
// Probably due to different order of events on Linux/GTK2, when one switched from 3D scene
|
||||
// to preview, this was called before canvas had its final size. It reported zero width
|
||||
// and the viewport was set incorrectly, leading to tripping glAsserts further down
|
||||
// the road (in apply_projection). That's why the minimum size is forced to 10.
|
||||
m_camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height()));
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
|
||||
if (m_camera.requires_zoom_to_bed)
|
||||
{
|
||||
|
|
@ -2647,6 +2655,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
|
||||
break;
|
||||
case WXK_ESCAPE: { deselect_all(); break; }
|
||||
case WXK_F5: { post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK)); break; }
|
||||
case '0': { select_view("iso"); break; }
|
||||
case '1': { select_view("top"); break; }
|
||||
case '2': { select_view("bottom"); break; }
|
||||
|
|
@ -3839,8 +3848,13 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool
|
|||
#if ENABLE_6DOF_CAMERA
|
||||
camera.set_scene_box(scene_bounding_box());
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||
camera.zoom_to_volumes(visible_volumes);
|
||||
#else
|
||||
camera.zoom_to_volumes(visible_volumes, thumbnail_data.width, thumbnail_data.height);
|
||||
camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
camera.apply_view_matrix();
|
||||
|
||||
double near_z = -1.0;
|
||||
|
|
@ -4431,8 +4445,10 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
|
|||
// ensures that this canvas is current
|
||||
_set_current();
|
||||
|
||||
#if !ENABLE_6DOF_CAMERA
|
||||
// updates camera
|
||||
m_camera.apply_viewport(0, 0, w, h);
|
||||
#endif // !ENABLE_6DOF_CAMERA
|
||||
}
|
||||
|
||||
BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_bed_model) const
|
||||
|
|
@ -4456,8 +4472,12 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_be
|
|||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
void GLCanvas3D::_zoom_to_box(const BoundingBoxf3& box, double margin_factor)
|
||||
{
|
||||
#if ENABLE_6DOF_CAMERA
|
||||
m_camera.zoom_to_box(box, margin_factor);
|
||||
#else
|
||||
const Size& cnv_size = get_canvas_size();
|
||||
m_camera.zoom_to_box(box, cnv_size.get_width(), cnv_size.get_height(), margin_factor);
|
||||
#endif // ENABLE_6DOF_CAMERA
|
||||
m_dirty = true;
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent);
|
|||
wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent);
|
||||
|
||||
class GLCanvas3D
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -960,8 +960,11 @@ void GUI_App::load_current_presets()
|
|||
this->plater()->set_printer_technology(printer_technology);
|
||||
for (Tab *tab : tabs_list)
|
||||
if (tab->supports_printer_technology(printer_technology)) {
|
||||
if (tab->type() == Preset::TYPE_PRINTER)
|
||||
if (tab->type() == Preset::TYPE_PRINTER) {
|
||||
static_cast<TabPrinter*>(tab)->update_pages();
|
||||
// Mark the plater to update print bed by tab->load_current_preset() from Plater::on_config_change().
|
||||
this->plater()->force_print_bed_update();
|
||||
}
|
||||
tab->load_current_preset();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,20 +90,20 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
// see note in PresetBundle::load_compatible_bitmaps()
|
||||
|
||||
// ptFFF
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(nullptr, "layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(nullptr, "infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(nullptr, "support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(nullptr, "time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
CATEGORY_ICON[L("Wipe options")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(nullptr, "skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(nullptr, "time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(nullptr, "wrench");
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel");
|
||||
CATEGORY_ICON[L("Wipe options")] = create_scaled_bitmap("funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wrench");
|
||||
// ptSLA
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(nullptr, "support"/*"sla_supports"*/);
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(nullptr, "pad");
|
||||
CATEGORY_ICON[L("Hollowing")] = create_scaled_bitmap(nullptr, "hollowing");
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("support"/*"sla_supports"*/);
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("pad");
|
||||
CATEGORY_ICON[L("Hollowing")] = create_scaled_bitmap("hollowing");
|
||||
}
|
||||
|
||||
// create control
|
||||
|
|
@ -230,9 +230,9 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
// So the postponed EnsureVisible() call is planned for an item, which may not exist at the Idle processing time, if this wxEVT_SIZE
|
||||
// event is succeeded by a delete of the currently active item. We are trying our luck by postponing the wxEVT_SIZE triggered EnsureVisible(),
|
||||
// which seems to be working as of now.
|
||||
this->CallAfter([this](){ this->EnsureVisible(this->GetCurrentItem()); });
|
||||
this->CallAfter([this](){ ensure_current_item_visible(); });
|
||||
#else
|
||||
this->EnsureVisible(this->GetCurrentItem());
|
||||
ensure_current_item_visible();
|
||||
#endif
|
||||
e.Skip();
|
||||
}));
|
||||
|
|
@ -265,7 +265,7 @@ void ObjectList::create_objects_ctrl()
|
|||
|
||||
// column ItemName(Icon+Text) of the view control:
|
||||
// And Icon can be consisting of several bitmaps
|
||||
AppendColumn(new wxDataViewColumn(_(L("Name")), new BitmapTextRenderer(),
|
||||
AppendColumn(new wxDataViewColumn(_(L("Name")), new BitmapTextRenderer(this),
|
||||
colName, 20*em, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
|
||||
|
||||
// column PrintableProperty (Icon) of the view control:
|
||||
|
|
@ -559,10 +559,10 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const
|
|||
|
||||
void ObjectList::init_icons()
|
||||
{
|
||||
m_bmp_solidmesh = ScalableBitmap(nullptr, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART) ].second);
|
||||
m_bmp_modifiermesh = ScalableBitmap(nullptr, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::PARAMETER_MODIFIER)].second);
|
||||
m_bmp_support_enforcer = ScalableBitmap(nullptr, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_ENFORCER) ].second);
|
||||
m_bmp_support_blocker = ScalableBitmap(nullptr, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER) ].second);
|
||||
m_bmp_solidmesh = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::MODEL_PART) ].second);
|
||||
m_bmp_modifiermesh = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::PARAMETER_MODIFIER)].second);
|
||||
m_bmp_support_enforcer = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_ENFORCER) ].second);
|
||||
m_bmp_support_blocker = ScalableBitmap(this, ADD_VOLUME_MENU_ITEMS[int(ModelVolumeType::SUPPORT_BLOCKER) ].second);
|
||||
|
||||
m_bmp_vector.reserve(4); // bitmaps for different types of parts
|
||||
m_bmp_vector.push_back(&m_bmp_solidmesh.bmp());
|
||||
|
|
@ -575,12 +575,12 @@ void ObjectList::init_icons()
|
|||
m_objects_model->SetVolumeBitmaps(m_bmp_vector);
|
||||
|
||||
// init icon for manifold warning
|
||||
m_bmp_manifold_warning = ScalableBitmap(nullptr, "exclamation");
|
||||
m_bmp_manifold_warning = ScalableBitmap(this, "exclamation");
|
||||
// Set warning bitmap for the model
|
||||
m_objects_model->SetWarningBitmap(&m_bmp_manifold_warning.bmp());
|
||||
|
||||
// init bitmap for "Add Settings" context menu
|
||||
m_bmp_cog = ScalableBitmap(nullptr, "cog");
|
||||
m_bmp_cog = ScalableBitmap(this, "cog");
|
||||
}
|
||||
|
||||
void ObjectList::msw_rescale_icons()
|
||||
|
|
@ -607,23 +607,20 @@ void ObjectList::msw_rescale_icons()
|
|||
|
||||
// Update CATEGORY_ICON according to new scale
|
||||
{
|
||||
// Note: `this` isn't passed to create_scaled_bitmap() here because of bugs in the widget,
|
||||
// see note in PresetBundle::load_compatible_bitmaps()
|
||||
|
||||
// ptFFF
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(nullptr, "layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(nullptr, "infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(nullptr, "support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(nullptr, "time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
CATEGORY_ICON[L("Wipe options")] = create_scaled_bitmap(nullptr, "funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(nullptr, "skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(nullptr, "time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(nullptr, "wrench");
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel");
|
||||
CATEGORY_ICON[L("Wipe options")] = create_scaled_bitmap("funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wrench");
|
||||
// ptSLA
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(nullptr, "support"/*"sla_supports"*/);
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(nullptr, "pad");
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("support"/*"sla_supports"*/);
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("pad");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1003,14 +1000,13 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
const bool mult_sel = multiple_selection();
|
||||
|
||||
if ((mult_sel && !selected_instances_of_same_object()) ||
|
||||
(!mult_sel && (GetSelection() != item)) ||
|
||||
m_objects_model->GetParent(item) == wxDataViewItem(nullptr) ) {
|
||||
(!mult_sel && (GetSelection() != item)) ) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
const ItemType& type = m_objects_model->GetItemType(item);
|
||||
if (!(type & (itVolume | itInstance))) {
|
||||
if (!(type & (itVolume | itObject | itInstance))) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1024,11 +1020,13 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
for (auto sel : sels )
|
||||
sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel));
|
||||
}
|
||||
else
|
||||
else if (type & itObject)
|
||||
m_dragged_data.init(m_objects_model->GetIdByItem(item), type);
|
||||
else
|
||||
m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),
|
||||
type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
|
||||
type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
|
||||
m_objects_model->GetInstanceIdByItem(item),
|
||||
type);
|
||||
type);
|
||||
|
||||
/* Under MSW or OSX, DnD moves an item to the place of another selected item
|
||||
* But under GTK, DnD moves an item between another two items.
|
||||
|
|
@ -1049,10 +1047,20 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
|
|||
|
||||
bool ObjectList::can_drop(const wxDataViewItem& item) const
|
||||
{
|
||||
return (m_dragged_data.type() == itInstance && !item.IsOk()) ||
|
||||
(m_dragged_data.type() == itVolume && item.IsOk() &&
|
||||
m_objects_model->GetItemType(item) == itVolume &&
|
||||
m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item));
|
||||
// move instance(s) or object on "empty place" of ObjectList
|
||||
if ( (m_dragged_data.type() & (itInstance | itObject)) && !item.IsOk() )
|
||||
return true;
|
||||
|
||||
// type of moved item should be the same as a "destination" item
|
||||
if (!item.IsOk() || !(m_dragged_data.type() & (itVolume|itObject)) ||
|
||||
m_objects_model->GetItemType(item) != m_dragged_data.type() )
|
||||
return false;
|
||||
|
||||
// move volumes inside one object only
|
||||
if (m_dragged_data.type() & itVolume)
|
||||
return m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectList::OnDropPossible(wxDataViewEvent &event)
|
||||
|
|
@ -1082,9 +1090,6 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
return;
|
||||
}
|
||||
|
||||
const int from_volume_id = m_dragged_data.sub_obj_idx();
|
||||
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
|
||||
|
||||
// It looks like a fixed in current version of the wxWidgets
|
||||
// #ifdef __WXGTK__
|
||||
// /* Under GTK, DnD moves an item between another two items.
|
||||
|
|
@ -1096,14 +1101,33 @@ void ObjectList::OnDrop(wxDataViewEvent &event)
|
|||
|
||||
take_snapshot(_((m_dragged_data.type() == itVolume) ? L("Volumes in Object reordered") : L("Object reordered")));
|
||||
|
||||
auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
|
||||
auto delta = to_volume_id < from_volume_id ? -1 : 1;
|
||||
int cnt = 0;
|
||||
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
||||
std::swap(volumes[id], volumes[id + delta]);
|
||||
if (m_dragged_data.type() & itVolume)
|
||||
{
|
||||
int from_volume_id = m_dragged_data.sub_obj_idx();
|
||||
int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
|
||||
int delta = to_volume_id < from_volume_id ? -1 : 1;
|
||||
|
||||
select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id,
|
||||
m_objects_model->GetParent(item)));
|
||||
auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
|
||||
|
||||
int cnt = 0;
|
||||
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++)
|
||||
std::swap(volumes[id], volumes[id + delta]);
|
||||
|
||||
select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, m_objects_model->GetParent(item)));
|
||||
|
||||
}
|
||||
else if (m_dragged_data.type() & itObject)
|
||||
{
|
||||
int from_obj_id = m_dragged_data.obj_idx();
|
||||
int to_obj_id = item.IsOk() ? m_objects_model->GetIdByItem(item) : ((int)m_objects->size()-1);
|
||||
int delta = to_obj_id < from_obj_id ? -1 : 1;
|
||||
|
||||
int cnt = 0;
|
||||
for (int id = from_obj_id; cnt < abs(from_obj_id - to_obj_id); id += delta, cnt++)
|
||||
std::swap((*m_objects)[id], (*m_objects)[id + delta]);
|
||||
|
||||
select_item(m_objects_model->ReorganizeObjects(from_obj_id, to_obj_id));
|
||||
}
|
||||
|
||||
changed_object(m_dragged_data.obj_idx());
|
||||
|
||||
|
|
@ -1741,7 +1765,8 @@ void ObjectList::create_instance_popupmenu(wxMenu*menu)
|
|||
void ObjectList::create_default_popupmenu(wxMenu*menu)
|
||||
{
|
||||
wxMenu* sub_menu = append_submenu_add_generic(menu, ModelVolumeType::INVALID);
|
||||
append_submenu(menu, sub_menu, wxID_ANY, _(L("Add Shape")), "", "add_part");
|
||||
append_submenu(menu, sub_menu, wxID_ANY, _(L("Add Shape")), "", "add_part",
|
||||
[](){return true;}, this);
|
||||
}
|
||||
|
||||
wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
|
||||
|
|
@ -3162,7 +3187,7 @@ void ObjectList::update_selections()
|
|||
select_items(sels);
|
||||
|
||||
// Scroll selected Item in the middle of an object list
|
||||
this->EnsureVisible(this->GetCurrentItem());
|
||||
ensure_current_item_visible();
|
||||
}
|
||||
|
||||
void ObjectList::update_selections_on_canvas()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/dataview.h>
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
|
||||
#include "Event.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "ObjectDataViewModel.hpp"
|
||||
|
||||
class wxBoxSizer;
|
||||
class wxBitmapComboBox;
|
||||
|
|
@ -171,6 +173,12 @@ private:
|
|||
SettingsBundle m_freq_settings_sla;
|
||||
#endif
|
||||
|
||||
inline void ensure_current_item_visible()
|
||||
{
|
||||
if (const auto &item = this->GetCurrentItem())
|
||||
this->EnsureVisible(item);
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectList(wxWindow* parent);
|
||||
~ObjectList();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include <wx/stattext.h>
|
||||
#include <wx/sizer.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ void GLGizmoCut::update_max_z(const Selection& selection) const
|
|||
void GLGizmoCut::set_cut_z(double cut_z) const
|
||||
{
|
||||
// Clamp the plane to the object's bounding box
|
||||
m_cut_z = std::max(0.0, std::min(m_max_z, cut_z));
|
||||
m_cut_z = std::clamp(cut_z, 0.0, m_max_z);
|
||||
}
|
||||
|
||||
void GLGizmoCut::perform_cut(const Selection& selection)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ class GLGizmoCut : public GLGizmoBase
|
|||
public:
|
||||
GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
double get_cut_z() const { return m_cut_z; }
|
||||
void set_cut_z(double cut_z) const;
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
virtual void on_load(cereal::BinaryInputArchive& ar) { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
|
||||
|
|
@ -40,7 +43,6 @@ protected:
|
|||
|
||||
private:
|
||||
void update_max_z(const Selection& selection) const;
|
||||
void set_cut_z(double cut_z) const;
|
||||
void perform_cut(const Selection& selection);
|
||||
double calc_projection(const Linef3& mouse_ray) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
processed = true;
|
||||
}
|
||||
else if (evt.Dragging() && (m_parent.get_move_volume_id() != -1) && (m_current == SlaSupports || m_current == Hollow))
|
||||
// don't allow dragging objects with the Sla gizmo on
|
||||
// don't allow dragging objects with the Sla gizmo on
|
||||
processed = true;
|
||||
else if (evt.Dragging() && (m_current == SlaSupports || m_current == Hollow) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
|
||||
{
|
||||
|
|
@ -557,12 +557,9 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
|
|||
else if (evt.LeftUp() && is_dragging())
|
||||
{
|
||||
switch (m_current) {
|
||||
case Move : m_parent.do_move(L("Gizmo-Move"));
|
||||
break;
|
||||
case Scale : m_parent.do_scale(L("Gizmo-Scale"));
|
||||
break;
|
||||
case Rotate : m_parent.do_rotate(L("Gizmo-Rotate"));
|
||||
break;
|
||||
case Move : m_parent.do_move(L("Gizmo-Move")); break;
|
||||
case Scale : m_parent.do_scale(L("Gizmo-Scale")); break;
|
||||
case Rotate : m_parent.do_rotate(L("Gizmo-Rotate")); break;
|
||||
default : break;
|
||||
}
|
||||
|
||||
|
|
@ -779,6 +776,64 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
|
|||
processed = true;
|
||||
}
|
||||
}
|
||||
else if (m_current == Move)
|
||||
{
|
||||
auto do_move = [this, &processed](const Vec3d& displacement) {
|
||||
Selection& selection = m_parent.get_selection();
|
||||
selection.start_dragging();
|
||||
selection.translate(displacement);
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
m_parent.do_move(L("Gizmo-Move"));
|
||||
m_parent.set_as_dirty();
|
||||
processed = true;
|
||||
};
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_NUMPAD_LEFT: case WXK_LEFT: { do_move(-Vec3d::UnitX()); break; }
|
||||
case WXK_NUMPAD_RIGHT: case WXK_RIGHT: { do_move(Vec3d::UnitX()); break; }
|
||||
case WXK_NUMPAD_UP: case WXK_UP: { do_move(Vec3d::UnitY()); break; }
|
||||
case WXK_NUMPAD_DOWN: case WXK_DOWN: { do_move(-Vec3d::UnitY()); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
else if (m_current == Rotate)
|
||||
{
|
||||
auto do_rotate = [this, &processed](const Vec3d& rotation) {
|
||||
Selection& selection = m_parent.get_selection();
|
||||
selection.start_dragging();
|
||||
selection.rotate(rotation, TransformationType(TransformationType::World_Relative_Joint));
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
m_parent.do_rotate(L("Gizmo-Rotate"));
|
||||
m_parent.set_as_dirty();
|
||||
processed = true;
|
||||
};
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_NUMPAD_LEFT: case WXK_LEFT: { do_rotate(Vec3d(0.0, 0.0, 0.5 * M_PI)); break; }
|
||||
case WXK_NUMPAD_RIGHT: case WXK_RIGHT: { do_rotate(-Vec3d(0.0, 0.0, 0.5 * M_PI)); break; }
|
||||
case WXK_NUMPAD_UP: case WXK_UP: { do_rotate(Vec3d(0.0, 0.0, 0.25 * M_PI)); break; }
|
||||
case WXK_NUMPAD_DOWN: case WXK_DOWN: { do_rotate(-Vec3d(0.0, 0.0, 0.25 * M_PI)); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
else if (m_current == Cut)
|
||||
{
|
||||
auto do_move = [this, &processed](double delta_z) {
|
||||
GLGizmoCut* cut = dynamic_cast<GLGizmoCut*>(get_current());
|
||||
cut->set_cut_z(delta_z + cut->get_cut_z());
|
||||
m_parent.set_as_dirty();
|
||||
processed = true;
|
||||
};
|
||||
|
||||
switch (keyCode)
|
||||
{
|
||||
case WXK_NUMPAD_UP: case WXK_UP: { do_move(1.0); break; }
|
||||
case WXK_NUMPAD_DOWN: case WXK_DOWN: { do_move(-1.0); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
// if (processed)
|
||||
// m_parent.set_cursor(GLCanvas3D::Standard);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||
/* Load default preset bitmaps before a tabpanel initialization,
|
||||
* but after filling of an em_unit value
|
||||
*/
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps(this);
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
|
||||
// initialize tabpanel and menubar
|
||||
init_tabpanel();
|
||||
|
|
@ -345,7 +345,7 @@ void MainFrame::on_dpi_changed(const wxRect &suggested_rect)
|
|||
/* Load default preset bitmaps before a tabpanel initialization,
|
||||
* but after filling of an em_unit value
|
||||
*/
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps(this);
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
|
||||
// update Plater
|
||||
wxGetApp().plater()->msw_rescale();
|
||||
|
|
@ -578,6 +578,11 @@ void MainFrame::init_menubar()
|
|||
append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "V",
|
||||
_(L("Paste clipboard")), [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); },
|
||||
"paste_menu", nullptr, [this](){return m_plater->can_paste_from_clipboard(); }, this);
|
||||
|
||||
editMenu->AppendSeparator();
|
||||
append_menu_item(editMenu, wxID_ANY, _(L("Re&load from disk")) + sep + "F5",
|
||||
_(L("Reload the plater from disk")), [this](wxCommandEvent&) { m_plater->reload_all_from_disk(); },
|
||||
"", nullptr, [this]() {return !m_plater->model().objects.empty(); }, this);
|
||||
}
|
||||
|
||||
// Window menu
|
||||
|
|
@ -728,7 +733,7 @@ void MainFrame::update_menubar()
|
|||
m_changeable_menu_items[miSend] ->SetItemLabel((is_fff ? _(L("S&end G-code")) : _(L("S&end to print"))) + dots + "\tCtrl+Shift+G");
|
||||
|
||||
m_changeable_menu_items[miMaterialTab] ->SetItemLabel((is_fff ? _(L("&Filament Settings Tab")) : _(L("Mate&rial Settings Tab"))) + "\tCtrl+3");
|
||||
m_changeable_menu_items[miMaterialTab] ->SetBitmap(create_scaled_bitmap(this, is_fff ? "spool": "resin"));
|
||||
m_changeable_menu_items[miMaterialTab] ->SetBitmap(create_scaled_bitmap(is_fff ? "spool": "resin"));
|
||||
}
|
||||
|
||||
// To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||
rightsizer->Add(btn_sizer, 0, wxALIGN_RIGHT);
|
||||
|
||||
if (! bitmap.IsOk()) {
|
||||
bitmap = create_scaled_bitmap(this, "PrusaSlicer_192px.png", 192);
|
||||
bitmap = create_scaled_bitmap("PrusaSlicer_192px.png", this, 192);
|
||||
}
|
||||
|
||||
logo = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
|
||||
|
|
@ -99,7 +99,7 @@ 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, "PrusaSlicer_192px_grayscale.png", 192));
|
||||
logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 192));
|
||||
|
||||
SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit()));
|
||||
Fit();
|
||||
|
|
|
|||
1764
src/slic3r/GUI/ObjectDataViewModel.cpp
Normal file
1764
src/slic3r/GUI/ObjectDataViewModel.cpp
Normal file
File diff suppressed because it is too large
Load diff
516
src/slic3r/GUI/ObjectDataViewModel.hpp
Normal file
516
src/slic3r/GUI/ObjectDataViewModel.hpp
Normal file
|
|
@ -0,0 +1,516 @@
|
|||
#ifndef slic3r_GUI_ObjectDataViewModel_hpp_
|
||||
#define slic3r_GUI_ObjectDataViewModel_hpp_
|
||||
|
||||
#include <wx/dataview.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class ModelVolumeType : int;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
typedef double coordf_t;
|
||||
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DataViewBitmapText: helper class used by BitmapTextRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class DataViewBitmapText : public wxObject
|
||||
{
|
||||
public:
|
||||
DataViewBitmapText( const wxString &text = wxEmptyString,
|
||||
const wxBitmap& bmp = wxNullBitmap) :
|
||||
m_text(text),
|
||||
m_bmp(bmp)
|
||||
{ }
|
||||
|
||||
DataViewBitmapText(const DataViewBitmapText &other)
|
||||
: wxObject(),
|
||||
m_text(other.m_text),
|
||||
m_bmp(other.m_bmp)
|
||||
{ }
|
||||
|
||||
void SetText(const wxString &text) { m_text = text; }
|
||||
wxString GetText() const { return m_text; }
|
||||
void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; }
|
||||
const wxBitmap &GetBitmap() const { return m_bmp; }
|
||||
|
||||
bool IsSameAs(const DataViewBitmapText& other) const {
|
||||
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
|
||||
}
|
||||
|
||||
bool operator==(const DataViewBitmapText& other) const {
|
||||
return IsSameAs(other);
|
||||
}
|
||||
|
||||
bool operator!=(const DataViewBitmapText& other) const {
|
||||
return !IsSameAs(other);
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_text;
|
||||
wxBitmap m_bmp;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(DataViewBitmapText);
|
||||
};
|
||||
DECLARE_VARIANT_OBJECT(DataViewBitmapText)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BitmapTextRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
class BitmapTextRenderer : public wxDataViewRenderer
|
||||
#else
|
||||
class BitmapTextRenderer : public wxDataViewCustomRenderer
|
||||
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
{
|
||||
public:
|
||||
BitmapTextRenderer(wxWindow* parent,
|
||||
wxDataViewCellMode mode =
|
||||
#ifdef __WXOSX__
|
||||
wxDATAVIEW_CELL_INERT
|
||||
#else
|
||||
wxDATAVIEW_CELL_EDITABLE
|
||||
#endif
|
||||
|
||||
, int align = wxDVR_DEFAULT_ALIGNMENT
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
);
|
||||
#else
|
||||
) :
|
||||
wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align),
|
||||
m_parent(parent)
|
||||
{}
|
||||
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
|
||||
bool SetValue(const wxVariant& value);
|
||||
bool GetValue(wxVariant& value) const;
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
|
||||
virtual wxString GetAccessibleDescription() const override;
|
||||
#endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
|
||||
virtual bool Render(wxRect cell, wxDC* dc, int state) override;
|
||||
virtual wxSize GetSize() const override;
|
||||
|
||||
bool HasEditorCtrl() const override
|
||||
{
|
||||
#ifdef __WXOSX__
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
wxWindow* CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) override;
|
||||
bool GetValueFromEditorCtrl(wxWindow* ctrl,
|
||||
wxVariant& value) override;
|
||||
bool WasCanceled() const { return m_was_unusable_symbol; }
|
||||
|
||||
private:
|
||||
DataViewBitmapText m_value;
|
||||
bool m_was_unusable_symbol{ false };
|
||||
wxWindow* m_parent{ nullptr };
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BitmapChoiceRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BitmapChoiceRenderer : public wxDataViewCustomRenderer
|
||||
{
|
||||
public:
|
||||
BitmapChoiceRenderer(wxDataViewCellMode mode =
|
||||
#ifdef __WXOSX__
|
||||
wxDATAVIEW_CELL_INERT
|
||||
#else
|
||||
wxDATAVIEW_CELL_EDITABLE
|
||||
#endif
|
||||
, int align = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
|
||||
) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {}
|
||||
|
||||
bool SetValue(const wxVariant& value);
|
||||
bool GetValue(wxVariant& value) const;
|
||||
|
||||
virtual bool Render(wxRect cell, wxDC* dc, int state) override;
|
||||
virtual wxSize GetSize() const override;
|
||||
|
||||
bool HasEditorCtrl() const override { return true; }
|
||||
wxWindow* CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) override;
|
||||
bool GetValueFromEditorCtrl(wxWindow* ctrl,
|
||||
wxVariant& value) override;
|
||||
|
||||
private:
|
||||
DataViewBitmapText m_value;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ObjectDataViewModelNode: a node inside ObjectDataViewModel
|
||||
// ----------------------------------------------------------------------------
|
||||
enum ItemType {
|
||||
itUndef = 0,
|
||||
itObject = 1,
|
||||
itVolume = 2,
|
||||
itInstanceRoot = 4,
|
||||
itInstance = 8,
|
||||
itSettings = 16,
|
||||
itLayerRoot = 32,
|
||||
itLayer = 64,
|
||||
};
|
||||
|
||||
enum ColumnNumber
|
||||
{
|
||||
colName = 0, // item name
|
||||
colPrint , // printable property
|
||||
colExtruder , // extruder selection
|
||||
colEditing , // item editing
|
||||
};
|
||||
|
||||
enum PrintIndicator
|
||||
{
|
||||
piUndef = 0, // no print indicator
|
||||
piPrintable , // printable
|
||||
piUnprintable , // unprintable
|
||||
};
|
||||
|
||||
class ObjectDataViewModelNode;
|
||||
WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
|
||||
|
||||
class ObjectDataViewModelNode
|
||||
{
|
||||
ObjectDataViewModelNode* m_parent;
|
||||
MyObjectTreeModelNodePtrArray m_children;
|
||||
wxBitmap m_empty_bmp;
|
||||
size_t m_volumes_cnt = 0;
|
||||
std::vector< std::string > m_opt_categories;
|
||||
t_layer_height_range m_layer_range = { 0.0f, 0.0f };
|
||||
|
||||
wxString m_name;
|
||||
wxBitmap& m_bmp = m_empty_bmp;
|
||||
ItemType m_type;
|
||||
int m_idx = -1;
|
||||
bool m_container = false;
|
||||
wxString m_extruder = "default";
|
||||
wxBitmap m_extruder_bmp;
|
||||
wxBitmap m_action_icon;
|
||||
PrintIndicator m_printable {piUndef};
|
||||
wxBitmap m_printable_icon;
|
||||
|
||||
std::string m_action_icon_name = "";
|
||||
ModelVolumeType m_volume_type;
|
||||
|
||||
public:
|
||||
ObjectDataViewModelNode(const wxString& name,
|
||||
const wxString& extruder):
|
||||
m_parent(NULL),
|
||||
m_name(name),
|
||||
m_type(itObject),
|
||||
m_extruder(extruder)
|
||||
{
|
||||
set_action_and_extruder_icons();
|
||||
init_container();
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
const wxString& sub_obj_name,
|
||||
const wxBitmap& bmp,
|
||||
const wxString& extruder,
|
||||
const int idx = -1 ) :
|
||||
m_parent (parent),
|
||||
m_name (sub_obj_name),
|
||||
m_type (itVolume),
|
||||
m_idx (idx),
|
||||
m_extruder (extruder)
|
||||
{
|
||||
m_bmp = bmp;
|
||||
set_action_and_extruder_icons();
|
||||
init_container();
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
const t_layer_height_range& layer_range,
|
||||
const int idx = -1,
|
||||
const wxString& extruder = wxEmptyString );
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type);
|
||||
|
||||
~ObjectDataViewModelNode()
|
||||
{
|
||||
// free all our children nodes
|
||||
size_t count = m_children.GetCount();
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
ObjectDataViewModelNode *child = m_children[i];
|
||||
delete child;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// Indicate that the object was deleted.
|
||||
m_idx = -2;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
|
||||
void init_container();
|
||||
bool IsContainer() const
|
||||
{
|
||||
return m_container;
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode* GetParent()
|
||||
{
|
||||
assert(m_parent == nullptr || m_parent->valid());
|
||||
return m_parent;
|
||||
}
|
||||
MyObjectTreeModelNodePtrArray& GetChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
ObjectDataViewModelNode* GetNthChild(unsigned int n)
|
||||
{
|
||||
return m_children.Item(n);
|
||||
}
|
||||
void Insert(ObjectDataViewModelNode* child, unsigned int n)
|
||||
{
|
||||
if (!m_container)
|
||||
m_container = true;
|
||||
m_children.Insert(child, n);
|
||||
}
|
||||
void Append(ObjectDataViewModelNode* child)
|
||||
{
|
||||
if (!m_container)
|
||||
m_container = true;
|
||||
m_children.Add(child);
|
||||
}
|
||||
void RemoveAllChildren()
|
||||
{
|
||||
if (GetChildCount() == 0)
|
||||
return;
|
||||
for (int id = int(GetChildCount()) - 1; id >= 0; --id)
|
||||
{
|
||||
if (m_children.Item(id)->GetChildCount() > 0)
|
||||
m_children[id]->RemoveAllChildren();
|
||||
auto node = m_children[id];
|
||||
m_children.RemoveAt(id);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetChildCount() const
|
||||
{
|
||||
return m_children.GetCount();
|
||||
}
|
||||
|
||||
bool SetValue(const wxVariant &variant, unsigned int col);
|
||||
|
||||
void SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
|
||||
const wxBitmap& GetBitmap() const { return m_bmp; }
|
||||
const wxString& GetName() const { return m_name; }
|
||||
ItemType GetType() const { return m_type; }
|
||||
void SetIdx(const int& idx);
|
||||
int GetIdx() const { return m_idx; }
|
||||
t_layer_height_range GetLayerRange() const { return m_layer_range; }
|
||||
PrintIndicator IsPrintable() const { return m_printable; }
|
||||
|
||||
// use this function only for childrens
|
||||
void AssignAllVal(ObjectDataViewModelNode& from_node)
|
||||
{
|
||||
// ! Don't overwrite other values because of equality of this values for all children --
|
||||
m_name = from_node.m_name;
|
||||
m_bmp = from_node.m_bmp;
|
||||
m_idx = from_node.m_idx;
|
||||
m_extruder = from_node.m_extruder;
|
||||
m_type = from_node.m_type;
|
||||
}
|
||||
|
||||
bool SwapChildrens(int frst_id, int scnd_id) {
|
||||
if (GetChildCount() < 2 ||
|
||||
frst_id < 0 || (size_t)frst_id >= GetChildCount() ||
|
||||
scnd_id < 0 || (size_t)scnd_id >= GetChildCount())
|
||||
return false;
|
||||
|
||||
ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
|
||||
ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
|
||||
|
||||
new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
|
||||
new_frst.m_idx = m_children.Item(frst_id)->m_idx;
|
||||
|
||||
m_children.Item(frst_id)->AssignAllVal(new_frst);
|
||||
m_children.Item(scnd_id)->AssignAllVal(new_scnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set action icons for node
|
||||
void set_action_and_extruder_icons();
|
||||
// Set printable icon for node
|
||||
void set_printable_icon(PrintIndicator printable);
|
||||
|
||||
void update_settings_digest_bitmaps();
|
||||
bool update_settings_digest(const std::vector<std::string>& categories);
|
||||
int volume_type() const { return int(m_volume_type); }
|
||||
void msw_rescale();
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool valid();
|
||||
#endif /* NDEBUG */
|
||||
bool invalid() const { return m_idx < -1; }
|
||||
|
||||
private:
|
||||
friend class ObjectDataViewModel;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ObjectDataViewModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// custom message the model sends to associated control to notify a last volume deleted from the object:
|
||||
wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent);
|
||||
|
||||
class ObjectDataViewModel :public wxDataViewModel
|
||||
{
|
||||
std::vector<ObjectDataViewModelNode*> m_objects;
|
||||
std::vector<wxBitmap*> m_volume_bmps;
|
||||
wxBitmap* m_warning_bmp { nullptr };
|
||||
|
||||
wxDataViewCtrl* m_ctrl { nullptr };
|
||||
|
||||
public:
|
||||
ObjectDataViewModel();
|
||||
~ObjectDataViewModel();
|
||||
|
||||
wxDataViewItem Add( const wxString &name,
|
||||
const int extruder,
|
||||
const bool has_errors = false);
|
||||
wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item,
|
||||
const wxString &name,
|
||||
const Slic3r::ModelVolumeType volume_type,
|
||||
const bool has_errors = false,
|
||||
const int extruder = 0,
|
||||
const bool create_frst_child = true);
|
||||
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
|
||||
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
|
||||
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, const std::vector<bool>& print_indicator);
|
||||
wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item);
|
||||
wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item,
|
||||
const t_layer_height_range& layer_range,
|
||||
const int extruder = 0,
|
||||
const int index = -1);
|
||||
wxDataViewItem Delete(const wxDataViewItem &item);
|
||||
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
|
||||
void DeleteAll();
|
||||
void DeleteChildren(wxDataViewItem& parent);
|
||||
void DeleteVolumeChildren(wxDataViewItem& parent);
|
||||
void DeleteSettings(const wxDataViewItem& parent);
|
||||
wxDataViewItem GetItemById(int obj_idx);
|
||||
wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type);
|
||||
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
|
||||
wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx);
|
||||
wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx);
|
||||
wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
int GetIdByItem(const wxDataViewItem& item) const;
|
||||
int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
|
||||
int GetObjectIdByItem(const wxDataViewItem& item) const;
|
||||
int GetVolumeIdByItem(const wxDataViewItem& item) const;
|
||||
int GetInstanceIdByItem(const wxDataViewItem& item) const;
|
||||
int GetLayerIdByItem(const wxDataViewItem& item) const;
|
||||
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
|
||||
int GetRowByItem(const wxDataViewItem& item) const;
|
||||
bool IsEmpty() { return m_objects.empty(); }
|
||||
bool InvalidItem(const wxDataViewItem& item);
|
||||
|
||||
// helper method for wxLog
|
||||
|
||||
wxString GetName(const wxDataViewItem &item) const;
|
||||
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
|
||||
wxString GetExtruder(const wxDataViewItem &item) const;
|
||||
int GetExtruderNumber(const wxDataViewItem &item) const;
|
||||
|
||||
// helper methods to change the model
|
||||
|
||||
virtual unsigned int GetColumnCount() const override { return 3;}
|
||||
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
|
||||
|
||||
virtual void GetValue( wxVariant &variant,
|
||||
const wxDataViewItem &item,
|
||||
unsigned int col) const override;
|
||||
virtual bool SetValue( const wxVariant &variant,
|
||||
const wxDataViewItem &item,
|
||||
unsigned int col) override;
|
||||
bool SetValue( const wxVariant &variant,
|
||||
const int item_idx,
|
||||
unsigned int col);
|
||||
|
||||
void SetExtruder(const wxString& extruder, wxDataViewItem item);
|
||||
|
||||
// For parent move child from cur_volume_id place to new_volume_id
|
||||
// Remaining items will moved up/down accordingly
|
||||
wxDataViewItem ReorganizeChildren( const int cur_volume_id,
|
||||
const int new_volume_id,
|
||||
const wxDataViewItem &parent);
|
||||
wxDataViewItem ReorganizeObjects( int current_id, int new_id);
|
||||
|
||||
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
|
||||
|
||||
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
|
||||
// get object item
|
||||
wxDataViewItem GetTopParent(const wxDataViewItem &item) const;
|
||||
virtual bool IsContainer(const wxDataViewItem &item) const override;
|
||||
virtual unsigned int GetChildren(const wxDataViewItem &parent,
|
||||
wxDataViewItemArray &array) const override;
|
||||
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
|
||||
// Is the container just a header or an item with all columns
|
||||
// In our case it is an item with all columns
|
||||
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
|
||||
|
||||
ItemType GetItemType(const wxDataViewItem &item) const ;
|
||||
wxDataViewItem GetItemByType( const wxDataViewItem &parent_item,
|
||||
ItemType type) const;
|
||||
wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const;
|
||||
wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const;
|
||||
wxDataViewItem GetLayerRootItem(const wxDataViewItem &item) const;
|
||||
bool IsSettingsItem(const wxDataViewItem &item) const;
|
||||
void UpdateSettingsDigest( const wxDataViewItem &item,
|
||||
const std::vector<std::string>& categories);
|
||||
|
||||
bool IsPrintable(const wxDataViewItem &item) const;
|
||||
void UpdateObjectPrintable(wxDataViewItem parent_item);
|
||||
void UpdateInstancesPrintable(wxDataViewItem parent_item);
|
||||
|
||||
void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
|
||||
void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; }
|
||||
void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
|
||||
wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx,
|
||||
int subobj_idx = -1,
|
||||
ItemType subobj_type = itInstance);
|
||||
wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item);
|
||||
|
||||
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
||||
// Rescale bitmaps for existing Items
|
||||
void Rescale();
|
||||
|
||||
wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type,
|
||||
const bool is_marked = false);
|
||||
void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false);
|
||||
t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const;
|
||||
|
||||
bool UpdateColumValues(unsigned col);
|
||||
void UpdateExtruderBitmap(wxDataViewItem item);
|
||||
|
||||
private:
|
||||
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
|
||||
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // slic3r_GUI_ObjectDataViewModel_hpp_
|
||||
|
|
@ -169,7 +169,7 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
|
|||
info_manifold_text->SetFont(wxGetApp().small_font());
|
||||
info_manifold = new wxStaticText(parent, wxID_ANY, "");
|
||||
info_manifold->SetFont(wxGetApp().small_font());
|
||||
manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, create_scaled_bitmap(parent, "exclamation"));
|
||||
manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, create_scaled_bitmap("exclamation"));
|
||||
auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_manifold->Add(info_manifold_text, 0);
|
||||
sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2);
|
||||
|
|
@ -188,7 +188,7 @@ void ObjectInfo::show_sizer(bool show)
|
|||
|
||||
void ObjectInfo::msw_rescale()
|
||||
{
|
||||
manifold_warning_icon->SetBitmap(create_scaled_bitmap(nullptr, "exclamation"));
|
||||
manifold_warning_icon->SetBitmap(create_scaled_bitmap("exclamation"));
|
||||
}
|
||||
|
||||
enum SlicedInfoIdx
|
||||
|
|
@ -258,7 +258,7 @@ void SlicedInfo::SetTextAndShow(SlicedInfoIdx idx, const wxString& text, const w
|
|||
}
|
||||
|
||||
PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) :
|
||||
wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 * wxGetApp().em_unit(), -1), 0, nullptr, wxCB_READONLY),
|
||||
PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
|
||||
preset_type(preset_type),
|
||||
last_selected(wxNOT_FOUND),
|
||||
m_em_unit(wxGetApp().em_unit())
|
||||
|
|
@ -1875,6 +1875,7 @@ struct Plater::priv
|
|||
}
|
||||
void export_gcode(fs::path output_path, PrintHostJob upload_job);
|
||||
void reload_from_disk();
|
||||
void reload_all_from_disk();
|
||||
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
|
||||
|
||||
void set_current_panel(wxPanel* panel);
|
||||
|
|
@ -2075,6 +2076,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event<float>& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_RELOAD_FROM_DISK, [this](SimpleEvent&) { if (!this->model.objects.empty()) this->reload_all_from_disk(); });
|
||||
|
||||
// 3DScene/Toolbar:
|
||||
view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
|
||||
|
|
@ -3447,6 +3449,24 @@ void Plater::priv::reload_from_disk()
|
|||
}
|
||||
}
|
||||
|
||||
void Plater::priv::reload_all_from_disk()
|
||||
{
|
||||
Plater::TakeSnapshot snapshot(q, _(L("Reload all from disk")));
|
||||
Plater::SuppressSnapshots suppress(q);
|
||||
|
||||
Selection& selection = get_selection();
|
||||
Selection::IndicesList curr_idxs = selection.get_volume_idxs();
|
||||
// reload from disk uses selection
|
||||
select_all();
|
||||
reload_from_disk();
|
||||
// restore previous selection
|
||||
selection.clear();
|
||||
for (unsigned int idx : curr_idxs)
|
||||
{
|
||||
selection.add(idx, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
|
||||
{
|
||||
if (obj_idx < 0)
|
||||
|
|
@ -5034,6 +5054,11 @@ void Plater::reload_from_disk()
|
|||
p->reload_from_disk();
|
||||
}
|
||||
|
||||
void Plater::reload_all_from_disk()
|
||||
{
|
||||
p->reload_all_from_disk();
|
||||
}
|
||||
|
||||
bool Plater::has_toolpaths_to_export() const
|
||||
{
|
||||
return p->preview->get_canvas3d()->has_toolpaths_to_export();
|
||||
|
|
@ -5376,6 +5401,13 @@ void Plater::force_filament_colors_update()
|
|||
this->p->schedule_background_process();
|
||||
}
|
||||
|
||||
void Plater::force_print_bed_update()
|
||||
{
|
||||
// Fill in the printer model key with something which cannot possibly be valid, so that Plater::on_config_change() will update the print bed
|
||||
// once a new Printer profile config is loaded.
|
||||
p->config->opt_string("printer_model", true) = "\x01\x00\x01";
|
||||
}
|
||||
|
||||
void Plater::on_activate()
|
||||
{
|
||||
#ifdef __linux__
|
||||
|
|
@ -5392,11 +5424,6 @@ void Plater::on_activate()
|
|||
this->p->show_delayed_error_message();
|
||||
}
|
||||
|
||||
const DynamicPrintConfig* Plater::get_plater_config() const
|
||||
{
|
||||
return p->config;
|
||||
}
|
||||
|
||||
// Get vector of extruder colors considering filament color, if extruder color is undefined.
|
||||
std::vector<std::string> Plater::get_extruder_colors_from_plater_config() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "3DScene.hpp"
|
||||
#include "GLTexture.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
class wxButton;
|
||||
class ScalableButton;
|
||||
|
|
@ -49,7 +50,7 @@ using t_optgroups = std::vector <std::shared_ptr<ConfigOptionsGroup>>;
|
|||
class Plater;
|
||||
enum class ActionButtonType : int;
|
||||
|
||||
class PresetComboBox : public wxBitmapComboBox
|
||||
class PresetComboBox : public PresetBitmapComboBox
|
||||
{
|
||||
public:
|
||||
PresetComboBox(wxWindow *parent, Preset::Type preset_type);
|
||||
|
|
@ -193,6 +194,7 @@ public:
|
|||
void export_amf();
|
||||
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
|
||||
void reload_from_disk();
|
||||
void reload_all_from_disk();
|
||||
bool has_toolpaths_to_export() const;
|
||||
void export_toolpaths_to_obj() const;
|
||||
void hollow();
|
||||
|
|
@ -227,9 +229,9 @@ public:
|
|||
void on_extruders_change(size_t extruders_count);
|
||||
void on_config_change(const DynamicPrintConfig &config);
|
||||
void force_filament_colors_update();
|
||||
void force_print_bed_update();
|
||||
// On activating the parent window.
|
||||
void on_activate();
|
||||
const DynamicPrintConfig* get_plater_config() const;
|
||||
std::vector<std::string> get_extruder_colors_from_plater_config() const;
|
||||
std::vector<std::string> get_colors_for_color_print() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -550,7 +550,6 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
|||
s_opts = {
|
||||
"printer_technology",
|
||||
"bed_shape", "bed_custom_texture", "bed_custom_model", "max_print_height",
|
||||
"bed_shape", "max_print_height",
|
||||
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
|
||||
"display_mirror_x", "display_mirror_y",
|
||||
"display_orientation",
|
||||
|
|
@ -874,18 +873,14 @@ bool PresetCollection::delete_preset(const std::string& name)
|
|||
return true;
|
||||
}
|
||||
|
||||
void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name)
|
||||
void PresetCollection::load_bitmap_default(const std::string &file_name)
|
||||
{
|
||||
// XXX: See note in PresetBundle::load_compatible_bitmaps()
|
||||
(void)window;
|
||||
*m_bitmap_main_frame = create_scaled_bitmap(nullptr, file_name);
|
||||
*m_bitmap_main_frame = create_scaled_bitmap(file_name);
|
||||
}
|
||||
|
||||
void PresetCollection::load_bitmap_add(wxWindow *window, const std::string &file_name)
|
||||
void PresetCollection::load_bitmap_add(const std::string &file_name)
|
||||
{
|
||||
// XXX: See note in PresetBundle::load_compatible_bitmaps()
|
||||
(void)window;
|
||||
*m_bitmap_add = create_scaled_bitmap(nullptr, file_name);
|
||||
*m_bitmap_add = create_scaled_bitmap(file_name);
|
||||
}
|
||||
|
||||
const Preset* PresetCollection::get_selected_preset_parent() const
|
||||
|
|
|
|||
|
|
@ -313,10 +313,10 @@ public:
|
|||
bool delete_preset(const std::string& name);
|
||||
|
||||
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
void load_bitmap_default(wxWindow *window, const std::string &file_name);
|
||||
void load_bitmap_default(const std::string &file_name);
|
||||
|
||||
// Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
void load_bitmap_add(wxWindow *window, const std::string &file_name);
|
||||
void load_bitmap_add(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; }
|
||||
|
|
|
|||
|
|
@ -480,19 +480,12 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||
config.set("presets", "printer", printers.get_selected_preset_name());
|
||||
}
|
||||
|
||||
void PresetBundle::load_compatible_bitmaps(wxWindow *window)
|
||||
void PresetBundle::load_compatible_bitmaps()
|
||||
{
|
||||
// We don't actually pass the window pointer here and instead generate
|
||||
// a low DPI bitmap, because the wxBitmapComboBox and wxDataViewCtrl don't support
|
||||
// high DPI bitmaps very well, they compute their dimensions wrong.
|
||||
// TODO: Update this when fixed in wxWidgets
|
||||
// See also PresetCollection::load_bitmap_default() and PresetCollection::load_bitmap_add()
|
||||
|
||||
(void)window;
|
||||
*m_bitmapCompatible = create_scaled_bitmap(nullptr, "flag_green");
|
||||
*m_bitmapIncompatible = create_scaled_bitmap(nullptr, "flag_red");
|
||||
*m_bitmapLock = create_scaled_bitmap(nullptr, "lock_closed");
|
||||
*m_bitmapLockOpen = create_scaled_bitmap(nullptr, "lock_open");
|
||||
*m_bitmapCompatible = create_scaled_bitmap("flag_green");
|
||||
*m_bitmapIncompatible = create_scaled_bitmap("flag_red");
|
||||
*m_bitmapLock = create_scaled_bitmap("lock_closed");
|
||||
*m_bitmapLockOpen = create_scaled_bitmap("lock_open");
|
||||
|
||||
prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
filaments .set_bitmap_compatible(m_bitmapCompatible);
|
||||
|
|
@ -1536,31 +1529,7 @@ void PresetBundle::set_filament_preset(size_t idx, const std::string &name)
|
|||
filament_presets[idx] = Preset::remove_suffix_modified(name);
|
||||
}
|
||||
|
||||
static inline int hex_digit_to_int(const char c)
|
||||
{
|
||||
return
|
||||
(c >= '0' && c <= '9') ? int(c - '0') :
|
||||
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
|
||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||
}
|
||||
|
||||
bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out)
|
||||
{
|
||||
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;
|
||||
if (scolor.size() != 7 || scolor.front() != '#')
|
||||
return false;
|
||||
const char *c = scolor.data() + 1;
|
||||
for (size_t i = 0; i < 3; ++ i) {
|
||||
int digit1 = hex_digit_to_int(*c ++);
|
||||
int digit2 = hex_digit_to_int(*c ++);
|
||||
if (digit1 == -1 || digit2 == -1)
|
||||
return false;
|
||||
rgb_out[i] = (unsigned char)(digit1 * 16 + digit2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PresetBundle::load_default_preset_bitmaps(wxWindow *window)
|
||||
void PresetBundle::load_default_preset_bitmaps()
|
||||
{
|
||||
// Clear bitmap cache, before load new scaled default preset bitmaps
|
||||
m_bitmapCache->clear();
|
||||
|
|
@ -1570,13 +1539,13 @@ void PresetBundle::load_default_preset_bitmaps(wxWindow *window)
|
|||
this->sla_materials.clear_bitmap_cache();
|
||||
this->printers.clear_bitmap_cache();
|
||||
|
||||
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);
|
||||
this->prints.load_bitmap_default("cog");
|
||||
this->sla_prints.load_bitmap_default("cog");
|
||||
this->filaments.load_bitmap_default("spool.png");
|
||||
this->sla_materials.load_bitmap_default("resin");
|
||||
this->printers.load_bitmap_default("printer");
|
||||
this->printers.load_bitmap_add("add.png");
|
||||
this->load_compatible_bitmaps();
|
||||
}
|
||||
|
||||
void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
|
||||
|
|
@ -1587,7 +1556,7 @@ void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::Pre
|
|||
|
||||
unsigned char rgb[3];
|
||||
std::string extruder_color = this->printers.get_edited_preset().config.opt_string("extruder_colour", idx_extruder);
|
||||
if (! parse_color(extruder_color, rgb))
|
||||
if (!m_bitmapCache->parse_color(extruder_color, rgb))
|
||||
// Extruder color is not defined.
|
||||
extruder_color.clear();
|
||||
|
||||
|
|
@ -1623,7 +1592,12 @@ void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::Pre
|
|||
|
||||
// To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size, so
|
||||
// set a bitmap height to m_bitmapLock->GetHeight()
|
||||
const int icon_height = m_bitmapLock->GetHeight();//2 * icon_unit; //16 * scale_f + 0.5f;
|
||||
// Note, under OSX we should use a ScaledHeight because of Retina scale
|
||||
#ifdef __APPLE__
|
||||
const int icon_height = m_bitmapLock->GetScaledHeight();
|
||||
#else
|
||||
const int icon_height = m_bitmapLock->GetHeight();
|
||||
#endif
|
||||
|
||||
wxString tooltip = "";
|
||||
|
||||
|
|
@ -1652,10 +1626,10 @@ void PresetBundle::update_plater_filament_ui(unsigned int idx_extruder, GUI::Pre
|
|||
// Paint a red flag for incompatible presets.
|
||||
bmps.emplace_back(preset.is_compatible ? m_bitmapCache->mkclear(normal_icon_width, icon_height) : *m_bitmapIncompatible);
|
||||
// Paint the color bars.
|
||||
parse_color(filament_rgb, rgb);
|
||||
m_bitmapCache->parse_color(filament_rgb, rgb);
|
||||
bmps.emplace_back(m_bitmapCache->mksolid(single_bar ? wide_icon_width : normal_icon_width, icon_height, rgb));
|
||||
if (! single_bar) {
|
||||
parse_color(extruder_rgb, rgb);
|
||||
m_bitmapCache->parse_color(extruder_rgb, rgb);
|
||||
bmps.emplace_back(m_bitmapCache->mksolid(thin_icon_width, icon_height, rgb));
|
||||
}
|
||||
// Paint a lock at the system presets.
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ public:
|
|||
|
||||
// There will be an entry for each system profile loaded,
|
||||
// and the system profiles will point to the VendorProfile instances owned by PresetBundle::vendors.
|
||||
// std::set<VendorProfile> vendors;
|
||||
VendorMap vendors;
|
||||
VendorMap vendors;
|
||||
|
||||
struct ObsoletePresets {
|
||||
std::vector<std::string> prints;
|
||||
|
|
@ -130,9 +129,7 @@ public:
|
|||
// preset if the current print or filament preset is not compatible.
|
||||
void update_compatible(bool select_other_if_incompatible);
|
||||
|
||||
static bool parse_color(const std::string &scolor, unsigned char *rgb_out);
|
||||
|
||||
void load_default_preset_bitmaps(wxWindow *window);
|
||||
void load_default_preset_bitmaps();
|
||||
|
||||
// Set the is_visible flag for printer vendors, printer models and printer variants
|
||||
// based on the user configuration.
|
||||
|
|
@ -161,7 +158,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);
|
||||
void load_compatible_bitmaps(wxWindow *window);
|
||||
void load_compatible_bitmaps();
|
||||
|
||||
DynamicPrintConfig full_fff_config() const;
|
||||
DynamicPrintConfig full_sla_config() const;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void Tab::create_preset_tab()
|
|||
#endif //__WXOSX__
|
||||
|
||||
// preset chooser
|
||||
m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(35 * m_em_unit, -1), 0, 0, wxCB_READONLY);
|
||||
m_presets_choice = new PresetBitmapComboBox(panel, wxSize(35 * m_em_unit, -1));
|
||||
|
||||
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
|
||||
|
|
@ -1690,7 +1690,7 @@ 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->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "browse"));
|
||||
btn->SetBitmap(create_scaled_bitmap("browse"));
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ protected:
|
|||
Preset::Type m_type;
|
||||
std::string m_name;
|
||||
const wxString m_title;
|
||||
wxBitmapComboBox* m_presets_choice;
|
||||
PresetBitmapComboBox* m_presets_choice;
|
||||
ScalableButton* m_btn_save_preset;
|
||||
ScalableButton* m_btn_delete_preset;
|
||||
ScalableButton* m_btn_hide_incompatible_presets;
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, w
|
|||
MsgDialog(nullptr, wxString::Format(_(L("%s incompatibility")), SLIC3R_APP_NAME),
|
||||
wxString::Format(_(L("%s configuration is incompatible")), SLIC3R_APP_NAME), wxID_NONE)
|
||||
{
|
||||
logo->SetBitmap(create_scaled_bitmap(this, "PrusaSlicer_192px_grayscale.png", 192));
|
||||
logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 192));
|
||||
|
||||
auto *text = new wxStaticText(this, wxID_ANY, wxString::Format(_(L(
|
||||
"This version of %s is not compatible with currently installed configuration bundles.\n"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include "WipeTowerDialog.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
|
@ -191,7 +191,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
|
|||
|
||||
for (const std::string& color : extruder_colours) {
|
||||
unsigned char rgb[3];
|
||||
Slic3r::PresetBundle::parse_color(color, rgb);
|
||||
Slic3r::GUI::BitmapCache::parse_color(color, rgb);
|
||||
m_colours.push_back(wxColor(rgb[0], rgb[1], rgb[2]));
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,23 +4,14 @@
|
|||
#include <wx/checklst.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/menu.h>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/bmpcbox.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <functional>
|
||||
|
||||
namespace Slic3r {
|
||||
enum class ModelVolumeType : int;
|
||||
};
|
||||
|
||||
typedef double coordf_t;
|
||||
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
void msw_rescale_menu(wxMenu* menu);
|
||||
|
|
@ -48,15 +39,13 @@ wxMenuItem* append_menu_check_item(wxMenu* menu, int id, const wxString& string,
|
|||
void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condition, wxMenuItem* item, wxWindow* win);
|
||||
|
||||
class wxDialog;
|
||||
class wxBitmapComboBox;
|
||||
|
||||
void edit_tooltip(wxString& tooltip);
|
||||
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids);
|
||||
int em_unit(wxWindow* win);
|
||||
float get_svg_scale_factor(wxWindow* win);
|
||||
|
||||
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name,
|
||||
const int px_cnt = 16, const bool is_horizontal = false, const bool grayscale = false);
|
||||
wxBitmap create_scaled_bitmap(const std::string& bmp_name, wxWindow *win = nullptr,
|
||||
const int px_cnt = 16, const bool grayscale = false);
|
||||
|
||||
std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon = false);
|
||||
void apply_extruder_selector(wxBitmapComboBox** ctrl,
|
||||
|
|
@ -102,6 +91,37 @@ public:
|
|||
void OnListBoxSelection(wxCommandEvent& evt);
|
||||
};
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
// *** PresetBitmapComboBox ***
|
||||
|
||||
// BitmapComboBox used to presets list on Sidebar and Tabs
|
||||
class PresetBitmapComboBox: public wxBitmapComboBox
|
||||
{
|
||||
public:
|
||||
PresetBitmapComboBox(wxWindow* parent, const wxSize& size = wxDefaultSize);
|
||||
~PresetBitmapComboBox() {}
|
||||
|
||||
#ifdef __APPLE__
|
||||
protected:
|
||||
/* For PresetBitmapComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
|
||||
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
|
||||
* "please scale this to such and such" but rather
|
||||
* "the wxImage is already sized for backing scale such and such". )
|
||||
* Unfortunately, the constructor changes the size of wxBitmap too.
|
||||
* Thus We need to use unscaled size value for bitmaps that we use
|
||||
* to avoid scaled size of control items.
|
||||
* For this purpose control drawing methods and
|
||||
* control size calculation methods (virtual) are overridden.
|
||||
**/
|
||||
virtual bool OnAddBitmap(const wxBitmap& bitmap) override;
|
||||
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// *** wxDataViewTreeCtrlComboBox ***
|
||||
|
||||
|
|
@ -127,587 +147,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DataViewBitmapText: helper class used by PrusaBitmapTextRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class DataViewBitmapText : public wxObject
|
||||
{
|
||||
public:
|
||||
DataViewBitmapText( const wxString &text = wxEmptyString,
|
||||
const wxBitmap& bmp = wxNullBitmap) :
|
||||
m_text(text),
|
||||
m_bmp(bmp)
|
||||
{ }
|
||||
|
||||
DataViewBitmapText(const DataViewBitmapText &other)
|
||||
: wxObject(),
|
||||
m_text(other.m_text),
|
||||
m_bmp(other.m_bmp)
|
||||
{ }
|
||||
|
||||
void SetText(const wxString &text) { m_text = text; }
|
||||
wxString GetText() const { return m_text; }
|
||||
void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; }
|
||||
const wxBitmap &GetBitmap() const { return m_bmp; }
|
||||
|
||||
bool IsSameAs(const DataViewBitmapText& other) const {
|
||||
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
|
||||
}
|
||||
|
||||
bool operator==(const DataViewBitmapText& other) const {
|
||||
return IsSameAs(other);
|
||||
}
|
||||
|
||||
bool operator!=(const DataViewBitmapText& other) const {
|
||||
return !IsSameAs(other);
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_text;
|
||||
wxBitmap m_bmp;
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(DataViewBitmapText);
|
||||
};
|
||||
DECLARE_VARIANT_OBJECT(DataViewBitmapText)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ObjectDataViewModelNode: a node inside ObjectDataViewModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
enum ItemType {
|
||||
itUndef = 0,
|
||||
itObject = 1,
|
||||
itVolume = 2,
|
||||
itInstanceRoot = 4,
|
||||
itInstance = 8,
|
||||
itSettings = 16,
|
||||
itLayerRoot = 32,
|
||||
itLayer = 64,
|
||||
};
|
||||
|
||||
enum ColumnNumber
|
||||
{
|
||||
colName = 0, // item name
|
||||
colPrint , // printable property
|
||||
colExtruder , // extruder selection
|
||||
colEditing , // item editing
|
||||
};
|
||||
|
||||
enum PrintIndicator
|
||||
{
|
||||
piUndef = 0, // no print indicator
|
||||
piPrintable , // printable
|
||||
piUnprintable , // unprintable
|
||||
};
|
||||
|
||||
class ObjectDataViewModelNode;
|
||||
WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
|
||||
|
||||
class ObjectDataViewModelNode
|
||||
{
|
||||
ObjectDataViewModelNode* m_parent;
|
||||
MyObjectTreeModelNodePtrArray m_children;
|
||||
wxBitmap m_empty_bmp;
|
||||
size_t m_volumes_cnt = 0;
|
||||
std::vector< std::string > m_opt_categories;
|
||||
t_layer_height_range m_layer_range = { 0.0f, 0.0f };
|
||||
|
||||
wxString m_name;
|
||||
wxBitmap& m_bmp = m_empty_bmp;
|
||||
ItemType m_type;
|
||||
int m_idx = -1;
|
||||
bool m_container = false;
|
||||
wxString m_extruder = "default";
|
||||
wxBitmap m_extruder_bmp;
|
||||
wxBitmap m_action_icon;
|
||||
PrintIndicator m_printable {piUndef};
|
||||
wxBitmap m_printable_icon;
|
||||
|
||||
std::string m_action_icon_name = "";
|
||||
Slic3r::ModelVolumeType m_volume_type;
|
||||
|
||||
public:
|
||||
ObjectDataViewModelNode(const wxString &name,
|
||||
const wxString& extruder):
|
||||
m_parent(NULL),
|
||||
m_name(name),
|
||||
m_type(itObject),
|
||||
m_extruder(extruder)
|
||||
{
|
||||
set_action_and_extruder_icons();
|
||||
init_container();
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
const wxString& sub_obj_name,
|
||||
const wxBitmap& bmp,
|
||||
const wxString& extruder,
|
||||
const int idx = -1 ) :
|
||||
m_parent (parent),
|
||||
m_name (sub_obj_name),
|
||||
m_type (itVolume),
|
||||
m_idx (idx),
|
||||
m_extruder (extruder)
|
||||
{
|
||||
m_bmp = bmp;
|
||||
set_action_and_extruder_icons();
|
||||
init_container();
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
const t_layer_height_range& layer_range,
|
||||
const int idx = -1,
|
||||
const wxString& extruder = wxEmptyString );
|
||||
|
||||
ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type);
|
||||
|
||||
~ObjectDataViewModelNode()
|
||||
{
|
||||
// free all our children nodes
|
||||
size_t count = m_children.GetCount();
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
ObjectDataViewModelNode *child = m_children[i];
|
||||
delete child;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// Indicate that the object was deleted.
|
||||
m_idx = -2;
|
||||
#endif /* NDEBUG */
|
||||
}
|
||||
|
||||
void init_container();
|
||||
bool IsContainer() const
|
||||
{
|
||||
return m_container;
|
||||
}
|
||||
|
||||
ObjectDataViewModelNode* GetParent()
|
||||
{
|
||||
assert(m_parent == nullptr || m_parent->valid());
|
||||
return m_parent;
|
||||
}
|
||||
MyObjectTreeModelNodePtrArray& GetChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
ObjectDataViewModelNode* GetNthChild(unsigned int n)
|
||||
{
|
||||
return m_children.Item(n);
|
||||
}
|
||||
void Insert(ObjectDataViewModelNode* child, unsigned int n)
|
||||
{
|
||||
if (!m_container)
|
||||
m_container = true;
|
||||
m_children.Insert(child, n);
|
||||
}
|
||||
void Append(ObjectDataViewModelNode* child)
|
||||
{
|
||||
if (!m_container)
|
||||
m_container = true;
|
||||
m_children.Add(child);
|
||||
}
|
||||
void RemoveAllChildren()
|
||||
{
|
||||
if (GetChildCount() == 0)
|
||||
return;
|
||||
for (int id = int(GetChildCount()) - 1; id >= 0; --id)
|
||||
{
|
||||
if (m_children.Item(id)->GetChildCount() > 0)
|
||||
m_children[id]->RemoveAllChildren();
|
||||
auto node = m_children[id];
|
||||
m_children.RemoveAt(id);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
size_t GetChildCount() const
|
||||
{
|
||||
return m_children.GetCount();
|
||||
}
|
||||
|
||||
bool SetValue(const wxVariant &variant, unsigned int col);
|
||||
|
||||
void SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
|
||||
const wxBitmap& GetBitmap() const { return m_bmp; }
|
||||
const wxString& GetName() const { return m_name; }
|
||||
ItemType GetType() const { return m_type; }
|
||||
void SetIdx(const int& idx);
|
||||
int GetIdx() const { return m_idx; }
|
||||
t_layer_height_range GetLayerRange() const { return m_layer_range; }
|
||||
PrintIndicator IsPrintable() const { return m_printable; }
|
||||
|
||||
// use this function only for childrens
|
||||
void AssignAllVal(ObjectDataViewModelNode& from_node)
|
||||
{
|
||||
// ! Don't overwrite other values because of equality of this values for all children --
|
||||
m_name = from_node.m_name;
|
||||
m_bmp = from_node.m_bmp;
|
||||
m_idx = from_node.m_idx;
|
||||
m_extruder = from_node.m_extruder;
|
||||
m_type = from_node.m_type;
|
||||
}
|
||||
|
||||
bool SwapChildrens(int frst_id, int scnd_id) {
|
||||
if (GetChildCount() < 2 ||
|
||||
frst_id < 0 || (size_t)frst_id >= GetChildCount() ||
|
||||
scnd_id < 0 || (size_t)scnd_id >= GetChildCount())
|
||||
return false;
|
||||
|
||||
ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
|
||||
ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
|
||||
|
||||
new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
|
||||
new_frst.m_idx = m_children.Item(frst_id)->m_idx;
|
||||
|
||||
m_children.Item(frst_id)->AssignAllVal(new_frst);
|
||||
m_children.Item(scnd_id)->AssignAllVal(new_scnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set action icons for node
|
||||
void set_action_and_extruder_icons();
|
||||
// Set printable icon for node
|
||||
void set_printable_icon(PrintIndicator printable);
|
||||
|
||||
void update_settings_digest_bitmaps();
|
||||
bool update_settings_digest(const std::vector<std::string>& categories);
|
||||
int volume_type() const { return int(m_volume_type); }
|
||||
void msw_rescale();
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool valid();
|
||||
#endif /* NDEBUG */
|
||||
bool invalid() const { return m_idx < -1; }
|
||||
|
||||
private:
|
||||
friend class ObjectDataViewModel;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ObjectDataViewModel
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// custom message the model sends to associated control to notify a last volume deleted from the object:
|
||||
wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent);
|
||||
|
||||
class ObjectDataViewModel :public wxDataViewModel
|
||||
{
|
||||
std::vector<ObjectDataViewModelNode*> m_objects;
|
||||
std::vector<wxBitmap*> m_volume_bmps;
|
||||
wxBitmap* m_warning_bmp { nullptr };
|
||||
|
||||
wxDataViewCtrl* m_ctrl { nullptr };
|
||||
|
||||
public:
|
||||
ObjectDataViewModel();
|
||||
~ObjectDataViewModel();
|
||||
|
||||
wxDataViewItem Add( const wxString &name,
|
||||
const int extruder,
|
||||
const bool has_errors = false);
|
||||
wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item,
|
||||
const wxString &name,
|
||||
const Slic3r::ModelVolumeType volume_type,
|
||||
const bool has_errors = false,
|
||||
const int extruder = 0,
|
||||
const bool create_frst_child = true);
|
||||
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
|
||||
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
|
||||
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, const std::vector<bool>& print_indicator);
|
||||
wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item);
|
||||
wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item,
|
||||
const t_layer_height_range& layer_range,
|
||||
const int extruder = 0,
|
||||
const int index = -1);
|
||||
wxDataViewItem Delete(const wxDataViewItem &item);
|
||||
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
|
||||
void DeleteAll();
|
||||
void DeleteChildren(wxDataViewItem& parent);
|
||||
void DeleteVolumeChildren(wxDataViewItem& parent);
|
||||
void DeleteSettings(const wxDataViewItem& parent);
|
||||
wxDataViewItem GetItemById(int obj_idx);
|
||||
wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type);
|
||||
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
|
||||
wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx);
|
||||
wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx);
|
||||
wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
|
||||
int GetIdByItem(const wxDataViewItem& item) const;
|
||||
int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
|
||||
int GetObjectIdByItem(const wxDataViewItem& item) const;
|
||||
int GetVolumeIdByItem(const wxDataViewItem& item) const;
|
||||
int GetInstanceIdByItem(const wxDataViewItem& item) const;
|
||||
int GetLayerIdByItem(const wxDataViewItem& item) const;
|
||||
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
|
||||
int GetRowByItem(const wxDataViewItem& item) const;
|
||||
bool IsEmpty() { return m_objects.empty(); }
|
||||
bool InvalidItem(const wxDataViewItem& item);
|
||||
|
||||
// helper method for wxLog
|
||||
|
||||
wxString GetName(const wxDataViewItem &item) const;
|
||||
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
|
||||
wxString GetExtruder(const wxDataViewItem &item) const;
|
||||
int GetExtruderNumber(const wxDataViewItem &item) const;
|
||||
|
||||
// helper methods to change the model
|
||||
|
||||
virtual unsigned int GetColumnCount() const override { return 3;}
|
||||
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
|
||||
|
||||
virtual void GetValue( wxVariant &variant,
|
||||
const wxDataViewItem &item,
|
||||
unsigned int col) const override;
|
||||
virtual bool SetValue( const wxVariant &variant,
|
||||
const wxDataViewItem &item,
|
||||
unsigned int col) override;
|
||||
bool SetValue( const wxVariant &variant,
|
||||
const int item_idx,
|
||||
unsigned int col);
|
||||
|
||||
void SetExtruder(const wxString& extruder, wxDataViewItem item);
|
||||
|
||||
// For parent move child from cur_volume_id place to new_volume_id
|
||||
// Remaining items will moved up/down accordingly
|
||||
wxDataViewItem ReorganizeChildren( const int cur_volume_id,
|
||||
const int new_volume_id,
|
||||
const wxDataViewItem &parent);
|
||||
|
||||
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
|
||||
|
||||
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
|
||||
// get object item
|
||||
wxDataViewItem GetTopParent(const wxDataViewItem &item) const;
|
||||
virtual bool IsContainer(const wxDataViewItem &item) const override;
|
||||
virtual unsigned int GetChildren(const wxDataViewItem &parent,
|
||||
wxDataViewItemArray &array) const override;
|
||||
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
|
||||
// Is the container just a header or an item with all columns
|
||||
// In our case it is an item with all columns
|
||||
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
|
||||
|
||||
ItemType GetItemType(const wxDataViewItem &item) const ;
|
||||
wxDataViewItem GetItemByType( const wxDataViewItem &parent_item,
|
||||
ItemType type) const;
|
||||
wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const;
|
||||
wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const;
|
||||
wxDataViewItem GetLayerRootItem(const wxDataViewItem &item) const;
|
||||
bool IsSettingsItem(const wxDataViewItem &item) const;
|
||||
void UpdateSettingsDigest( const wxDataViewItem &item,
|
||||
const std::vector<std::string>& categories);
|
||||
|
||||
bool IsPrintable(const wxDataViewItem &item) const;
|
||||
void UpdateObjectPrintable(wxDataViewItem parent_item);
|
||||
void UpdateInstancesPrintable(wxDataViewItem parent_item);
|
||||
|
||||
void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
|
||||
void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; }
|
||||
void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
|
||||
wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx,
|
||||
int subobj_idx = -1,
|
||||
ItemType subobj_type = itInstance);
|
||||
wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item);
|
||||
|
||||
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
||||
// Rescale bitmaps for existing Items
|
||||
void Rescale();
|
||||
|
||||
wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type,
|
||||
const bool is_marked = false);
|
||||
void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false);
|
||||
t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const;
|
||||
|
||||
bool UpdateColumValues(unsigned col);
|
||||
void UpdateExtruderBitmap(wxDataViewItem item);
|
||||
|
||||
private:
|
||||
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
|
||||
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BitmapTextRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
class BitmapTextRenderer : public wxDataViewRenderer
|
||||
#else
|
||||
class BitmapTextRenderer : public wxDataViewCustomRenderer
|
||||
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
{
|
||||
public:
|
||||
BitmapTextRenderer(wxDataViewCellMode mode =
|
||||
#ifdef __WXOSX__
|
||||
wxDATAVIEW_CELL_INERT
|
||||
#else
|
||||
wxDATAVIEW_CELL_EDITABLE
|
||||
#endif
|
||||
|
||||
,int align = wxDVR_DEFAULT_ALIGNMENT
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
);
|
||||
#else
|
||||
) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {}
|
||||
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
|
||||
bool SetValue(const wxVariant &value);
|
||||
bool GetValue(wxVariant &value) const;
|
||||
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
|
||||
virtual wxString GetAccessibleDescription() const override;
|
||||
#endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
||||
|
||||
virtual bool Render(wxRect cell, wxDC *dc, int state);
|
||||
virtual wxSize GetSize() const;
|
||||
|
||||
bool HasEditorCtrl() const override
|
||||
{
|
||||
#ifdef __WXOSX__
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
wxWindow* CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) override;
|
||||
bool GetValueFromEditorCtrl( wxWindow* ctrl,
|
||||
wxVariant& value) override;
|
||||
bool WasCanceled() const { return m_was_unusable_symbol; }
|
||||
|
||||
private:
|
||||
DataViewBitmapText m_value;
|
||||
bool m_was_unusable_symbol {false};
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// BitmapChoiceRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BitmapChoiceRenderer : public wxDataViewCustomRenderer
|
||||
{
|
||||
public:
|
||||
BitmapChoiceRenderer(wxDataViewCellMode mode =
|
||||
#ifdef __WXOSX__
|
||||
wxDATAVIEW_CELL_INERT
|
||||
#else
|
||||
wxDATAVIEW_CELL_EDITABLE
|
||||
#endif
|
||||
,int align = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
|
||||
) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {}
|
||||
|
||||
bool SetValue(const wxVariant& value);
|
||||
bool GetValue(wxVariant& value) const;
|
||||
|
||||
virtual bool Render(wxRect cell, wxDC* dc, int state);
|
||||
virtual wxSize GetSize() const;
|
||||
|
||||
bool HasEditorCtrl() const override { return true; }
|
||||
wxWindow* CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) override;
|
||||
bool GetValueFromEditorCtrl( wxWindow* ctrl,
|
||||
wxVariant& value) override;
|
||||
|
||||
private:
|
||||
DataViewBitmapText m_value;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MyCustomRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class MyCustomRenderer : public wxDataViewCustomRenderer
|
||||
{
|
||||
public:
|
||||
// This renderer can be either activatable or editable, for demonstration
|
||||
// purposes. In real programs, you should select whether the user should be
|
||||
// able to activate or edit the cell and it doesn't make sense to switch
|
||||
// between the two -- but this is just an example, so it doesn't stop us.
|
||||
explicit MyCustomRenderer(wxDataViewCellMode mode)
|
||||
: wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
|
||||
{ }
|
||||
|
||||
virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/
|
||||
{
|
||||
dc->SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
dc->SetPen(*wxTRANSPARENT_PEN);
|
||||
|
||||
rect.Deflate(2);
|
||||
dc->DrawRoundedRectangle(rect, 5);
|
||||
|
||||
RenderText(m_value,
|
||||
0, // no offset
|
||||
wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
|
||||
dc,
|
||||
state);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
|
||||
wxDataViewModel *WXUNUSED(model),
|
||||
const wxDataViewItem &WXUNUSED(item),
|
||||
unsigned int WXUNUSED(col),
|
||||
const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/
|
||||
{
|
||||
wxString position;
|
||||
if (mouseEvent)
|
||||
position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
|
||||
else
|
||||
position = "from keyboard";
|
||||
// wxLogMessage("MyCustomRenderer ActivateCell() %s", position);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual wxSize GetSize() const override/*wxOVERRIDE*/
|
||||
{
|
||||
return wxSize(60, 20);
|
||||
}
|
||||
|
||||
virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/
|
||||
{
|
||||
m_value = value.GetString();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; }
|
||||
|
||||
virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; }
|
||||
|
||||
virtual wxWindow*
|
||||
CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) override/*wxOVERRIDE*/
|
||||
{
|
||||
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
|
||||
labelRect.GetPosition(),
|
||||
labelRect.GetSize(),
|
||||
wxTE_PROCESS_ENTER);
|
||||
text->SetInsertionPointEnd();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/
|
||||
{
|
||||
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
|
||||
if (!text)
|
||||
return false;
|
||||
|
||||
value = text->GetValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_value;
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ScalableBitmap
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -718,11 +157,14 @@ public:
|
|||
ScalableBitmap() {};
|
||||
ScalableBitmap( wxWindow *parent,
|
||||
const std::string& icon_name = "",
|
||||
const int px_cnt = 16,
|
||||
const bool is_horizontal = false);
|
||||
const int px_cnt = 16);
|
||||
|
||||
~ScalableBitmap() {}
|
||||
|
||||
wxSize GetBmpSize() const;
|
||||
int GetBmpWidth() const;
|
||||
int GetBmpHeight() const;
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
const wxBitmap& bmp() const { return m_bmp; }
|
||||
|
|
@ -730,14 +172,12 @@ public:
|
|||
const std::string& name() const{ return m_icon_name; }
|
||||
|
||||
int px_cnt()const {return m_px_cnt;}
|
||||
bool is_horizontal()const {return m_is_horizontal;}
|
||||
|
||||
private:
|
||||
wxWindow* m_parent{ nullptr };
|
||||
wxBitmap m_bmp = wxBitmap();
|
||||
std::string m_icon_name = "";
|
||||
int m_px_cnt {16};
|
||||
bool m_is_horizontal {false};
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -821,7 +261,6 @@ private:
|
|||
|
||||
// bitmap dimensions
|
||||
int m_px_cnt{ 16 };
|
||||
bool m_is_horizontal{ false };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue