Merge branch 'scene_manipulators' of https://github.com/prusa3d/Slic3r

This commit is contained in:
Enrico Turri 2018-07-20 10:31:53 +02:00
commit c1d1721dae
16 changed files with 498 additions and 487 deletions

View File

@ -103,6 +103,10 @@ public:
bool contains(const BoundingBox3Base<PointClass>& other) const {
return contains(other.min) && contains(other.max);
}
bool intersects(const BoundingBox3Base<PointClass>& other) const {
return (this->min.x < other.max.x) && (this->max.x > other.min.x) && (this->min.y < other.max.y) && (this->max.y > other.min.y) && (this->min.z < other.max.z) && (this->max.z > other.min.z);
}
};
class BoundingBox : public BoundingBoxBase<Point>

View File

@ -785,9 +785,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
// Order objects using a nearest neighbor search.
std::vector<size_t> object_indices;
Points object_reference_points;
for (PrintObject *object : print.objects)
PrintObjectPtrs printable_objects = print.get_printable_objects();
for (PrintObject *object : printable_objects)
object_reference_points.push_back(object->_shifted_copies.front());
Slic3r::Geometry::chained_path(object_reference_points, object_indices);
Slic3r::Geometry::chained_path(object_reference_points, object_indices);
// Sort layers by Z.
// All extrusion moves with the same top layer height are extruded uninterrupted.
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
@ -799,7 +800,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
// Verify, whether the print overaps the priming extrusions.
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
for (const PrintObject *print_object : print.objects)
for (const PrintObject *print_object : printable_objects)
bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));

View File

@ -67,11 +67,13 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
m_print_config_ptr = &print.config;
PrintObjectPtrs objects = print.get_printable_objects();
// Initialize the print layers for all objects and all layers.
coordf_t object_bottom_z = 0.;
{
std::vector<coordf_t> zs;
for (auto object : print.objects) {
for (auto object : objects) {
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
for (auto layer : object->layers)
zs.emplace_back(layer->print_z);
@ -84,7 +86,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
}
// Collect extruders reuqired to print the layers.
for (auto object : print.objects)
for (auto object : objects)
this->collect_extruders(*object);
// Reorder the extruders to minimize tool switches.

View File

@ -1235,6 +1235,59 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
return;
}
void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume)
{
for (ModelVolume* vol : this->volumes)
{
if (!vol->modifier)
{
for (ModelInstance* inst : this->instances)
{
BoundingBoxf3 bb;
double c = cos(inst->rotation);
double s = sin(inst->rotation);
for (int f = 0; f < vol->mesh.stl.stats.number_of_facets; ++f)
{
const stl_facet& facet = vol->mesh.stl.facet_start[f];
for (int i = 0; i < 3; ++i)
{
// original point
const stl_vertex& v = facet.vertex[i];
Pointf3 p((double)v.x, (double)v.y, (double)v.z);
// scale
p.x *= inst->scaling_factor;
p.y *= inst->scaling_factor;
p.z *= inst->scaling_factor;
// rotate Z
double x = p.x;
double y = p.y;
p.x = c * x - s * y;
p.y = s * x + c * y;
// translate
p.x += inst->offset.x;
p.y += inst->offset.y;
bb.merge(p);
}
}
if (print_volume.contains(bb))
inst->print_volume_state = ModelInstance::PVS_Inside;
else if (print_volume.intersects(bb))
inst->print_volume_state = ModelInstance::PVS_Partly_Outside;
else
inst->print_volume_state = ModelInstance::PVS_Fully_Outside;
}
}
}
}
void ModelObject::print_info() const
{
using namespace std;

View File

@ -132,6 +132,8 @@ public:
void cut(coordf_t z, Model* model) const;
void split(ModelObjectPtrs* new_objects);
void check_instances_print_volume_state(const BoundingBoxf3& print_volume);
// Print object statistics to console.
void print_info() const;
@ -197,12 +199,24 @@ private:
// Knows the affine transformation of an object.
class ModelInstance
{
friend class ModelObject;
public:
enum EPrintVolumeState : unsigned char
{
PVS_Inside,
PVS_Partly_Outside,
PVS_Fully_Outside,
Num_BedStates
};
friend class ModelObject;
double rotation; // Rotation around the Z axis, in radians around mesh center point
double scaling_factor;
Pointf offset; // in unscaled coordinates
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
EPrintVolumeState print_volume_state;
ModelObject* get_object() const { return this->object; }
// To be called on an external mesh
@ -214,13 +228,15 @@ public:
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
void transform_polygon(Polygon* polygon) const;
bool is_printable() const { return print_volume_state == PVS_Inside; }
private:
// Parent object, owning this instance.
ModelObject* object;
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object) {}
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), print_volume_state(PVS_Inside) {}
ModelInstance(ModelObject *object, const ModelInstance &other) :
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object) {}
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), print_volume_state(PVS_Inside) {}
};

View File

@ -71,6 +71,13 @@ bool Print::reload_model_instances()
return invalidated;
}
PrintObjectPtrs Print::get_printable_objects() const
{
PrintObjectPtrs printable_objects(this->objects);
printable_objects.erase(std::remove_if(printable_objects.begin(), printable_objects.end(), [](PrintObject* o) { return !o->is_printable(); }), printable_objects.end());
return printable_objects;
}
PrintRegion* Print::add_region()
{
regions.push_back(new PrintRegion(this));
@ -534,11 +541,17 @@ std::string Print::validate() const
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height));
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
print_volume.min.z = -1e10;
unsigned int printable_count = 0;
for (PrintObject *po : this->objects) {
if (!print_volume.contains(po->model_object()->tight_bounding_box(false)))
return L("Some objects are outside of the print volume.");
po->model_object()->check_instances_print_volume_state(print_volume);
po->reload_model_instances();
if (po->is_printable())
++printable_count;
}
if (printable_count == 0)
return L("All objects are outside of the print volume.");
if (this->config.complete_objects) {
// Check horizontal clearance.
{
@ -858,7 +871,8 @@ void Print::_make_skirt()
// prepended to the first 'n' layers (with 'n' = skirt_height).
// $skirt_height_z in this case is the highest possible skirt height for safety.
coordf_t skirt_height_z = 0.;
for (const PrintObject *object : this->objects) {
PrintObjectPtrs printable_objects = get_printable_objects();
for (const PrintObject *object : printable_objects) {
size_t skirt_layers = this->has_infinite_skirt() ?
object->layer_count() :
std::min(size_t(this->config.skirt_height.value), object->layer_count());
@ -867,7 +881,7 @@ void Print::_make_skirt()
// Collect points from all layers contained in skirt height.
Points points;
for (const PrintObject *object : this->objects) {
for (const PrintObject *object : printable_objects) {
Points object_points;
// Get object layers up to skirt_height_z.
for (const Layer *layer : object->layers) {
@ -980,7 +994,8 @@ void Print::_make_brim()
// Brim is only printed on first layer and uses perimeter extruder.
Flow flow = this->brim_flow();
Polygons islands;
for (PrintObject *object : this->objects) {
PrintObjectPtrs printable_objects = get_printable_objects();
for (PrintObject *object : printable_objects) {
Polygons object_islands;
for (ExPolygon &expoly : object->layers.front()->slices.expolygons)
object_islands.push_back(expoly.contour);

View File

@ -209,6 +209,8 @@ public:
void combine_infill();
void _generate_support_material();
bool is_printable() const { return !this->_shifted_copies.empty(); }
private:
Print* _print;
ModelObject* _model_object;
@ -257,6 +259,8 @@ public:
void reload_object(size_t idx);
bool reload_model_instances();
PrintObjectPtrs get_printable_objects() const;
// methods for handling regions
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }

View File

@ -102,7 +102,10 @@ bool PrintObject::reload_model_instances()
Points copies;
copies.reserve(this->_model_object->instances.size());
for (const ModelInstance *mi : this->_model_object->instances)
copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y));
{
if (mi->is_printable())
copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y));
}
return this->set_copies(copies);
}
@ -291,6 +294,9 @@ bool PrintObject::has_support_material() const
void PrintObject::_prepare_infill()
{
if (!this->is_printable())
return;
// This will assign a type (top/bottom/internal) to $layerm->slices.
// Then the classifcation of $layerm->slices is transfered onto
// the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
@ -1442,6 +1448,9 @@ void PrintObject::_simplify_slices(double distance)
void PrintObject::_make_perimeters()
{
if (!this->is_printable())
return;
if (this->state.is_done(posPerimeters)) return;
this->state.set_started(posPerimeters);
@ -1550,6 +1559,9 @@ void PrintObject::_make_perimeters()
void PrintObject::_infill()
{
if (!this->is_printable())
return;
if (this->state.is_done(posInfill)) return;
this->state.set_started(posInfill);
@ -1954,6 +1966,9 @@ void PrintObject::combine_infill()
void PrintObject::_generate_support_material()
{
if (!this->is_printable())
return;
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
support_material.generate(*this);
}

View File

@ -22,11 +22,6 @@
#include <tbb/parallel_for.h>
#include <tbb/spin_mutex.h>
#include <wx/bitmap.h>
#include <wx/dcmemory.h>
#include <wx/image.h>
#include <wx/settings.h>
#include <Eigen/Dense>
#include "GUI.hpp"
@ -540,8 +535,8 @@ double GLVolume::layer_height_texture_z_to_row_id() const
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
{
GLTexture *tex = this->layer_height_texture.get();
if (tex == nullptr)
LayersTexture *tex = this->layer_height_texture.get();
if (tex == nullptr)
// No layer_height_texture is assigned to this GLVolume, therefore the layer height texture cannot be filled.
return;
@ -588,7 +583,7 @@ std::vector<int> GLVolumeCollection::load_object(
};
// Object will have a single common layer height texture for all volumes.
std::shared_ptr<GLTexture> layer_height_texture = std::make_shared<GLTexture>();
std::shared_ptr<LayersTexture> layer_height_texture = std::make_shared<LayersTexture>();
std::vector<int> volumes_idx;
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++ volume_idx) {
@ -743,7 +738,7 @@ void GLVolumeCollection::render_legacy() const
glDisable(GL_BLEND);
}
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state)
{
if (config == nullptr)
return false;
@ -757,18 +752,31 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
bool contained = true;
ModelInstance::EPrintVolumeState state = ModelInstance::PVS_Inside;
bool all_contained = true;
for (GLVolume* volume : this->volumes)
{
if ((volume != nullptr) && !volume->is_modifier)
{
bool state = print_volume.contains(volume->transformed_bounding_box());
contained &= state;
volume->is_outside = !state;
const BoundingBoxf3& bb = volume->transformed_bounding_box();
bool contained = print_volume.contains(bb);
all_contained &= contained;
volume->is_outside = !contained;
if ((state == ModelInstance::PVS_Inside) && volume->is_outside)
state = ModelInstance::PVS_Fully_Outside;
if ((state == ModelInstance::PVS_Fully_Outside) && volume->is_outside && print_volume.intersects(bb))
state = ModelInstance::PVS_Partly_Outside;
}
}
return contained;
if (out_state != nullptr)
*out_state = state;
return all_contained;
}
void GLVolumeCollection::reset_outside_state()
@ -1576,246 +1584,8 @@ void _3DScene::point3_to_verts(const Point3& point, double width, double height,
thick_point_to_verts(point, width, height, volume);
}
_3DScene::LegendTexture _3DScene::s_legend_texture;
_3DScene::WarningTexture _3DScene::s_warning_texture;
GUI::GLCanvas3DManager _3DScene::s_canvas_mgr;
unsigned int _3DScene::TextureBase::finalize()
{
if ((m_tex_id == 0) && !m_data.empty()) {
// sends buffer to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_tex_id);
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_tex_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_tex_width, (GLsizei)m_tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)m_data.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
::glBindTexture(GL_TEXTURE_2D, 0);
m_data.clear();
}
return (m_tex_width > 0 && m_tex_height > 0) ? m_tex_id : 0;
}
void _3DScene::TextureBase::_destroy_texture()
{
if (m_tex_id > 0)
{
::glDeleteTextures(1, &m_tex_id);
m_tex_id = 0;
m_tex_height = 0;
m_tex_width = 0;
}
m_data.clear();
}
const unsigned char _3DScene::WarningTexture::Background_Color[3] = { 9, 91, 134 };
const unsigned char _3DScene::WarningTexture::Opacity = 255;
// Generate a texture data, but don't load it into the GPU yet, as the GPU context may not yet be valid.
bool _3DScene::WarningTexture::generate(const std::string& msg)
{
// Mark the texture as released, but don't release the texture from the GPU yet.
m_tex_width = m_tex_height = 0;
m_data.clear();
if (msg.empty())
return false;
wxMemoryDC memDC;
// select default font
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// calculates texture size
wxCoord w, h;
memDC.GetTextExtent(msg, &w, &h);
m_tex_width = (unsigned int)w;
m_tex_height = (unsigned int)h;
// generates bitmap
wxBitmap bitmap(m_tex_width, m_tex_height);
#if defined(__APPLE__) || defined(_MSC_VER)
bitmap.UseAlpha();
#endif
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
memDC.Clear();
memDC.SetTextForeground(*wxWHITE);
// draw message
memDC.DrawText(msg, 0, 0);
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
{
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
m_data.assign(4 * m_tex_width * m_tex_height, 0);
for (unsigned int h = 0; h < m_tex_height; ++h)
{
unsigned int hh = h * m_tex_width;
unsigned char* px_ptr = m_data.data() + 4 * hh;
for (unsigned int w = 0; w < m_tex_width; ++w)
{
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
}
}
}
return true;
}
const unsigned char _3DScene::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
const unsigned char _3DScene::LegendTexture::Background_Color[3] = { 9, 91, 134 };
const unsigned char _3DScene::LegendTexture::Opacity = 255;
// Generate a texture data, but don't load it into the GPU yet, as the GPU context may not yet be valid.
bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
// Mark the texture as released, but don't release the texture from the GPU yet.
m_tex_width = m_tex_height = 0;
m_data.clear();
// collects items to render
auto title = _(preview_data.get_legend_title());
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
unsigned int items_count = (unsigned int)items.size();
if (items_count == 0)
// nothing to render, return
return false;
wxMemoryDC memDC;
// select default font
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// calculates texture size
wxCoord w, h;
memDC.GetTextExtent(title, &w, &h);
unsigned int title_width = (unsigned int)w;
unsigned int title_height = (unsigned int)h;
unsigned int max_text_width = 0;
unsigned int max_text_height = 0;
for (const GCodePreviewData::LegendItem& item : items)
{
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
max_text_width = std::max(max_text_width, (unsigned int)w);
max_text_height = std::max(max_text_height, (unsigned int)h);
}
m_tex_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
m_tex_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
if (items_count > 1)
m_tex_height += (items_count - 1) * Px_Square_Contour;
// generates bitmap
wxBitmap bitmap(m_tex_width, m_tex_height);
#if defined(__APPLE__) || defined(_MSC_VER)
bitmap.UseAlpha();
#endif
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
memDC.Clear();
memDC.SetTextForeground(*wxWHITE);
// draw title
unsigned int title_x = Px_Border;
unsigned int title_y = Px_Border;
memDC.DrawText(title, title_x, title_y);
// draw icons contours as background
unsigned int squares_contour_x = Px_Border;
unsigned int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
unsigned int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
unsigned int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
if (items_count > 1)
squares_contour_height += (items_count - 1) * Px_Square_Contour;
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
wxPen pen(color);
wxBrush brush(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
// draw items (colored icon + text)
unsigned int icon_x = squares_contour_x + Px_Square_Contour;
unsigned int icon_x_inner = icon_x + 1;
unsigned int icon_y = squares_contour_y + Px_Square_Contour;
unsigned int icon_y_step = Px_Square + Px_Square_Contour;
unsigned int text_x = icon_x + Px_Square + Px_Text_Offset;
unsigned int text_y_offset = (Px_Square - max_text_height) / 2;
unsigned int px_inner_square = Px_Square - 2;
for (const GCodePreviewData::LegendItem& item : items)
{
// draw darker icon perimeter
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
dark_hsv.value *= 0.75;
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
pen.SetColour(color);
brush.SetColour(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
// draw icon interior
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
pen.SetColour(color);
brush.SetColour(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
// draw text
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
// update y
icon_y += icon_y_step;
}
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
{
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
m_data.assign(4 * m_tex_width * m_tex_height, 0);
for (unsigned int h = 0; h < m_tex_height; ++h)
{
unsigned int hh = h * m_tex_width;
unsigned char* px_ptr = m_data.data() + 4 * hh;
for (unsigned int w = 0; w < m_tex_width; ++w)
{
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
}
}
}
return true;
}
void _3DScene::init_gl()
{
s_canvas_mgr.init_gl();
@ -2218,54 +1988,9 @@ void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* pr
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
}
void _3DScene::generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
s_legend_texture.generate(preview_data, tool_colors);
}
unsigned int _3DScene::get_legend_texture_width()
{
return s_legend_texture.get_texture_width();
}
unsigned int _3DScene::get_legend_texture_height()
{
return s_legend_texture.get_texture_height();
}
void _3DScene::reset_legend_texture()
{
s_legend_texture.reset_texture();
}
unsigned int _3DScene::finalize_legend_texture()
{
return s_legend_texture.finalize();
}
unsigned int _3DScene::get_warning_texture_width()
{
return s_warning_texture.get_texture_width();
}
unsigned int _3DScene::get_warning_texture_height()
{
return s_warning_texture.get_texture_height();
}
void _3DScene::generate_warning_texture(const std::string& msg)
{
s_warning_texture.generate(msg);
}
void _3DScene::reset_warning_texture()
{
s_warning_texture.reset_texture();
}
unsigned int _3DScene::finalize_warning_texture()
{
return s_warning_texture.finalize();
s_canvas_mgr.reset_legend_texture();
}
} // namespace Slic3r

View File

@ -6,6 +6,7 @@
#include "../../libslic3r/Line.hpp"
#include "../../libslic3r/TriangleMesh.hpp"
#include "../../libslic3r/Utils.hpp"
#include "../../libslic3r/Model.hpp"
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
class wxBitmap;
@ -199,10 +200,10 @@ private:
}
};
class GLTexture
class LayersTexture
{
public:
GLTexture() : width(0), height(0), levels(0), cells(0) {}
LayersTexture() : width(0), height(0), levels(0), cells(0) {}
// Texture data
std::vector<char> data;
@ -341,7 +342,7 @@ public:
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
/************************************************ Layer height texture ****************************************************/
std::shared_ptr<GLTexture> layer_height_texture;
std::shared_ptr<LayersTexture> layer_height_texture;
// Data to render this volume using the layer height texture
LayerHeightTextureData layer_height_texture_data;
@ -422,7 +423,9 @@ public:
print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z;
}
bool check_outside_state(const DynamicPrintConfig* config);
// returns true if all the volumes are completely contained in the print volume
// returns the containment state in the given out_state, if non-null
bool check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state);
void reset_outside_state();
void update_colors_by_extruder(const DynamicPrintConfig* config);
@ -437,65 +440,6 @@ private:
class _3DScene
{
class TextureBase
{
protected:
unsigned int m_tex_id;
unsigned int m_tex_width;
unsigned int m_tex_height;
// generate() fills in m_data with the pixels, while finalize() moves the data to the GPU before rendering.
std::vector<unsigned char> m_data;
public:
TextureBase() : m_tex_id(0), m_tex_width(0), m_tex_height(0) {}
virtual ~TextureBase() { _destroy_texture(); }
// If not loaded, load the texture data into the GPU. Return a texture ID or 0 if the texture has zero size.
unsigned int finalize();
unsigned int get_texture_id() const { return m_tex_id; }
unsigned int get_texture_width() const { return m_tex_width; }
unsigned int get_texture_height() const { return m_tex_height; }
void reset_texture() { _destroy_texture(); }
private:
void _destroy_texture();
};
class WarningTexture : public TextureBase
{
static const unsigned char Background_Color[3];
static const unsigned char Opacity;
public:
WarningTexture() : TextureBase() {}
// Generate a texture data, but don't load it into the GPU yet, as the glcontext may not be valid yet.
bool generate(const std::string& msg);
};
class LegendTexture : public TextureBase
{
static const unsigned int Px_Title_Offset = 5;
static const unsigned int Px_Text_Offset = 5;
static const unsigned int Px_Square = 20;
static const unsigned int Px_Square_Contour = 1;
static const unsigned int Px_Border = Px_Square / 2;
static const unsigned char Squares_Border_Color[3];
static const unsigned char Background_Color[3];
static const unsigned char Opacity;
public:
LegendTexture() : TextureBase() {}
// Generate a texture data, but don't load it into the GPU yet, as the glcontext may not be valid yet.
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
};
static LegendTexture s_legend_texture;
static WarningTexture s_warning_texture;
static GUI::GLCanvas3DManager s_canvas_mgr;
public:
@ -597,21 +541,7 @@ public:
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
// generates the legend texture in dependence of the current shown view type
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
static unsigned int get_legend_texture_width();
static unsigned int get_legend_texture_height();
static void reset_legend_texture();
static unsigned int finalize_legend_texture();
static unsigned int get_warning_texture_width();
static unsigned int get_warning_texture_height();
// generates a warning texture containing the given message
static void generate_warning_texture(const std::string& msg);
static void reset_warning_texture();
static unsigned int finalize_warning_texture();
static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);

View File

@ -15,6 +15,10 @@
#include <wx/glcanvas.h>
#include <wx/timer.h>
#include <wx/bitmap.h>
#include <wx/dcmemory.h>
#include <wx/image.h>
#include <wx/settings.h>
#include <tbb/parallel_for.h>
#include <tbb/spin_mutex.h>
@ -1381,7 +1385,8 @@ void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& b
::glDisable(GL_DEPTH_TEST);
_render_current_gizmo(box);
if (box.radius() > 0.0)
_render_current_gizmo(box);
::glPushMatrix();
::glLoadIdentity();
@ -1456,6 +1461,224 @@ float GLCanvas3D::Gizmos::_get_total_overlay_height() const
return height;
}
const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 9, 91, 134 };
const unsigned char GLCanvas3D::WarningTexture::Opacity = 255;
bool GLCanvas3D::WarningTexture::generate(const std::string& msg)
{
reset();
if (msg.empty())
return false;
wxMemoryDC memDC;
// select default font
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// calculates texture size
wxCoord w, h;
memDC.GetTextExtent(msg, &w, &h);
m_width = (int)w;
m_height = (int)h;
// generates bitmap
wxBitmap bitmap(m_width, m_height);
#if defined(__APPLE__) || defined(_MSC_VER)
bitmap.UseAlpha();
#endif
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
memDC.Clear();
memDC.SetTextForeground(*wxWHITE);
// draw message
memDC.DrawText(msg, 0, 0);
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
for (int h = 0; h < m_height; ++h)
{
int hh = h * m_width;
unsigned char* px_ptr = data.data() + 4 * hh;
for (int w = 0; w < m_width; ++w)
{
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
}
}
// sends buffer to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
::glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
const unsigned char GLCanvas3D::LegendTexture::Squares_Border_Color[3] = { 64, 64, 64 };
const unsigned char GLCanvas3D::LegendTexture::Background_Color[3] = { 9, 91, 134 };
const unsigned char GLCanvas3D::LegendTexture::Opacity = 255;
bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
reset();
// collects items to render
auto title = _(preview_data.get_legend_title());
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
unsigned int items_count = (unsigned int)items.size();
if (items_count == 0)
// nothing to render, return
return false;
wxMemoryDC memDC;
// select default font
memDC.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
// calculates texture size
wxCoord w, h;
memDC.GetTextExtent(title, &w, &h);
int title_width = (int)w;
int title_height = (int)h;
int max_text_width = 0;
int max_text_height = 0;
for (const GCodePreviewData::LegendItem& item : items)
{
memDC.GetTextExtent(GUI::from_u8(item.text), &w, &h);
max_text_width = std::max(max_text_width, (int)w);
max_text_height = std::max(max_text_height, (int)h);
}
m_width = std::max(2 * Px_Border + title_width, 2 * (Px_Border + Px_Square_Contour) + Px_Square + Px_Text_Offset + max_text_width);
m_height = 2 * (Px_Border + Px_Square_Contour) + title_height + Px_Title_Offset + items_count * Px_Square;
if (items_count > 1)
m_height += (items_count - 1) * Px_Square_Contour;
// generates bitmap
wxBitmap bitmap(m_width, m_height);
#if defined(__APPLE__) || defined(_MSC_VER)
bitmap.UseAlpha();
#endif
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
memDC.Clear();
memDC.SetTextForeground(*wxWHITE);
// draw title
int title_x = Px_Border;
int title_y = Px_Border;
memDC.DrawText(title, title_x, title_y);
// draw icons contours as background
int squares_contour_x = Px_Border;
int squares_contour_y = Px_Border + title_height + Px_Title_Offset;
int squares_contour_width = Px_Square + 2 * Px_Square_Contour;
int squares_contour_height = items_count * Px_Square + 2 * Px_Square_Contour;
if (items_count > 1)
squares_contour_height += (items_count - 1) * Px_Square_Contour;
wxColour color(Squares_Border_Color[0], Squares_Border_Color[1], Squares_Border_Color[2]);
wxPen pen(color);
wxBrush brush(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
// draw items (colored icon + text)
int icon_x = squares_contour_x + Px_Square_Contour;
int icon_x_inner = icon_x + 1;
int icon_y = squares_contour_y + Px_Square_Contour;
int icon_y_step = Px_Square + Px_Square_Contour;
int text_x = icon_x + Px_Square + Px_Text_Offset;
int text_y_offset = (Px_Square - max_text_height) / 2;
int px_inner_square = Px_Square - 2;
for (const GCodePreviewData::LegendItem& item : items)
{
// draw darker icon perimeter
const std::vector<unsigned char>& item_color_bytes = item.color.as_bytes();
wxImage::HSVValue dark_hsv = wxImage::RGBtoHSV(wxImage::RGBValue(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2]));
dark_hsv.value *= 0.75;
wxImage::RGBValue dark_rgb = wxImage::HSVtoRGB(dark_hsv);
color.Set(dark_rgb.red, dark_rgb.green, dark_rgb.blue, item_color_bytes[3]);
pen.SetColour(color);
brush.SetColour(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(icon_x, icon_y, Px_Square, Px_Square));
// draw icon interior
color.Set(item_color_bytes[0], item_color_bytes[1], item_color_bytes[2], item_color_bytes[3]);
pen.SetColour(color);
brush.SetColour(color);
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
// draw text
memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
// update y
icon_y += icon_y_step;
}
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
for (int h = 0; h < m_height; ++h)
{
int hh = h * m_width;
unsigned char* px_ptr = data.data() + 4 * hh;
for (int w = 0; w < m_width; ++w)
{
*px_ptr++ = image.GetRed(w, h);
*px_ptr++ = image.GetGreen(w, h);
*px_ptr++ = image.GetBlue(w, h);
*px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
}
}
// sends buffer to gpu
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
::glGenTextures(1, &m_id);
::glBindTexture(GL_TEXTURE_2D, (GLuint)m_id);
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data());
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
::glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
{
GizmosMap::const_iterator it = m_gizmos.find(m_current);
@ -1657,7 +1880,7 @@ void GLCanvas3D::update_volumes_selection(const std::vector<int>& selections)
bool GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
{
return m_volumes.check_outside_state(config);
return m_volumes.check_outside_state(config, nullptr);
}
bool GLCanvas3D::move_volume_up(unsigned int id)
@ -1905,7 +2128,7 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
void GLCanvas3D::update_gizmos_data()
{
if (!m_gizmos.is_running())
if (!m_gizmos.is_enabled())
return;
int id = _get_first_selected_object_id();
@ -1917,26 +2140,16 @@ void GLCanvas3D::update_gizmos_data()
ModelInstance* model_instance = model_object->instances[0];
if (model_instance != nullptr)
{
switch (m_gizmos.get_current_type())
{
case Gizmos::Scale:
{
m_gizmos.set_scale(model_instance->scaling_factor);
break;
}
case Gizmos::Rotate:
{
m_gizmos.set_angle_z(model_instance->rotation);
break;
}
default:
{
break;
}
}
m_gizmos.set_scale(model_instance->scaling_factor);
m_gizmos.set_angle_z(model_instance->rotation);
}
}
}
else
{
m_gizmos.set_scale(1.0f);
m_gizmos.set_angle_z(0.0f);
}
}
void GLCanvas3D::render()
@ -2051,8 +2264,12 @@ void GLCanvas3D::reload_scene(bool force)
m_objects_volumes_idxs.push_back(load_object(*m_model, obj_idx));
}
// 1st call to reset if no objects left
update_gizmos_data();
update_volumes_selection(m_objects_selections);
// 2nd call to restore if something selected
if (!m_objects_selections.empty())
update_gizmos_data();
if (m_config->has("nozzle_diameter"))
{
@ -2082,25 +2299,28 @@ void GLCanvas3D::reload_scene(bool force)
// checks for geometry outside the print volume to render it accordingly
if (!m_volumes.empty())
{
bool contained = m_volumes.check_outside_state(m_config);
ModelInstance::EPrintVolumeState state;
bool contained = m_volumes.check_outside_state(m_config, &state);
if (!contained)
{
enable_warning_texture(true);
_3DScene::generate_warning_texture(L("Detected object outside print volume"));
m_on_enable_action_buttons_callback.call(false);
_generate_warning_texture(L("Detected object outside print volume"));
m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
}
else
{
enable_warning_texture(false);
m_volumes.reset_outside_state();
_3DScene::reset_warning_texture();
_reset_warning_texture();
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
}
}
else
{
enable_warning_texture(false);
_3DScene::reset_warning_texture();
_reset_warning_texture();
m_on_enable_action_buttons_callback.call(false);
}
}
@ -2490,10 +2710,10 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
_load_gcode_unretractions(preview_data);
if (m_volumes.empty())
_3DScene::reset_legend_texture();
reset_legend_texture();
else
{
_3DScene::generate_legend_texture(preview_data, tool_colors);
_generate_legend_texture(preview_data, tool_colors);
// removes empty volumes
m_volumes.volumes.erase(std::remove_if(m_volumes.volumes.begin(), m_volumes.volumes.end(),
@ -3103,6 +3323,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
deselect_volumes();
_on_select(-1);
update_gizmos_data();
}
}
else if (evt.LeftUp() && m_gizmos.is_dragging())
@ -3130,6 +3351,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.set_start_position_3D_as_invalid();
m_mouse.set_start_position_2D_as_invalid();
m_mouse.dragging = false;
m_dirty = true;
}
else if (evt.Moving())
{
@ -3181,6 +3403,14 @@ Point GLCanvas3D::get_local_mouse_position() const
return Point(mouse_pos.x, mouse_pos.y);
}
void GLCanvas3D::reset_legend_texture()
{
if (!set_current())
return;
m_legend_texture.reset();
}
bool GLCanvas3D::_is_shown_on_screen() const
{
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
@ -3272,7 +3502,7 @@ BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const
BoundingBoxf3 bb;
for (const GLVolume* volume : m_volumes.volumes)
{
if ((volume != nullptr) && volume->selected)
if ((volume != nullptr) && !volume->is_wipe_tower && volume->selected)
bb.merge(volume->transformed_bounding_box());
}
return bb;
@ -3441,6 +3671,7 @@ void GLCanvas3D::_picking_pass() const
::glDisable(GL_MULTISAMPLE);
::glDisable(GL_BLEND);
::glEnable(GL_DEPTH_TEST);
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -3549,7 +3780,7 @@ void GLCanvas3D::_render_objects() const
{
const BoundingBoxf3& bed_bb = m_bed.get_bounding_box();
m_volumes.set_print_box((float)bed_bb.min.x, (float)bed_bb.min.y, 0.0f, (float)bed_bb.max.x, (float)bed_bb.max.y, (float)m_config->opt_float("max_print_height"));
m_volumes.check_outside_state(m_config);
m_volumes.check_outside_state(m_config, nullptr);
}
// do not cull backfaces to show broken geometry, if any
::glDisable(GL_CULL_FACE);
@ -3588,11 +3819,11 @@ void GLCanvas3D::_render_warning_texture() const
return;
// If the warning texture has not been loaded into the GPU, do it now.
unsigned int tex_id = _3DScene::finalize_warning_texture();
unsigned int tex_id = m_warning_texture.get_id();
if (tex_id > 0)
{
unsigned int w = _3DScene::get_warning_texture_width();
unsigned int h = _3DScene::get_warning_texture_height();
int w = m_warning_texture.get_width();
int h = m_warning_texture.get_height();
if ((w > 0) && (h > 0))
{
::glDisable(GL_DEPTH_TEST);
@ -3621,11 +3852,11 @@ void GLCanvas3D::_render_legend_texture() const
return;
// If the legend texture has not been loaded into the GPU, do it now.
unsigned int tex_id = _3DScene::finalize_legend_texture();
unsigned int tex_id = m_legend_texture.get_id();
if (tex_id > 0)
{
unsigned int w = _3DScene::get_legend_texture_width();
unsigned int h = _3DScene::get_legend_texture_height();
int w = m_legend_texture.get_width();
int h = m_legend_texture.get_height();
if ((w > 0) && (h > 0))
{
::glDisable(GL_DEPTH_TEST);
@ -4539,5 +4770,29 @@ std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& col
return output;
}
void GLCanvas3D::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
if (!set_current())
return;
m_legend_texture.generate(preview_data, tool_colors);
}
void GLCanvas3D::_generate_warning_texture(const std::string& msg)
{
if (!set_current())
return;
m_warning_texture.generate(msg);
}
void GLCanvas3D::_reset_warning_texture()
{
if (!set_current())
return;
m_warning_texture.reset();
}
} // namespace GUI
} // namespace Slic3r

View File

@ -394,9 +394,35 @@ public:
GLGizmoBase* _get_current() const;
};
class WarningTexture : public GUI::GLTexture
{
static const unsigned char Background_Color[3];
static const unsigned char Opacity;
public:
bool generate(const std::string& msg);
};
class LegendTexture : public GUI::GLTexture
{
static const int Px_Title_Offset = 5;
static const int Px_Text_Offset = 5;
static const int Px_Square = 20;
static const int Px_Square_Contour = 1;
static const int Px_Border = Px_Square / 2;
static const unsigned char Squares_Border_Color[3];
static const unsigned char Background_Color[3];
static const unsigned char Opacity;
public:
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
};
private:
wxGLCanvas* m_canvas;
wxGLContext* m_context;
LegendTexture m_legend_texture;
WarningTexture m_warning_texture;
wxTimer* m_timer;
Camera m_camera;
Bed m_bed;
@ -578,6 +604,8 @@ public:
Size get_canvas_size() const;
Point get_local_mouse_position() const;
void reset_legend_texture();
private:
bool _is_shown_on_screen() const;
void _force_zoom_to_bed();
@ -643,6 +671,13 @@ private:
void _on_move(const std::vector<int>& volume_idxs);
void _on_select(int volume_idx);
// generates the legend texture in dependence of the current shown view type
void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates a warning texture containing the given message
void _generate_warning_texture(const std::string& msg);
void _reset_warning_texture();
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
};

View File

@ -550,6 +550,15 @@ void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePrevie
it->second->load_gcode_preview(*preview_data, str_tool_colors);
}
void GLCanvas3DManager::reset_legend_texture()
{
for (CanvasesMap::value_type& canvas : m_canvases)
{
if (canvas.second != nullptr)
canvas.second->reset_legend_texture();
}
}
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
{
CanvasesMap::iterator it = _get_canvas(canvas);

View File

@ -137,6 +137,8 @@ public:
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
void reset_legend_texture();
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);

View File

@ -10,7 +10,7 @@ namespace GUI {
class GLTexture
{
private:
protected:
unsigned int m_id;
int m_width;
int m_height;
@ -18,7 +18,7 @@ namespace GUI {
public:
GLTexture();
~GLTexture();
virtual ~GLTexture();
bool load_from_file(const std::string& filename, bool generate_mipmaps);
void reset();
@ -26,11 +26,12 @@ namespace GUI {
unsigned int get_id() const;
int get_width() const;
int get_height() const;
const std::string& get_source() const;
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
private:
protected:
void _generate_mipmaps(wxImage& image);
};

View File

@ -105,10 +105,6 @@
void release_geometry();
void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z);
bool check_outside_state(DynamicPrintConfig* config)
%code%{
RETVAL = THIS->check_outside_state(config);
%};
void reset_outside_state();
void update_colors_by_extruder(DynamicPrintConfig* config);
@ -628,63 +624,11 @@ register_on_update_geometry_info_callback(canvas, callback)
CODE:
_3DScene::register_on_update_geometry_info_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback);
unsigned int
finalize_legend_texture()
CODE:
RETVAL = _3DScene::finalize_legend_texture();
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
reset_legend_texture()
CODE:
_3DScene::reset_legend_texture();
void
generate_warning_texture(std::string msg)
CODE:
_3DScene::generate_warning_texture(msg);
unsigned int
finalize_warning_texture()
CODE:
RETVAL = _3DScene::finalize_warning_texture();
OUTPUT:
RETVAL
unsigned int
get_warning_texture_width()
CODE:
RETVAL = _3DScene::get_warning_texture_width();
OUTPUT:
RETVAL
unsigned int
get_warning_texture_height()
CODE:
RETVAL = _3DScene::get_warning_texture_height();
OUTPUT:
RETVAL
void
reset_warning_texture()
CODE:
_3DScene::reset_warning_texture();
std::vector<int>
load_model_object(canvas, model_object, obj_idx, instance_idxs)
SV *canvas;