Warning and legend textures moved from _3DScene class to GLCanvas3D class
This commit is contained in:
parent
5ff26bce50
commit
63fe2a9fb9
6 changed files with 313 additions and 324 deletions
|
@ -22,11 +22,6 @@
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/spin_mutex.h>
|
#include <tbb/spin_mutex.h>
|
||||||
|
|
||||||
#include <wx/bitmap.h>
|
|
||||||
#include <wx/dcmemory.h>
|
|
||||||
#include <wx/image.h>
|
|
||||||
#include <wx/settings.h>
|
|
||||||
|
|
||||||
#include <Eigen/Dense>
|
#include <Eigen/Dense>
|
||||||
|
|
||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
|
@ -1589,228 +1584,8 @@ void _3DScene::point3_to_verts(const Point3& point, double width, double height,
|
||||||
thick_point_to_verts(point, width, height, volume);
|
thick_point_to_verts(point, width, height, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
_3DScene::LegendTexture _3DScene::s_legend_texture;
|
|
||||||
_3DScene::WarningTexture _3DScene::s_warning_texture;
|
|
||||||
GUI::GLCanvas3DManager _3DScene::s_canvas_mgr;
|
GUI::GLCanvas3DManager _3DScene::s_canvas_mgr;
|
||||||
|
|
||||||
const unsigned char _3DScene::WarningTexture::Background_Color[3] = { 9, 91, 134 };
|
|
||||||
const unsigned char _3DScene::WarningTexture::Opacity = 255;
|
|
||||||
|
|
||||||
bool _3DScene::WarningTexture::generate(const std::string& msg)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
|
|
||||||
if (msg.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wxMemoryDC memDC;
|
|
||||||
// select default font
|
|
||||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
|
||||||
|
|
||||||
// calculates texture size
|
|
||||||
wxCoord w, h;
|
|
||||||
memDC.GetTextExtent(msg, &w, &h);
|
|
||||||
m_width = (int)w;
|
|
||||||
m_height = (int)h;
|
|
||||||
|
|
||||||
// generates bitmap
|
|
||||||
wxBitmap bitmap(m_width, m_height);
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
|
||||||
bitmap.UseAlpha();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memDC.SelectObject(bitmap);
|
|
||||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
|
||||||
memDC.Clear();
|
|
||||||
|
|
||||||
memDC.SetTextForeground(*wxWHITE);
|
|
||||||
|
|
||||||
// draw message
|
|
||||||
memDC.DrawText(msg, 0, 0);
|
|
||||||
|
|
||||||
memDC.SelectObject(wxNullBitmap);
|
|
||||||
|
|
||||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
|
||||||
wxImage image = bitmap.ConvertToImage();
|
|
||||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
|
||||||
|
|
||||||
// prepare buffer
|
|
||||||
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
|
||||||
for (int h = 0; h < m_height; ++h)
|
|
||||||
{
|
|
||||||
int hh = h * m_width;
|
|
||||||
unsigned char* px_ptr = data.data() + 4 * hh;
|
|
||||||
for (int w = 0; w < m_width; ++w)
|
|
||||||
{
|
|
||||||
*px_ptr++ = image.GetRed(w, h);
|
|
||||||
*px_ptr++ = image.GetGreen(w, h);
|
|
||||||
*px_ptr++ = image.GetBlue(w, h);
|
|
||||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sends buffer to gpu
|
|
||||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
::glGenTextures(1, &m_id);
|
|
||||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
|
||||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
|
||||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char _3DScene::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
|
|
||||||
const unsigned char _3DScene::LegendTexture::Background_Color[3] = { 9, 91, 134 };
|
|
||||||
const unsigned char _3DScene::LegendTexture::Opacity = 255;
|
|
||||||
|
|
||||||
bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
|
|
||||||
// collects items to render
|
|
||||||
auto title = _(preview_data.get_legend_title());
|
|
||||||
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
|
|
||||||
|
|
||||||
unsigned int items_count = (unsigned int)items.size();
|
|
||||||
if (items_count == 0)
|
|
||||||
// nothing to render, return
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wxMemoryDC memDC;
|
|
||||||
// select default font
|
|
||||||
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
|
||||||
|
|
||||||
// calculates texture size
|
|
||||||
wxCoord w, h;
|
|
||||||
memDC.GetTextExtent(title, &w, &h);
|
|
||||||
int title_width = (int)w;
|
|
||||||
int title_height = (int)h;
|
|
||||||
|
|
||||||
int max_text_width = 0;
|
|
||||||
int max_text_height = 0;
|
|
||||||
for (const GCodePreviewData::LegendItem& item : items)
|
|
||||||
{
|
|
||||||
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
|
|
||||||
max_text_width = std::max(max_text_width, (int)w);
|
|
||||||
max_text_height = std::max(max_text_height, (int)h);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
|
|
||||||
m_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
|
|
||||||
if (items_count > 1)
|
|
||||||
m_height += (items_count - 1) * Px_Square_Contour;
|
|
||||||
|
|
||||||
// generates bitmap
|
|
||||||
wxBitmap bitmap(m_width, m_height);
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(_MSC_VER)
|
|
||||||
bitmap.UseAlpha();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memDC.SelectObject(bitmap);
|
|
||||||
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
|
||||||
memDC.Clear();
|
|
||||||
|
|
||||||
memDC.SetTextForeground(*wxWHITE);
|
|
||||||
|
|
||||||
// draw title
|
|
||||||
int title_x = Px_Border;
|
|
||||||
int title_y = Px_Border;
|
|
||||||
memDC.DrawText(title, title_x, title_y);
|
|
||||||
|
|
||||||
// draw icons contours as background
|
|
||||||
int squares_contour_x = Px_Border;
|
|
||||||
int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
|
|
||||||
int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
|
|
||||||
int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
|
|
||||||
if (items_count > 1)
|
|
||||||
squares_contour_height += (items_count - 1) * Px_Square_Contour;
|
|
||||||
|
|
||||||
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
|
|
||||||
wxPen pen(color);
|
|
||||||
wxBrush brush(color);
|
|
||||||
memDC.SetPen(pen);
|
|
||||||
memDC.SetBrush(brush);
|
|
||||||
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
|
|
||||||
|
|
||||||
// draw items (colored icon + text)
|
|
||||||
int icon_x = squares_contour_x + Px_Square_Contour;
|
|
||||||
int icon_x_inner = icon_x + 1;
|
|
||||||
int icon_y = squares_contour_y + Px_Square_Contour;
|
|
||||||
int icon_y_step = Px_Square + Px_Square_Contour;
|
|
||||||
|
|
||||||
int text_x = icon_x + Px_Square + Px_Text_Offset;
|
|
||||||
int text_y_offset = (Px_Square - max_text_height) / 2;
|
|
||||||
|
|
||||||
int px_inner_square = Px_Square - 2;
|
|
||||||
|
|
||||||
for (const GCodePreviewData::LegendItem& item : items)
|
|
||||||
{
|
|
||||||
// draw darker icon perimeter
|
|
||||||
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
|
|
||||||
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
|
|
||||||
dark_hsv.value *= 0.75;
|
|
||||||
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
|
|
||||||
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
|
|
||||||
pen.SetColour(color);
|
|
||||||
brush.SetColour(color);
|
|
||||||
memDC.SetPen(pen);
|
|
||||||
memDC.SetBrush(brush);
|
|
||||||
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
|
|
||||||
|
|
||||||
// draw icon interior
|
|
||||||
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
|
|
||||||
pen.SetColour(color);
|
|
||||||
brush.SetColour(color);
|
|
||||||
memDC.SetPen(pen);
|
|
||||||
memDC.SetBrush(brush);
|
|
||||||
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
|
|
||||||
|
|
||||||
// draw text
|
|
||||||
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
|
|
||||||
|
|
||||||
// update y
|
|
||||||
icon_y += icon_y_step;
|
|
||||||
}
|
|
||||||
|
|
||||||
memDC.SelectObject(wxNullBitmap);
|
|
||||||
|
|
||||||
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
|
||||||
wxImage image = bitmap.ConvertToImage();
|
|
||||||
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
|
||||||
|
|
||||||
// prepare buffer
|
|
||||||
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
|
||||||
for (int h = 0; h < m_height; ++h)
|
|
||||||
{
|
|
||||||
int hh = h * m_width;
|
|
||||||
unsigned char* px_ptr = data.data() + 4 * hh;
|
|
||||||
for (int w = 0; w < m_width; ++w)
|
|
||||||
{
|
|
||||||
*px_ptr++ = image.GetRed(w, h);
|
|
||||||
*px_ptr++ = image.GetGreen(w, h);
|
|
||||||
*px_ptr++ = image.GetBlue(w, h);
|
|
||||||
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sends buffer to gpu
|
|
||||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
::glGenTextures(1, &m_id);
|
|
||||||
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
|
||||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
|
||||||
::glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3DScene::init_gl()
|
void _3DScene::init_gl()
|
||||||
{
|
{
|
||||||
s_canvas_mgr.init_gl();
|
s_canvas_mgr.init_gl();
|
||||||
|
@ -2213,54 +1988,9 @@ void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* pr
|
||||||
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _3DScene::generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
|
||||||
{
|
|
||||||
s_legend_texture.generate(preview_data, tool_colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3DScene::reset_legend_texture()
|
void _3DScene::reset_legend_texture()
|
||||||
{
|
{
|
||||||
s_legend_texture.reset();
|
s_canvas_mgr.reset_legend_texture();
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int _3DScene::get_legend_texture_id()
|
|
||||||
{
|
|
||||||
return s_legend_texture.get_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _3DScene::get_legend_texture_width()
|
|
||||||
{
|
|
||||||
return s_legend_texture.get_width();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _3DScene::get_legend_texture_height()
|
|
||||||
{
|
|
||||||
return s_legend_texture.get_height();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3DScene::generate_warning_texture(const std::string& msg)
|
|
||||||
{
|
|
||||||
s_warning_texture.generate(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3DScene::reset_warning_texture()
|
|
||||||
{
|
|
||||||
s_warning_texture.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int _3DScene::get_warning_texture_id()
|
|
||||||
{
|
|
||||||
return s_warning_texture.get_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _3DScene::get_warning_texture_width()
|
|
||||||
{
|
|
||||||
return s_warning_texture.get_width();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _3DScene::get_warning_texture_height()
|
|
||||||
{
|
|
||||||
return s_warning_texture.get_height();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "../../libslic3r/Utils.hpp"
|
#include "../../libslic3r/Utils.hpp"
|
||||||
#include "../../libslic3r/Model.hpp"
|
#include "../../libslic3r/Model.hpp"
|
||||||
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
||||||
#include "../../slic3r/GUI/GLTexture.hpp"
|
|
||||||
|
|
||||||
class wxBitmap;
|
class wxBitmap;
|
||||||
class wxWindow;
|
class wxWindow;
|
||||||
|
@ -441,32 +440,6 @@ private:
|
||||||
|
|
||||||
class _3DScene
|
class _3DScene
|
||||||
{
|
{
|
||||||
class WarningTexture : public GUI::GLTexture
|
|
||||||
{
|
|
||||||
static const unsigned char Background_Color[3];
|
|
||||||
static const unsigned char Opacity;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool generate(const std::string& msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
class LegendTexture : public GUI::GLTexture
|
|
||||||
{
|
|
||||||
static const int Px_Title_Offset = 5;
|
|
||||||
static const int Px_Text_Offset = 5;
|
|
||||||
static const int Px_Square = 20;
|
|
||||||
static const int Px_Square_Contour = 1;
|
|
||||||
static const int Px_Border = Px_Square / 2;
|
|
||||||
static const unsigned char Squares_Border_Color[3];
|
|
||||||
static const unsigned char Background_Color[3];
|
|
||||||
static const unsigned char Opacity;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
|
||||||
};
|
|
||||||
|
|
||||||
static LegendTexture s_legend_texture;
|
|
||||||
static WarningTexture s_warning_texture;
|
|
||||||
static GUI::GLCanvas3DManager s_canvas_mgr;
|
static GUI::GLCanvas3DManager s_canvas_mgr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -568,22 +541,8 @@ public:
|
||||||
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||||
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
|
|
||||||
// generates the legend texture in dependence of the current shown view type
|
|
||||||
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
|
||||||
static void reset_legend_texture();
|
static void reset_legend_texture();
|
||||||
|
|
||||||
static unsigned int get_legend_texture_id();
|
|
||||||
static int get_legend_texture_width();
|
|
||||||
static int get_legend_texture_height();
|
|
||||||
|
|
||||||
// generates a warning texture containing the given message
|
|
||||||
static void generate_warning_texture(const std::string& msg);
|
|
||||||
static void reset_warning_texture();
|
|
||||||
|
|
||||||
static unsigned int get_warning_texture_id();
|
|
||||||
static int get_warning_texture_width();
|
|
||||||
static int get_warning_texture_height();
|
|
||||||
|
|
||||||
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
|
||||||
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
|
||||||
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
|
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
|
|
||||||
#include <wx/glcanvas.h>
|
#include <wx/glcanvas.h>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
|
#include <wx/bitmap.h>
|
||||||
|
#include <wx/dcmemory.h>
|
||||||
|
#include <wx/image.h>
|
||||||
|
#include <wx/settings.h>
|
||||||
|
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/spin_mutex.h>
|
#include <tbb/spin_mutex.h>
|
||||||
|
@ -1457,6 +1461,224 @@ float GLCanvas3D::Gizmos::_get_total_overlay_height() const
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 9, 91, 134 };
|
||||||
|
const unsigned char GLCanvas3D::WarningTexture::Opacity = 255;
|
||||||
|
|
||||||
|
bool GLCanvas3D::WarningTexture::generate(const std::string& msg)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
|
||||||
|
if (msg.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxMemoryDC memDC;
|
||||||
|
// select default font
|
||||||
|
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
|
|
||||||
|
// calculates texture size
|
||||||
|
wxCoord w, h;
|
||||||
|
memDC.GetTextExtent(msg, &w, &h);
|
||||||
|
m_width = (int)w;
|
||||||
|
m_height = (int)h;
|
||||||
|
|
||||||
|
// generates bitmap
|
||||||
|
wxBitmap bitmap(m_width, m_height);
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||||
|
bitmap.UseAlpha();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memDC.SelectObject(bitmap);
|
||||||
|
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||||
|
memDC.Clear();
|
||||||
|
|
||||||
|
memDC.SetTextForeground(*wxWHITE);
|
||||||
|
|
||||||
|
// draw message
|
||||||
|
memDC.DrawText(msg, 0, 0);
|
||||||
|
|
||||||
|
memDC.SelectObject(wxNullBitmap);
|
||||||
|
|
||||||
|
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||||
|
wxImage image = bitmap.ConvertToImage();
|
||||||
|
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||||
|
|
||||||
|
// prepare buffer
|
||||||
|
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
||||||
|
for (int h = 0; h < m_height; ++h)
|
||||||
|
{
|
||||||
|
int hh = h * m_width;
|
||||||
|
unsigned char* px_ptr = data.data() + 4 * hh;
|
||||||
|
for (int w = 0; w < m_width; ++w)
|
||||||
|
{
|
||||||
|
*px_ptr++ = image.GetRed(w, h);
|
||||||
|
*px_ptr++ = image.GetGreen(w, h);
|
||||||
|
*px_ptr++ = image.GetBlue(w, h);
|
||||||
|
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends buffer to gpu
|
||||||
|
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
::glGenTextures(1, &m_id);
|
||||||
|
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
||||||
|
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||||
|
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char GLCanvas3D::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
|
||||||
|
const unsigned char GLCanvas3D::LegendTexture::Background_Color[3] = { 9, 91, 134 };
|
||||||
|
const unsigned char GLCanvas3D::LegendTexture::Opacity = 255;
|
||||||
|
|
||||||
|
bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
|
||||||
|
// collects items to render
|
||||||
|
auto title = _(preview_data.get_legend_title());
|
||||||
|
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
|
||||||
|
|
||||||
|
unsigned int items_count = (unsigned int)items.size();
|
||||||
|
if (items_count == 0)
|
||||||
|
// nothing to render, return
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxMemoryDC memDC;
|
||||||
|
// select default font
|
||||||
|
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
|
|
||||||
|
// calculates texture size
|
||||||
|
wxCoord w, h;
|
||||||
|
memDC.GetTextExtent(title, &w, &h);
|
||||||
|
int title_width = (int)w;
|
||||||
|
int title_height = (int)h;
|
||||||
|
|
||||||
|
int max_text_width = 0;
|
||||||
|
int max_text_height = 0;
|
||||||
|
for (const GCodePreviewData::LegendItem& item : items)
|
||||||
|
{
|
||||||
|
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
|
||||||
|
max_text_width = std::max(max_text_width, (int)w);
|
||||||
|
max_text_height = std::max(max_text_height, (int)h);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
|
||||||
|
m_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
|
||||||
|
if (items_count > 1)
|
||||||
|
m_height += (items_count - 1) * Px_Square_Contour;
|
||||||
|
|
||||||
|
// generates bitmap
|
||||||
|
wxBitmap bitmap(m_width, m_height);
|
||||||
|
|
||||||
|
#if defined(__APPLE__) || defined(_MSC_VER)
|
||||||
|
bitmap.UseAlpha();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memDC.SelectObject(bitmap);
|
||||||
|
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
|
||||||
|
memDC.Clear();
|
||||||
|
|
||||||
|
memDC.SetTextForeground(*wxWHITE);
|
||||||
|
|
||||||
|
// draw title
|
||||||
|
int title_x = Px_Border;
|
||||||
|
int title_y = Px_Border;
|
||||||
|
memDC.DrawText(title, title_x, title_y);
|
||||||
|
|
||||||
|
// draw icons contours as background
|
||||||
|
int squares_contour_x = Px_Border;
|
||||||
|
int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
|
||||||
|
int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
|
||||||
|
int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
|
||||||
|
if (items_count > 1)
|
||||||
|
squares_contour_height += (items_count - 1) * Px_Square_Contour;
|
||||||
|
|
||||||
|
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
|
||||||
|
wxPen pen(color);
|
||||||
|
wxBrush brush(color);
|
||||||
|
memDC.SetPen(pen);
|
||||||
|
memDC.SetBrush(brush);
|
||||||
|
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
|
||||||
|
|
||||||
|
// draw items (colored icon + text)
|
||||||
|
int icon_x = squares_contour_x + Px_Square_Contour;
|
||||||
|
int icon_x_inner = icon_x + 1;
|
||||||
|
int icon_y = squares_contour_y + Px_Square_Contour;
|
||||||
|
int icon_y_step = Px_Square + Px_Square_Contour;
|
||||||
|
|
||||||
|
int text_x = icon_x + Px_Square + Px_Text_Offset;
|
||||||
|
int text_y_offset = (Px_Square - max_text_height) / 2;
|
||||||
|
|
||||||
|
int px_inner_square = Px_Square - 2;
|
||||||
|
|
||||||
|
for (const GCodePreviewData::LegendItem& item : items)
|
||||||
|
{
|
||||||
|
// draw darker icon perimeter
|
||||||
|
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
|
||||||
|
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
|
||||||
|
dark_hsv.value *= 0.75;
|
||||||
|
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
|
||||||
|
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
|
||||||
|
pen.SetColour(color);
|
||||||
|
brush.SetColour(color);
|
||||||
|
memDC.SetPen(pen);
|
||||||
|
memDC.SetBrush(brush);
|
||||||
|
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
|
||||||
|
|
||||||
|
// draw icon interior
|
||||||
|
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
|
||||||
|
pen.SetColour(color);
|
||||||
|
brush.SetColour(color);
|
||||||
|
memDC.SetPen(pen);
|
||||||
|
memDC.SetBrush(brush);
|
||||||
|
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
|
||||||
|
|
||||||
|
// draw text
|
||||||
|
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
|
||||||
|
|
||||||
|
// update y
|
||||||
|
icon_y += icon_y_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
memDC.SelectObject(wxNullBitmap);
|
||||||
|
|
||||||
|
// Convert the bitmap into a linear data ready to be loaded into the GPU.
|
||||||
|
wxImage image = bitmap.ConvertToImage();
|
||||||
|
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
|
||||||
|
|
||||||
|
// prepare buffer
|
||||||
|
std::vector<unsigned char> data(4 * m_width * m_height, 0);
|
||||||
|
for (int h = 0; h < m_height; ++h)
|
||||||
|
{
|
||||||
|
int hh = h * m_width;
|
||||||
|
unsigned char* px_ptr = data.data() + 4 * hh;
|
||||||
|
for (int w = 0; w < m_width; ++w)
|
||||||
|
{
|
||||||
|
*px_ptr++ = image.GetRed(w, h);
|
||||||
|
*px_ptr++ = image.GetGreen(w, h);
|
||||||
|
*px_ptr++ = image.GetBlue(w, h);
|
||||||
|
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends buffer to gpu
|
||||||
|
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
::glGenTextures(1, &m_id);
|
||||||
|
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
|
||||||
|
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
|
||||||
|
::glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
|
GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
|
||||||
{
|
{
|
||||||
GizmosMap::const_iterator it = m_gizmos.find(m_current);
|
GizmosMap::const_iterator it = m_gizmos.find(m_current);
|
||||||
|
@ -2079,21 +2301,21 @@ void GLCanvas3D::reload_scene(bool force)
|
||||||
if (!contained)
|
if (!contained)
|
||||||
{
|
{
|
||||||
enable_warning_texture(true);
|
enable_warning_texture(true);
|
||||||
_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
_generate_warning_texture(L("Detected object outside print volume"));
|
||||||
m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
|
m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enable_warning_texture(false);
|
enable_warning_texture(false);
|
||||||
m_volumes.reset_outside_state();
|
m_volumes.reset_outside_state();
|
||||||
_3DScene::reset_warning_texture();
|
_reset_warning_texture();
|
||||||
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
|
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enable_warning_texture(false);
|
enable_warning_texture(false);
|
||||||
_3DScene::reset_warning_texture();
|
_reset_warning_texture();
|
||||||
m_on_enable_action_buttons_callback.call(false);
|
m_on_enable_action_buttons_callback.call(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2484,10 +2706,10 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
|
||||||
_load_gcode_unretractions(preview_data);
|
_load_gcode_unretractions(preview_data);
|
||||||
|
|
||||||
if (m_volumes.empty())
|
if (m_volumes.empty())
|
||||||
_3DScene::reset_legend_texture();
|
reset_legend_texture();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_3DScene::generate_legend_texture(preview_data, tool_colors);
|
_generate_legend_texture(preview_data, tool_colors);
|
||||||
|
|
||||||
// removes empty volumes
|
// removes empty volumes
|
||||||
m_volumes.volumes.erase(std::remove_if(m_volumes.volumes.begin(), m_volumes.volumes.end(),
|
m_volumes.volumes.erase(std::remove_if(m_volumes.volumes.begin(), m_volumes.volumes.end(),
|
||||||
|
@ -3176,6 +3398,14 @@ Point GLCanvas3D::get_local_mouse_position() const
|
||||||
return Point(mouse_pos.x, mouse_pos.y);
|
return Point(mouse_pos.x, mouse_pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::reset_legend_texture()
|
||||||
|
{
|
||||||
|
if (!set_current())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_legend_texture.reset();
|
||||||
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::_is_shown_on_screen() const
|
bool GLCanvas3D::_is_shown_on_screen() const
|
||||||
{
|
{
|
||||||
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
|
||||||
|
@ -3584,11 +3814,11 @@ void GLCanvas3D::_render_warning_texture() const
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the warning texture has not been loaded into the GPU, do it now.
|
// If the warning texture has not been loaded into the GPU, do it now.
|
||||||
unsigned int tex_id = _3DScene::get_warning_texture_id();
|
unsigned int tex_id = m_warning_texture.get_id();
|
||||||
if (tex_id > 0)
|
if (tex_id > 0)
|
||||||
{
|
{
|
||||||
unsigned int w = _3DScene::get_warning_texture_width();
|
int w = m_warning_texture.get_width();
|
||||||
unsigned int h = _3DScene::get_warning_texture_height();
|
int h = m_warning_texture.get_height();
|
||||||
if ((w > 0) && (h > 0))
|
if ((w > 0) && (h > 0))
|
||||||
{
|
{
|
||||||
::glDisable(GL_DEPTH_TEST);
|
::glDisable(GL_DEPTH_TEST);
|
||||||
|
@ -3617,11 +3847,11 @@ void GLCanvas3D::_render_legend_texture() const
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the legend texture has not been loaded into the GPU, do it now.
|
// If the legend texture has not been loaded into the GPU, do it now.
|
||||||
unsigned int tex_id = _3DScene::get_legend_texture_id();
|
unsigned int tex_id = m_legend_texture.get_id();
|
||||||
if (tex_id > 0)
|
if (tex_id > 0)
|
||||||
{
|
{
|
||||||
unsigned int w = _3DScene::get_legend_texture_width();
|
int w = m_legend_texture.get_width();
|
||||||
unsigned int h = _3DScene::get_legend_texture_height();
|
int h = m_legend_texture.get_height();
|
||||||
if ((w > 0) && (h > 0))
|
if ((w > 0) && (h > 0))
|
||||||
{
|
{
|
||||||
::glDisable(GL_DEPTH_TEST);
|
::glDisable(GL_DEPTH_TEST);
|
||||||
|
@ -4535,5 +4765,29 @@ std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& col
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
|
{
|
||||||
|
if (!set_current())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_legend_texture.generate(preview_data, tool_colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_generate_warning_texture(const std::string& msg)
|
||||||
|
{
|
||||||
|
if (!set_current())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_warning_texture.generate(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::_reset_warning_texture()
|
||||||
|
{
|
||||||
|
if (!set_current())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_warning_texture.reset();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -394,9 +394,35 @@ public:
|
||||||
GLGizmoBase* _get_current() const;
|
GLGizmoBase* _get_current() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WarningTexture : public GUI::GLTexture
|
||||||
|
{
|
||||||
|
static const unsigned char Background_Color[3];
|
||||||
|
static const unsigned char Opacity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool generate(const std::string& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LegendTexture : public GUI::GLTexture
|
||||||
|
{
|
||||||
|
static const int Px_Title_Offset = 5;
|
||||||
|
static const int Px_Text_Offset = 5;
|
||||||
|
static const int Px_Square = 20;
|
||||||
|
static const int Px_Square_Contour = 1;
|
||||||
|
static const int Px_Border = Px_Square / 2;
|
||||||
|
static const unsigned char Squares_Border_Color[3];
|
||||||
|
static const unsigned char Background_Color[3];
|
||||||
|
static const unsigned char Opacity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxGLCanvas* m_canvas;
|
wxGLCanvas* m_canvas;
|
||||||
wxGLContext* m_context;
|
wxGLContext* m_context;
|
||||||
|
LegendTexture m_legend_texture;
|
||||||
|
WarningTexture m_warning_texture;
|
||||||
wxTimer* m_timer;
|
wxTimer* m_timer;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
Bed m_bed;
|
Bed m_bed;
|
||||||
|
@ -578,6 +604,8 @@ public:
|
||||||
Size get_canvas_size() const;
|
Size get_canvas_size() const;
|
||||||
Point get_local_mouse_position() const;
|
Point get_local_mouse_position() const;
|
||||||
|
|
||||||
|
void reset_legend_texture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_shown_on_screen() const;
|
bool _is_shown_on_screen() const;
|
||||||
void _force_zoom_to_bed();
|
void _force_zoom_to_bed();
|
||||||
|
@ -643,6 +671,13 @@ private:
|
||||||
void _on_move(const std::vector<int>& volume_idxs);
|
void _on_move(const std::vector<int>& volume_idxs);
|
||||||
void _on_select(int volume_idx);
|
void _on_select(int volume_idx);
|
||||||
|
|
||||||
|
// generates the legend texture in dependence of the current shown view type
|
||||||
|
void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
|
|
||||||
|
// generates a warning texture containing the given message
|
||||||
|
void _generate_warning_texture(const std::string& msg);
|
||||||
|
void _reset_warning_texture();
|
||||||
|
|
||||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -550,6 +550,15 @@ void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePrevie
|
||||||
it->second->load_gcode_preview(*preview_data, str_tool_colors);
|
it->second->load_gcode_preview(*preview_data, str_tool_colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3DManager::reset_legend_texture()
|
||||||
|
{
|
||||||
|
for (CanvasesMap::value_type& canvas : m_canvases)
|
||||||
|
{
|
||||||
|
if (canvas.second != nullptr)
|
||||||
|
canvas.second->reset_legend_texture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
|
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
|
||||||
{
|
{
|
||||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
|
|
@ -137,6 +137,8 @@ public:
|
||||||
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||||
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
|
|
||||||
|
void reset_legend_texture();
|
||||||
|
|
||||||
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
||||||
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
|
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
|
||||||
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
|
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
|
||||||
|
|
Loading…
Add table
Reference in a new issue