GCode Preview - Added legend texture

This commit is contained in:
Enrico Turri 2018-01-16 14:59:06 +01:00
parent 9e0dd2a96a
commit c63e6b74fa
7 changed files with 548 additions and 13 deletions

View File

@ -30,6 +30,7 @@ use Slic3r::Geometry qw(PI);
# _dirty: boolean flag indicating, that the screen has to be redrawn on EVT_IDLE. # _dirty: boolean flag indicating, that the screen has to be redrawn on EVT_IDLE.
# volumes: reference to vector of Slic3r::GUI::3DScene::Volume. # volumes: reference to vector of Slic3r::GUI::3DScene::Volume.
# _camera_type: 'perspective' or 'ortho' # _camera_type: 'perspective' or 'ortho'
# ===================== ENRICO_GCODE_PREVIEW ==================================================
__PACKAGE__->mk_accessors( qw(_quat _dirty init __PACKAGE__->mk_accessors( qw(_quat _dirty init
enable_picking enable_picking
enable_moving enable_moving
@ -66,8 +67,51 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init
_camera_target _camera_target
_camera_distance _camera_distance
_zoom _zoom
_legend_enabled
) ); ) );
#__PACKAGE__->mk_accessors( qw(_quat _dirty init
# enable_picking
# enable_moving
# use_plain_shader
# on_viewport_changed
# on_hover
# on_select
# on_double_click
# on_right_click
# on_move
# on_model_update
# volumes
# _sphi _stheta
# cutting_plane_z
# cut_lines_vertices
# bed_shape
# bed_triangles
# bed_grid_lines
# bed_polygon
# background
# origin
# _mouse_pos
# _hover_volume_idx
#
# _drag_volume_idx
# _drag_start_pos
# _drag_volume_center_offset
# _drag_start_xy
# _dragged
#
# _layer_height_edited
#
# _camera_type
# _camera_target
# _camera_distance
# _zoom
#
# ) );
# ===================== ENRICO_GCODE_PREVIEW ==================================================
use constant TRACKBALLSIZE => 0.8; use constant TRACKBALLSIZE => 0.8;
use constant TURNTABLE_MODE => 1; use constant TURNTABLE_MODE => 1;
use constant GROUND_Z => -0.02; use constant GROUND_Z => -0.02;
@ -137,6 +181,9 @@ sub new {
$self->_stheta(45); $self->_stheta(45);
$self->_sphi(45); $self->_sphi(45);
$self->_zoom(1); $self->_zoom(1);
# ===================== ENRICO_GCODE_PREVIEW ==================================================
$self->_legend_enabled(0);
# ===================== ENRICO_GCODE_PREVIEW ==================================================
$self->use_plain_shader(0); $self->use_plain_shader(0);
# Collection of GLVolume objects # Collection of GLVolume objects
@ -209,6 +256,13 @@ sub new {
return $self; return $self;
} }
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub set_legend_enabled {
my ($self, $value) = @_;
$self->_legend_enabled($value);
}
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub Destroy { sub Destroy {
my ($self) = @_; my ($self) = @_;
$self->{layer_height_edit_timer}->Stop; $self->{layer_height_edit_timer}->Stop;
@ -1316,6 +1370,11 @@ sub Render {
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
# ===================== ENRICO_GCODE_PREVIEW ==================================================
# draw gcode preview legend
$self->draw_legend;
# ===================== ENRICO_GCODE_PREVIEW ==================================================
$self->draw_active_object_annotations; $self->draw_active_object_annotations;
$self->SwapBuffers(); $self->SwapBuffers();
@ -1449,12 +1508,38 @@ sub _variable_layer_thickness_load_reset_image {
# Paint the tooltip. # Paint the tooltip.
sub _render_image { sub _render_image {
my ($self, $image, $l, $r, $b, $t) = @_; my ($self, $image, $l, $r, $b, $t) = @_;
# ===================== ENRICO_GCODE_PREVIEW ==================================================
$self->_render_texture($image->{texture_id}, $l, $r, $b, $t);
# glColor4f(1.,1.,1.,1.);
# glDisable(GL_LIGHTING);
# glEnable(GL_BLEND);
# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
# glEnable(GL_TEXTURE_2D);
# glBindTexture(GL_TEXTURE_2D, $image->{texture_id});
# glBegin(GL_QUADS);
# glTexCoord2d(0.,1.); glVertex3f($l, $b, 0);
# glTexCoord2d(1.,1.); glVertex3f($r, $b, 0);
# glTexCoord2d(1.,0.); glVertex3f($r, $t, 0);
# glTexCoord2d(0.,0.); glVertex3f($l, $t, 0);
# glEnd();
# glBindTexture(GL_TEXTURE_2D, 0);
# glDisable(GL_TEXTURE_2D);
# glDisable(GL_BLEND);
# glEnable(GL_LIGHTING);
# ===================== ENRICO_GCODE_PREVIEW ==================================================
}
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub _render_texture {
my ($self, $tex_id, $l, $r, $b, $t) = @_;
glColor4f(1.,1.,1.,1.); glColor4f(1.,1.,1.,1.);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, $image->{texture_id}); glBindTexture(GL_TEXTURE_2D, $tex_id);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2d(0.,1.); glVertex3f($l, $b, 0); glTexCoord2d(0.,1.); glVertex3f($l, $b, 0);
glTexCoord2d(1.,1.); glVertex3f($r, $b, 0); glTexCoord2d(1.,1.); glVertex3f($r, $b, 0);
@ -1466,6 +1551,7 @@ sub _render_image {
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
} }
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub draw_active_object_annotations { sub draw_active_object_annotations {
# $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking. # $fakecolor is a boolean indicating, that the objects shall be rendered in a color coding the object index for picking.
@ -1579,6 +1665,37 @@ sub draw_active_object_annotations {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
} }
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub draw_legend {
my ($self) = @_;
if ($self->_legend_enabled)
{
my $tex_id = Slic3r::GUI::_3DScene::get_legend_texture_id;
if ($tex_id > 0)
{
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glLoadIdentity();
my $tex_w = Slic3r::GUI::_3DScene::get_legend_texture_width;
my $tex_h = Slic3r::GUI::_3DScene::get_legend_texture_height;
my ($cw, $ch) = $self->GetSizeWH;
my $l = (-0.5 * $cw) / $self->_zoom;
my $t = (0.5 * $ch) / $self->_zoom;
my $r = $l + $tex_w / $self->_zoom;
my $b = $t - $tex_h / $self->_zoom;
$self->_render_texture($tex_id, $l, $r, $b, $t);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
}
}
# ===================== ENRICO_GCODE_PREVIEW ==================================================
sub opengl_info sub opengl_info
{ {
my ($self, %params) = @_; my ($self, %params) = @_;

View File

@ -153,7 +153,16 @@ sub new {
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub { EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
my $preview = $self->{preview_notebook}->GetCurrentPage; my $preview = $self->{preview_notebook}->GetCurrentPage;
$self->{preview3D}->load_print(1) if ($preview == $self->{preview3D}); # ===================== ENRICO_GCODE_PREVIEW ==================================================
if ($preview == $self->{preview3D})
{
$self->{preview3D}->canvas->set_legend_enabled(1);
$self->{preview3D}->load_print(1);
} else {
$self->{preview3D}->canvas->set_legend_enabled(0);
}
# $self->{preview3D}->load_print(1) if ($preview == $self->{preview3D});
# ===================== ENRICO_GCODE_PREVIEW ==================================================
$preview->OnActivate if $preview->can('OnActivate'); $preview->OnActivate if $preview->can('OnActivate');
}); });

View File

@ -436,6 +436,16 @@ GCodeAnalyzer::PreviewData::Color::Color(float r, float g, float b, float a)
rgba[3] = a; rgba[3] = a;
} }
std::vector<unsigned char> GCodeAnalyzer::PreviewData::Color::as_bytes() const
{
std::vector<unsigned char> ret;
for (unsigned int i = 0; i < 4; ++i)
{
ret.push_back((unsigned char)(255.0f * rgba[i]));
}
return ret;
}
GCodeAnalyzer::PreviewData::Extrusion::Layer::Layer(float z, const ExtrusionPaths& paths) GCodeAnalyzer::PreviewData::Extrusion::Layer::Layer(float z, const ExtrusionPaths& paths)
: z(z) : z(z)
, paths(paths) , paths(paths)
@ -491,6 +501,11 @@ void GCodeAnalyzer::PreviewData::Range::set_from(const Range& other)
max = other.max; max = other.max;
} }
float GCodeAnalyzer::PreviewData::Range::step_size() const
{
return (max - min) / (float)Colors_Count;
}
const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::Range::get_color_at_max() const const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::Range::get_color_at_max() const
{ {
return colors[Colors_Count - 1]; return colors[Colors_Count - 1];
@ -498,12 +513,13 @@ const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::Range::get_
const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::Range::get_color_at(float value) const const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::Range::get_color_at(float value) const
{ {
return empty() ? get_color_at_max() : colors[clamp((unsigned int)0, Colors_Count - 1, (unsigned int)((value - min) / _step()))]; return empty() ? get_color_at_max() : colors[clamp((unsigned int)0, Colors_Count - 1, (unsigned int)((value - min) / step_size()))];
} }
float GCodeAnalyzer::PreviewData::Range::_step() const GCodeAnalyzer::PreviewData::LegendItem::LegendItem(const std::string& text, const GCodeAnalyzer::PreviewData::Color& color)
: text(text)
, color(color)
{ {
return (max - min) / (float)Colors_Count;
} }
const GCodeAnalyzer::PreviewData::Color GCodeAnalyzer::PreviewData::Extrusion::Default_Extrusion_Role_Colors[Num_Extrusion_Roles] = const GCodeAnalyzer::PreviewData::Color GCodeAnalyzer::PreviewData::Extrusion::Default_Extrusion_Role_Colors[Num_Extrusion_Roles] =
@ -523,6 +539,23 @@ const GCodeAnalyzer::PreviewData::Color GCodeAnalyzer::PreviewData::Extrusion::D
Color(0.0f, 0.0f, 0.0f, 1.0f) // erMixed Color(0.0f, 0.0f, 0.0f, 1.0f) // erMixed
}; };
const std::string GCodeAnalyzer::PreviewData::Extrusion::Default_Extrusion_Role_Names[Num_Extrusion_Roles]
{
"None",
"Perimeter",
"External perimeter",
"Overhang perimeter",
"Internal infill",
"Solid infill",
"Top solid infill",
"Bridge infill",
"Gap fill",
"Skirt",
"Support material",
"Support material interface",
"Mixed"
};
const GCodeAnalyzer::PreviewData::Extrusion::EViewType GCodeAnalyzer::PreviewData::Extrusion::Default_View_Type = GCodeAnalyzer::PreviewData::Extrusion::FeatureType; const GCodeAnalyzer::PreviewData::Extrusion::EViewType GCodeAnalyzer::PreviewData::Extrusion::Default_View_Type = GCodeAnalyzer::PreviewData::Extrusion::FeatureType;
void GCodeAnalyzer::PreviewData::Extrusion::set_default() void GCodeAnalyzer::PreviewData::Extrusion::set_default()
@ -534,6 +567,11 @@ void GCodeAnalyzer::PreviewData::Extrusion::set_default()
::memcpy((void*)ranges.width.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); ::memcpy((void*)ranges.width.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.feedrate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color)); ::memcpy((void*)ranges.feedrate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
{
role_names[i] = Default_Extrusion_Role_Names[i];
}
role_flags = 0; role_flags = 0;
for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i) for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
{ {
@ -628,6 +666,74 @@ const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::get_extrusi
return extrusion.ranges.feedrate.get_color_at(feedrate); return extrusion.ranges.feedrate.get_color_at(feedrate);
} }
std::string GCodeAnalyzer::PreviewData::get_legend_title() const
{
switch (extrusion.view_type)
{
case Extrusion::FeatureType:
return "Feature type";
case Extrusion::Height:
return "Height (mm)";
case Extrusion::Width:
return "Width (mm)";
case Extrusion::Feedrate:
return "Speed (mm/min)";
}
return "";
}
GCodeAnalyzer::PreviewData::LegendItemsList GCodeAnalyzer::PreviewData::get_legend_items() const
{
struct Helper
{
static void FillListFromRange(LegendItemsList& list, const Range& range, unsigned int decimals, float scale_factor)
{
list.reserve(Range::Colors_Count);
float step = range.step_size();
for (unsigned int i = 0; i < Range::Colors_Count; ++i)
{
char buf[32];
sprintf(buf, "%.*f/%.*f", decimals, scale_factor * (range.min + (float)i * step), decimals, scale_factor * (range.min + (float)(i + 1) * step));
list.emplace_back(buf, range.colors[i]);
}
}
};
LegendItemsList items;
switch (extrusion.view_type)
{
case Extrusion::FeatureType:
{
items.reserve(erMixed - erPerimeter + 1);
for (unsigned int i = (unsigned int)erPerimeter; i < (unsigned int)erMixed; ++i)
{
items.emplace_back(extrusion.role_names[i], extrusion.role_colors[i]);
}
break;
}
case Extrusion::Height:
{
Helper::FillListFromRange(items, extrusion.ranges.height, 3, 1.0f);
break;
}
case Extrusion::Width:
{
Helper::FillListFromRange(items, extrusion.ranges.width, 3, 1.0f);
break;
}
case Extrusion::Feedrate:
{
Helper::FillListFromRange(items, extrusion.ranges.feedrate, 0, 60.0f);
break;
}
}
return items;
}
GCodeAnalyzer::GCodeAnalyzer() GCodeAnalyzer::GCodeAnalyzer()
{ {
reset(); reset();

View File

@ -206,9 +206,9 @@ public:
ExtrusionRole extrusion_role; ExtrusionRole extrusion_role;
unsigned int extruder_id; unsigned int extruder_id;
double mm3_per_mm; double mm3_per_mm;
float width; float width; // mm
float height; float height; // mm
float feedrate; float feedrate; // mm/s
Metadata(); Metadata();
Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate); Metadata(ExtrusionRole extrusion_role, unsigned int extruder_id, double mm3_per_mm, float width, float height, float feedrate);
@ -264,6 +264,8 @@ public:
Color(); Color();
Color(float r, float g, float b, float a); Color(float r, float g, float b, float a);
std::vector<unsigned char> as_bytes() const;
static const Color Dummy; static const Color Dummy;
}; };
@ -282,14 +284,22 @@ public:
bool empty() const; bool empty() const;
void update_from(float value); void update_from(float value);
void set_from(const Range& other); void set_from(const Range& other);
float step_size() const;
const Color& get_color_at(float value) const; const Color& get_color_at(float value) const;
const Color& get_color_at_max() const; const Color& get_color_at_max() const;
private:
float _step() const;
}; };
struct LegendItem
{
std::string text;
Color color;
LegendItem(const std::string& text, const Color& color);
};
typedef std::vector<LegendItem> LegendItemsList;
struct Extrusion struct Extrusion
{ {
enum EViewType : unsigned char enum EViewType : unsigned char
@ -303,6 +313,7 @@ public:
static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1; static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1;
static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles]; static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles];
static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
static const EViewType Default_View_Type; static const EViewType Default_View_Type;
struct Ranges struct Ranges
@ -324,6 +335,7 @@ public:
EViewType view_type; EViewType view_type;
Color role_colors[Num_Extrusion_Roles]; Color role_colors[Num_Extrusion_Roles];
std::string role_names[Num_Extrusion_Roles];
Ranges ranges; Ranges ranges;
LayersList layers; LayersList layers;
unsigned int role_flags; unsigned int role_flags;
@ -411,6 +423,9 @@ public:
const Color& get_extrusion_height_color(float height) const; const Color& get_extrusion_height_color(float height) const;
const Color& get_extrusion_width_color(float width) const; const Color& get_extrusion_width_color(float width) const;
const Color& get_extrusion_feedrate_color(float feedrate) const; const Color& get_extrusion_feedrate_color(float feedrate) const;
std::string get_legend_title() const;
LegendItemsList get_legend_items() const;
}; };
private: private:

View File

@ -8,9 +8,11 @@
#include "../../libslic3r/Geometry.hpp" #include "../../libslic3r/Geometry.hpp"
#include "../../libslic3r/Print.hpp" #include "../../libslic3r/Print.hpp"
#include "../../libslic3r/Slicing.hpp" #include "../../libslic3r/Slicing.hpp"
//############################################################################################################
#if ENRICO_GCODE_PREVIEW #if ENRICO_GCODE_PREVIEW
#include "GCode/Analyzer.hpp" #include "GCode/Analyzer.hpp"
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -23,6 +25,15 @@
#include <tbb/parallel_for.h> #include <tbb/parallel_for.h>
#include <tbb/spin_mutex.h> #include <tbb/spin_mutex.h>
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
#include <wx/bitmap.h>
#include <wx/dcmemory.h>
#include <wx/image.h>
#include <wx/settings.h>
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
namespace Slic3r { namespace Slic3r {
void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
@ -1098,6 +1109,197 @@ void _3DScene::GCodePreviewData::reset()
} }
_3DScene::GCodePreviewData _3DScene::s_gcode_preview_data; _3DScene::GCodePreviewData _3DScene::s_gcode_preview_data;
_3DScene::LegendTexture _3DScene::s_legend_texture;
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;
_3DScene::LegendTexture::LegendTexture()
: m_tex_id(0)
, m_tex_width(0)
, m_tex_height(0)
{
}
_3DScene::LegendTexture::~LegendTexture()
{
_destroy_texture();
}
bool _3DScene::LegendTexture::generate_texture(const Print& print)
{
_destroy_texture();
// collects items to render
const std::string& title = print.gcode_preview.get_legend_title();
const GCodeAnalyzer::PreviewData::LegendItemsList& items = print.gcode_preview.get_legend_items();
unsigned int items_count = (unsigned int)items.size();
if (items_count == 0)
// nothing to render, return
return false;
wxMemoryDC memDC;
// select default font
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// calculates texture size
wxCoord w, h;
memDC.GetTextExtent(title, &w, &h);
unsigned int title_width = (unsigned int)w;
unsigned int title_height = (unsigned int)h;
unsigned int max_text_width = 0;
unsigned int max_text_height = 0;
for (const GCodeAnalyzer::PreviewData::LegendItem& item : items)
{
memDC.GetTextExtent(item.text, &w, &h);
max_text_width = std::max(max_text_width, (unsigned int)w);
max_text_height = std::max(max_text_height, (unsigned int)h);
}
m_tex_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
m_tex_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
if (items_count > 1)
m_tex_height += (items_count - 1) * Px_Square_Contour;
// generates bitmap
wxBitmap bitmap(m_tex_width, m_tex_height);
#if defined(__APPLE__) || defined(_MSC_VER)
bitmap.UseAlpha();
#endif
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
memDC.Clear();
memDC.SetTextForeground(*wxWHITE);
// draw title
unsigned int title_x = Px_Border;
unsigned int title_y = Px_Border;
memDC.DrawText(title, title_x, title_y);
// draw icons contours as background
unsigned int squares_contour_x = Px_Border;
unsigned int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
unsigned int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
unsigned int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
if (items_count > 1)
squares_contour_height += (items_count - 1) * Px_Square_Contour;
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
wxPen pen(color);
wxBrush brush(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
// draw items (colored icon + text)
unsigned int icon_x = squares_contour_x + Px_Square_Contour;
unsigned int icon_x_inner = icon_x + 1;
unsigned int icon_y = squares_contour_y + Px_Square_Contour;
unsigned int icon_y_step = Px_Square + Px_Square_Contour;
unsigned int text_x = icon_x + Px_Square + Px_Text_Offset;
unsigned int text_y_offset = (Px_Square - max_text_height) / 2;
unsigned int px_inner_square = Px_Square - 2;
for (const GCodeAnalyzer::PreviewData::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(item.text, text_x, icon_y + text_y_offset);
// update y
icon_y += icon_y_step;
}
memDC.SelectObject(wxNullBitmap);
return _create_texture(print, bitmap);
}
unsigned int _3DScene::LegendTexture::get_texture_id() const
{
return m_tex_id;
}
unsigned int _3DScene::LegendTexture::get_texture_width() const
{
return m_tex_width;
}
unsigned int _3DScene::LegendTexture::get_texture_height() const
{
return m_tex_height;
}
bool _3DScene::LegendTexture::_create_texture(const Print& print, const wxBitmap& bitmap)
{
if ((m_tex_width == 0) || (m_tex_height == 0))
return false;
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
std::vector<unsigned char> buffer(4 * m_tex_width * m_tex_height, 0);
for (unsigned int h = 0; h < m_tex_height; ++h)
{
unsigned int hh = h * m_tex_width;
for (unsigned int w = 0; w < m_tex_width; ++w)
{
unsigned char* px_ptr = buffer.data() + 4 * (hh + 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
::glGenTextures(1, &m_tex_id);
::glBindTexture(GL_TEXTURE_2D, m_tex_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)m_tex_width, (GLsizei)m_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)buffer.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::LegendTexture::_destroy_texture()
{
if (m_tex_id > 0)
{
::glDeleteTextures(1, &m_tex_id);
m_tex_id = 0;
}
}
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################
@ -1145,10 +1347,27 @@ void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volume
_load_gcode_travel_paths(*print, *volumes, use_VBOs); _load_gcode_travel_paths(*print, *volumes, use_VBOs);
_load_gcode_retractions(*print, *volumes, use_VBOs); _load_gcode_retractions(*print, *volumes, use_VBOs);
_load_gcode_unretractions(*print, *volumes, use_VBOs); _load_gcode_unretractions(*print, *volumes, use_VBOs);
_generate_legend_texture(*print);
} }
_update_gcode_volumes_visibility(*print, *volumes); _update_gcode_volumes_visibility(*print, *volumes);
} }
unsigned int _3DScene::get_legend_texture_id()
{
return s_legend_texture.get_texture_id();
}
unsigned int _3DScene::get_legend_texture_width()
{
return s_legend_texture.get_texture_width();
}
unsigned int _3DScene::get_legend_texture_height()
{
return s_legend_texture.get_texture_height();
}
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################
@ -1847,6 +2066,11 @@ void _3DScene::_update_gcode_volumes_visibility(const Print& print, GLVolumeColl
} }
} }
} }
void _3DScene::_generate_legend_texture(const Print& print)
{
s_legend_texture.generate_texture(print);
}
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################

View File

@ -7,6 +7,12 @@
#include "../../libslic3r/TriangleMesh.hpp" #include "../../libslic3r/TriangleMesh.hpp"
#include "../../libslic3r/Utils.hpp" #include "../../libslic3r/Utils.hpp"
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
class wxBitmap;
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
namespace Slic3r { namespace Slic3r {
class Print; class Print;
@ -389,6 +395,38 @@ class _3DScene
}; };
static GCodePreviewData s_gcode_preview_data; static GCodePreviewData s_gcode_preview_data;
class LegendTexture
{
static const unsigned int Px_Title_Offset = 5;
static const unsigned int Px_Text_Offset = 5;
static const unsigned int Px_Square = 20;
static const unsigned int Px_Square_Contour = 1;
static const unsigned int Px_Border = Px_Square / 2;
static const unsigned char Squares_Border_Color[3];
static const unsigned char Background_Color[3];
static const unsigned char Opacity;
unsigned int m_tex_id;
unsigned int m_tex_width;
unsigned int m_tex_height;
public:
LegendTexture();
~LegendTexture();
bool generate_texture(const Print& print);
unsigned int get_texture_id() const;
unsigned int get_texture_width() const;
unsigned int get_texture_height() const;
private:
bool _create_texture(const Print& print, const wxBitmap& bitmap);
void _destroy_texture();
};
static LegendTexture s_legend_texture;
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################
public: public:
@ -397,6 +435,9 @@ public:
//############################################################################################################ //############################################################################################################
#if ENRICO_GCODE_PREVIEW #if ENRICO_GCODE_PREVIEW
static void load_gcode_preview(const Print* print, GLVolumeCollection* volumes, bool use_VBOs); static void load_gcode_preview(const Print* print, GLVolumeCollection* volumes, bool use_VBOs);
static unsigned int get_legend_texture_id();
static unsigned int get_legend_texture_width();
static unsigned int get_legend_texture_height();
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################
@ -432,6 +473,8 @@ private:
static void _load_gcode_unretractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); static void _load_gcode_unretractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
// sets gcode geometry visibility according to user selection // sets gcode geometry visibility according to user selection
static void _update_gcode_volumes_visibility(const Print& print, GLVolumeCollection& volumes); static void _update_gcode_volumes_visibility(const Print& print, GLVolumeCollection& volumes);
// generates the legend texture in dependence of the current shown view type
static void _generate_legend_texture(const Print& print);
#endif // ENRICO_GCODE_PREVIEW #endif // ENRICO_GCODE_PREVIEW
//############################################################################################################ //############################################################################################################
}; };

View File

@ -141,6 +141,27 @@ _glew_init()
CODE: CODE:
_3DScene::_glew_init(); _3DScene::_glew_init();
unsigned int
get_legend_texture_id()
CODE:
RETVAL = _3DScene::get_legend_texture_id();
OUTPUT:
RETVAL
unsigned int
get_legend_texture_width()
CODE:
RETVAL = _3DScene::get_legend_texture_width();
OUTPUT:
RETVAL
unsigned int
get_legend_texture_height()
CODE:
RETVAL = _3DScene::get_legend_texture_height();
OUTPUT:
RETVAL
void void
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs) _load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
Print *print; Print *print;