Merge remote-tracking branch 'origin/master' into tm_colldetection_upgr

This commit is contained in:
tamasmeszaros 2019-01-31 10:11:56 +01:00
commit 30477c710c
32 changed files with 563 additions and 276 deletions

View File

@ -1,5 +1,5 @@
### Version
_Version of Slic3r used goes here_
_Version of Slic3r Prusa Edition used goes here_
_Use `About->About Slic3r` for release versions_
@ -7,6 +7,10 @@ _For -dev versions, use `git describe --tag` or get the hash value for the versi
### Operating system type + version
_What OS are you using, and state any version #s_
_In case of 3D rendering issues, please attach the content of menu Help -> System Info dialog_
### 3D printer brand / version + firmware version (if known)
_What 3D printer brand / version are you printing on, is it a stock model or did you modify the printer, what firmware is running on your printer, version of the firmware #s_
### Behavior
* _Describe the problem_
@ -18,5 +22,5 @@ _What OS are you using, and state any version #s_
_Is this a new feature request?_
#### STL/Config (.ZIP) where problem occurs
_Upload a zipped copy of an STL and your config (`File -> Export Config`)_
#### Project File (.3MF) where problem occurs
_Upload a Slic3r PE Project File (.3MF) (`Plater -> Export plate as 3MF` for Slic3r PE 1.41.2 and older, `File -> Save` / `Save Project` for Slic3r PE 1.42.0-alpha and newer)_

View File

@ -86,9 +86,8 @@ set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
if(NOT WIN32)
# Add DEBUG flags for the debug builds in a way the Visual Studio adds these flags.
# Add DEBUG flags to debug builds.
add_compile_options("$<$<CONFIG:DEBUG>:-DDEBUG>")
add_compile_options("$<$<CONFIG:DEBUG>:-D_DEBUG>")
endif()
# To be able to link libslic3r with the Perl XS module.

View File

@ -1,8 +1,21 @@
if (MSVC_VERSION EQUAL 1800)
set(DEP_VS_VER "12")
set(DEP_BOOST_TOOLSET "msvc-12.0")
elseif (MSVC_VERSION EQUAL 1900)
set(DEP_VS_VER "14")
set(DEP_BOOST_TOOLSET "msvc-14.0")
elseif (MSVC_VERSION GREATER 1900)
set(DEP_VS_VER "15")
set(DEP_BOOST_TOOLSET "msvc-14.1")
else ()
message(FATAL_ERROR "Unsupported MSVC version")
endif ()
if (${DEPS_BITS} EQUAL 32)
set(DEP_MSVC_GEN "Visual Studio 12")
set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER}")
else ()
set(DEP_MSVC_GEN "Visual Studio 12 Win64")
set(DEP_MSVC_GEN "Visual Studio ${DEP_VS_VER} Win64")
endif ()
@ -29,7 +42,7 @@ ExternalProject_Add(dep_boost
--with-regex
"--prefix=${DESTDIR}/usr/local"
"address-model=${DEPS_BITS}"
toolset=msvc-12.0
"toolset=${DEP_BOOST_TOOLSET}"
link=static
variant=release
threading=multi
@ -204,7 +217,7 @@ ExternalProject_Add(dep_libcurl
URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}"
BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static "VC=${DEP_VS_VER}" GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}"
INSTALL_COMMAND cd builds\\libcurl-*-release-*-winssl
&& "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include"
&& "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib"
@ -214,7 +227,7 @@ if (${DEP_DEBUG})
ExternalProject_Add_Step(dep_libcurl build_debug
DEPENDEES build
DEPENDERS install
COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=yes "MACHINE=${DEP_LIBCURL_TARGET}"
COMMAND cd winbuild && nmake /f Makefile.vc mode=static "VC=${DEP_VS_VER}" GEN_PDB=yes DEBUG=yes "MACHINE=${DEP_LIBCURL_TARGET}"
WORKING_DIRECTORY "${SOURCE_DIR}"
)
ExternalProject_Add_Step(dep_libcurl install_debug

View File

@ -45,7 +45,9 @@ extern "C" {
#define chdir _chdir
#define isatty _isatty
#define lseek _lseek
#if _MSC_VER < 1900
#define snprintf _snprintf
#endif
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#define stat _stat

View File

@ -71,8 +71,8 @@ add_library(libslic3r STATIC
GCode/CoolingBuffer.hpp
GCode/PostProcessor.cpp
GCode/PostProcessor.hpp
GCode/PressureEqualizer.cpp
GCode/PressureEqualizer.hpp
# GCode/PressureEqualizer.cpp
# GCode/PressureEqualizer.hpp
GCode/PreviewData.cpp
GCode/PreviewData.hpp
GCode/PrintExtents.cpp

View File

@ -662,10 +662,14 @@ void GCode::_do_export(Print &print, FILE *file)
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
if (print.config().spiral_vase.value)
m_spiral_vase = make_unique<SpiralVase>(print.config());
#ifdef HAS_PRESSURE_EQUALIZER
if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 ||
print.config().max_volumetric_extrusion_rate_slope_negative.value > 0)
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config());
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
#else /* HAS_PRESSURE_EQUALIZER */
m_enable_extrusion_role_markers = false;
#endif /* HAS_PRESSURE_EQUALIZER */
// Write information on the generator.
_write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str());
@ -860,7 +864,7 @@ void GCode::_do_export(Print &print, FILE *file)
if (! (has_wipe_tower && print.config().single_extruder_multi_material_priming)) {
// Set initial extruder only after custom start G-code.
// Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed.
_write(file, this->set_extruder(initial_extruder_id));
_write(file, this->set_extruder(initial_extruder_id, 0.));
}
// Do all objects for each layer.
@ -918,8 +922,10 @@ void GCode::_do_export(Print &print, FILE *file)
this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), &copy - object.copies().data());
print.throw_if_canceled();
}
#ifdef HAS_PRESSURE_EQUALIZER
if (m_pressure_equalizer)
_write(file, m_pressure_equalizer->process("", true));
#endif /* HAS_PRESSURE_EQUALIZER */
++ finished_objects;
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
// Reset it when starting another object from 1st layer.
@ -974,8 +980,10 @@ void GCode::_do_export(Print &print, FILE *file)
this->process_layer(file, print, layer.second, layer_tools, size_t(-1));
print.throw_if_canceled();
}
#ifdef HAS_PRESSURE_EQUALIZER
if (m_pressure_equalizer)
_write(file, m_pressure_equalizer->process("", true));
#endif /* HAS_PRESSURE_EQUALIZER */
if (m_wipe_tower)
// Purge the extruder, pull out the active filament.
_write(file, m_wipe_tower->finalize(*this));
@ -1533,15 +1541,13 @@ void GCode::process_layer(
}
} // for objects
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
std::vector<std::unique_ptr<EdgeGrid::Grid>> lower_layer_edge_grids(layers.size());
for (unsigned int extruder_id : layer_tools.extruders)
{
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
this->set_extruder(extruder_id);
this->set_extruder(extruder_id, print_z);
// let analyzer tag generator aware of a role type change
if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower)
@ -1658,11 +1664,13 @@ void GCode::process_layer(
if (m_cooling_buffer)
gcode = m_cooling_buffer->process_layer(gcode, layer.id());
#ifdef HAS_PRESSURE_EQUALIZER
// Apply pressure equalization if enabled;
// printf("G-code before filter:\n%s\n", gcode.c_str());
if (m_pressure_equalizer)
gcode = m_pressure_equalizer->process(gcode.c_str(), false);
// printf("G-code after filter:\n%s\n", out.c_str());
#endif /* HAS_PRESSURE_EQUALIZER */
_write(file, gcode);
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
@ -2643,7 +2651,7 @@ std::string GCode::retract(bool toolchange)
return gcode;
}
std::string GCode::set_extruder(unsigned int extruder_id)
std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
{
if (!m_writer.need_toolchange(extruder_id))
return "";
@ -2677,6 +2685,8 @@ std::string GCode::set_extruder(unsigned int extruder_id)
DynamicConfig config;
config.set_key_value("previous_extruder", new ConfigOptionInt((int)m_writer.extruder()->id()));
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
gcode += placeholder_parser_process("toolchange_gcode", m_config.toolchange_gcode.value, extruder_id, &config);
check_add_eol(gcode);
}

View File

@ -11,7 +11,6 @@
#include "Print.hpp"
#include "PrintConfig.hpp"
#include "GCode/CoolingBuffer.hpp"
#include "GCode/PressureEqualizer.hpp"
#include "GCode/SpiralVase.hpp"
#include "GCode/ToolOrdering.hpp"
#include "GCode/WipeTower.hpp"
@ -22,6 +21,10 @@
#include <memory>
#include <string>
#ifdef HAS_PRESSURE_EQUALIZER
#include "GCode/PressureEqualizer.hpp"
#endif /* HAS_PRESSURE_EQUALIZER */
namespace Slic3r {
// Forward declarations.
@ -257,12 +260,12 @@ protected:
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
std::string retract(bool toolchange = false);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id);
std::string set_extruder(unsigned int extruder_id, double print_z);
/* Origin of print coordinates expressed in unscaled G-code coordinates.
This affects the input arguments supplied to the extrude*() and travel_to()
methods. */
Vec2d m_origin;
Vec2d m_origin;
FullPrintConfig m_config;
GCodeWriter m_writer;
PlaceholderParser m_placeholder_parser;
@ -306,7 +309,9 @@ protected:
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
std::unique_ptr<SpiralVase> m_spiral_vase;
#ifdef HAS_PRESSURE_EQUALIZER
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
#endif /* HAS_PRESSURE_EQUALIZER */
std::unique_ptr<WipeTowerIntegration> m_wipe_tower;
// Heights at which the skirt has already been extruded.

View File

@ -479,14 +479,14 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
}
case Extrusion::ColorPrint:
{
const auto color_print_cnt = cp_values.size();
const int color_cnt = (int)tool_colors.size()/4;
const auto color_print_cnt = (int)cp_values.size();
for (int i = color_print_cnt; i >= 0 ; --i)
{
int val = i;
while (val >= GCodePreviewData::Range::Colors_Count)
val -= GCodePreviewData::Range::Colors_Count;
GCodePreviewData::Color color = Range::Default_Colors[val];
GCodePreviewData::Color color;
::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (i % color_cnt) * 4), 4 * sizeof(float));
if (color_print_cnt == 0) {
items.emplace_back(Slic3r::I18N::translate(L("Default print color")), color);
break;
@ -521,6 +521,12 @@ size_t GCodePreviewData::memory_used() const
sizeof(shell) + sizeof(ranges);
}
const std::vector<std::string>& GCodePreviewData::ColorPrintColors()
{
static std::vector<std::string> color_print = {"#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6"};
return color_print;
}
GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2)
{
return GCodePreviewData::Color(clamp(0.0f, 1.0f, c1.rgba[0] + c2.rgba[0]),

View File

@ -216,6 +216,8 @@ public:
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
static const std::vector<std::string>& ColorPrintColors();
};
GCodePreviewData::Color operator + (const GCodePreviewData::Color& c1, const GCodePreviewData::Color& c2);

View File

@ -381,22 +381,7 @@ public:
Writer& comment_material(WipeTowerPrusaMM::material_type material)
{
m_gcode += "; material : ";
switch (material)
{
case WipeTowerPrusaMM::PVA:
m_gcode += "#8 (PVA)";
break;
case WipeTowerPrusaMM::SCAFF:
m_gcode += "#5 (Scaffold)";
break;
case WipeTowerPrusaMM::FLEX:
m_gcode += "#4 (Flex)";
break;
default:
m_gcode += "DEFAULT (PLA)";
break;
}
m_gcode += "\n";
m_gcode += WipeTowerPrusaMM::to_string(material) + "\n";
return *this;
};
@ -487,6 +472,23 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam
return INVALID;
}
std::string WipeTowerPrusaMM::to_string(material_type material)
{
switch (material) {
case PLA: return "PLA";
case ABS: return "ABS";
case PET: return "PET";
case HIPS: return "HIPS";
case FLEX: return "FLEX";
case SCAFF: return "SCAFF";
case EDGE: return "EDGE";
case NGEN: return "NGEN";
case PVA: return "PVA";
case INVALID:
default: return "INVALID";
}
}
// Returns gcode to prime the nozzles at the front edge of the print bed.
WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
// print_z of the first layer.

View File

@ -38,6 +38,7 @@ public:
// Parse material name into material_type.
static material_type parse_material(const char *name);
static std::string to_string(material_type material);
// x -- x coordinates of wipe tower in mm ( left bottom corner )
// y -- y coordinates of wipe tower in mm ( left bottom corner )

View File

@ -53,6 +53,11 @@
#define HAS_INTRINSIC_128_TYPE
#endif
#if defined(_MSC_VER) && defined(_WIN64)
#include <intrin.h>
#pragma intrinsic(_mul128)
#endif
//------------------------------------------------------------------------------
// Int128 class (enables safe math on signed 64bit integers)
// eg Int128 val1((int64_t)9223372036854775807); //ie 2^63 -1

View File

@ -489,6 +489,9 @@ void Model::convert_multipart_object(unsigned int max_extruders)
{
new_v->name = o->name;
new_v->config.set_deserialize("extruder", get_auto_extruder_id_as_string(max_extruders));
#if ENABLE_VOLUMES_CENTERING_FIXES
new_v->translate(-o->origin_translation);
#endif // ENABLE_VOLUMES_CENTERING_FIXES
}
}
@ -549,7 +552,7 @@ std::string Model::propose_export_file_name() const
for (const ModelObject *model_object : this->objects)
for (ModelInstance *model_instance : model_object->instances)
if (model_instance->is_printable())
return model_object->input_file;
return model_object->name.empty() ? model_object->input_file : model_object->name;
return std::string();
}
@ -1683,7 +1686,7 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO
return false;
}
#ifdef _DEBUG
#ifndef NDEBUG
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
void check_model_ids_validity(const Model &model)
{
@ -1729,6 +1732,6 @@ void check_model_ids_equal(const Model &model1, const Model &model2)
}
}
}
#endif /* _DEBUG */
#endif /* NDEBUG */
}

View File

@ -629,11 +629,11 @@ extern bool model_object_list_extended(const Model &model_old, const Model &mode
// than the old ModelObject.
extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type);
#ifdef _DEBUG
#ifndef NDEBUG
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
void check_model_ids_validity(const Model &model);
void check_model_ids_equal(const Model &model1, const Model &model2);
#endif /* _DEBUG */
#endif /* NDEBUG */
}

View File

@ -135,8 +135,10 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"min_print_speed",
"max_print_speed",
"max_volumetric_speed",
#ifdef HAS_PRESSURE_EQUALIZER
"max_volumetric_extrusion_rate_slope_positive",
"max_volumetric_extrusion_rate_slope_negative",
#endif /* HAS_PRESSURE_EQUALIZER */
"notes",
"only_retract_when_crossing_perimeters",
"output_filename_format",
@ -1908,7 +1910,7 @@ DynamicConfig PrintStatistics::config() const
config.set_key_value("print_time", new ConfigOptionString(normal_print_time));
config.set_key_value("normal_print_time", new ConfigOptionString(normal_print_time));
config.set_key_value("silent_print_time", new ConfigOptionString(silent_print_time));
config.set_key_value("used_filament", new ConfigOptionFloat (this->total_used_filament));
config.set_key_value("used_filament", new ConfigOptionFloat (this->total_used_filament / 1000.));
config.set_key_value("extruded_volume", new ConfigOptionFloat (this->total_extruded_volume));
config.set_key_value("total_cost", new ConfigOptionFloat (this->total_cost));
config.set_key_value("total_weight", new ConfigOptionFloat (this->total_weight));
@ -1924,7 +1926,7 @@ DynamicConfig PrintStatistics::placeholders()
"print_time", "normal_print_time", "silent_print_time",
"used_filament", "extruded_volume", "total_cost", "total_weight",
"total_wipe_tower_cost", "total_wipe_tower_filament"})
config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}"));
config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}"));
return config;
}

View File

@ -1208,6 +1208,7 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert;
def->default_value = new ConfigOptionFloat(0);
#ifdef HAS_PRESSURE_EQUALIZER
def = this->add("max_volumetric_extrusion_rate_slope_positive", coFloat);
def->label = L("Max volumetric slope positive");
def->tooltip = L("This experimental setting is used to limit the speed of change in extrusion rate. "
@ -1231,6 +1232,7 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->mode = comExpert;
def->default_value = new ConfigOptionFloat(0);
#endif /* HAS_PRESSURE_EQUALIZER */
def = this->add("min_fan_speed", coInts);
def->label = L("Min");
@ -2740,6 +2742,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
"start_perimeters_at_concave_points", "start_perimeters_at_non_overhang", "randomize_start",
"seal_position", "vibration_limit", "bed_size",
"print_center", "g0", "threads", "pressure_advance", "wipe_tower_per_color_wipe"
#ifndef HAS_PRESSURE_EQUALIZER
, "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative"
#endif /* HAS_PRESSURE_EQUALIZER */
};
if (ignore.find(opt_key) != ignore.end()) {

View File

@ -20,6 +20,8 @@
#include "libslic3r.h"
#include "Config.hpp"
// #define HAS_PRESSURE_EQUALIZER
namespace Slic3r {
enum PrinterTechnology
@ -620,8 +622,10 @@ public:
ConfigOptionString layer_gcode;
ConfigOptionFloat max_print_speed;
ConfigOptionFloat max_volumetric_speed;
#ifdef HAS_PRESSURE_EQUALIZER
ConfigOptionFloat max_volumetric_extrusion_rate_slope_positive;
ConfigOptionFloat max_volumetric_extrusion_rate_slope_negative;
#endif
ConfigOptionPercents retract_before_wipe;
ConfigOptionFloats retract_length;
ConfigOptionFloats retract_length_toolchange;
@ -689,8 +693,10 @@ protected:
OPT_PTR(layer_gcode);
OPT_PTR(max_print_speed);
OPT_PTR(max_volumetric_speed);
#ifdef HAS_PRESSURE_EQUALIZER
OPT_PTR(max_volumetric_extrusion_rate_slope_positive);
OPT_PTR(max_volumetric_extrusion_rate_slope_negative);
#endif /* HAS_PRESSURE_EQUALIZER */
OPT_PTR(retract_before_wipe);
OPT_PTR(retract_length);
OPT_PTR(retract_length_toolchange);

View File

@ -35,6 +35,27 @@
#include "GUI.hpp"
#ifdef HAS_GLSAFE
void glAssertRecentCallImpl()
{
GLenum err = glGetError();
if (err == GL_NO_ERROR)
return;
const char *sErr = 0;
switch (err) {
case GL_INVALID_ENUM: sErr = "Invalid Enum"; break;
case GL_INVALID_VALUE: sErr = "Invalid Value"; break;
case GL_INVALID_OPERATION: sErr = "Invalid Operation"; break;
case GL_STACK_OVERFLOW: sErr = "Stack Overflow"; break;
case GL_STACK_UNDERFLOW: sErr = "Stack Underflow"; break;
case GL_OUT_OF_MEMORY: sErr = "Out Of Memory"; break;
default: sErr = "Unknown"; break;
}
BOOST_LOG_TRIVIAL(error) << "OpenGL error " << (int)err << ": " << sErr;
assert(false);
}
#endif
namespace Slic3r {
void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
@ -81,25 +102,25 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
if (use_VBOs) {
if (! empty()) {
glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id);
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glsafe(glGenBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glBufferData(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved.size() * 4, this->vertices_and_normals_interleaved.data(), GL_STATIC_DRAW));
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
this->vertices_and_normals_interleaved.clear();
}
if (! this->triangle_indices.empty()) {
glGenBuffers(1, &this->triangle_indices_VBO_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW);
glsafe(glGenBuffers(1, &this->triangle_indices_VBO_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices.size() * 4, this->triangle_indices.data(), GL_STATIC_DRAW));
this->triangle_indices.clear();
}
if (! this->quad_indices.empty()) {
glGenBuffers(1, &this->quad_indices_VBO_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW);
glsafe(glGenBuffers(1, &this->quad_indices_VBO_id));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices.size() * 4, this->quad_indices.data(), GL_STATIC_DRAW));
this->quad_indices.clear();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
this->shrink_to_fit();
}
@ -107,15 +128,15 @@ void GLIndexedVertexArray::finalize_geometry(bool use_VBOs)
void GLIndexedVertexArray::release_geometry()
{
if (this->vertices_and_normals_interleaved_VBO_id) {
glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id);
glsafe(glDeleteBuffers(1, &this->vertices_and_normals_interleaved_VBO_id));
this->vertices_and_normals_interleaved_VBO_id = 0;
}
if (this->triangle_indices_VBO_id) {
glDeleteBuffers(1, &this->triangle_indices_VBO_id);
glsafe(glDeleteBuffers(1, &this->triangle_indices_VBO_id));
this->triangle_indices_VBO_id = 0;
}
if (this->quad_indices_VBO_id) {
glDeleteBuffers(1, &this->quad_indices_VBO_id);
glsafe(glDeleteBuffers(1, &this->quad_indices_VBO_id));
this->quad_indices_VBO_id = 0;
}
this->clear();
@ -125,42 +146,42 @@ void GLIndexedVertexArray::release_geometry()
void GLIndexedVertexArray::render() const
{
if (this->vertices_and_normals_interleaved_VBO_id) {
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
} else {
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3);
glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data());
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
if (this->indexed()) {
if (this->vertices_and_normals_interleaved_VBO_id) {
// Render using the Vertex Buffer Objects.
if (this->triangle_indices_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr);
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, nullptr));
}
if (this->quad_indices_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr);
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, nullptr));
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
if (! this->triangle_indices.empty())
glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data());
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(this->triangle_indices_size), GL_UNSIGNED_INT, this->triangle_indices.data()));
if (! this->quad_indices.empty())
glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data());
glsafe(glDrawElements(GL_QUADS, GLsizei(this->quad_indices_size), GL_UNSIGNED_INT, this->quad_indices.data()));
}
} else
glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6));
glsafe(glDrawArrays(GL_TRIANGLES, 0, GLsizei(this->vertices_and_normals_interleaved_size / 6)));
if (this->vertices_and_normals_interleaved_VBO_id)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
}
void GLIndexedVertexArray::render(
@ -173,35 +194,35 @@ void GLIndexedVertexArray::render(
if (this->vertices_and_normals_interleaved_VBO_id) {
// Render using the Vertex Buffer Objects.
glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glsafe(glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id));
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
if (this->triangle_indices_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id);
glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id));
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
}
if (this->quad_indices_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id);
glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->quad_indices_VBO_id));
glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glsafe(glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
// Render in an immediate mode.
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3);
glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glsafe(glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data() + 3));
glsafe(glNormalPointer(GL_FLOAT, 6 * sizeof(float), this->vertices_and_normals_interleaved.data()));
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
if (! this->triangle_indices.empty())
glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first));
glsafe(glDrawElements(GL_TRIANGLES, GLsizei(std::min(this->triangle_indices_size, tverts_range.second - tverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->triangle_indices.data() + tverts_range.first)));
if (! this->quad_indices.empty())
glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first));
glsafe(glDrawElements(GL_QUADS, GLsizei(std::min(this->quad_indices_size, qverts_range.second - qverts_range.first)), GL_UNSIGNED_INT, (const void*)(this->quad_indices.data() + qverts_range.first)));
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
}
const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
@ -375,15 +396,15 @@ void GLVolume::render() const
if (!is_active)
return;
::glCullFace(GL_BACK);
::glPushMatrix();
glsafe(::glCullFace(GL_BACK));
glsafe(::glPushMatrix());
::glMultMatrixd(world_matrix().data());
glsafe(::glMultMatrixd(world_matrix().data()));
if (this->indexed_vertex_array.indexed())
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
else
this->indexed_vertex_array.render();
::glPopMatrix();
glsafe(::glPopMatrix());
}
void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const
@ -398,63 +419,63 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
if (n_triangles + n_quads == 0)
{
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (color_id >= 0)
{
float color[4];
::memcpy((void*)color, (const void*)render_color, 4 * sizeof(float));
::glUniform4fv(color_id, 1, (const GLfloat*)color);
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color));
}
else
::glColor4fv(render_color);
glsafe(::glColor4fv(render_color));
if (detection_id != -1)
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0));
if (worldmatrix_id != -1)
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data()));
render();
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
return;
}
if (color_id >= 0)
::glUniform4fv(color_id, 1, (const GLfloat*)render_color);
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)render_color));
else
::glColor4fv(render_color);
glsafe(::glColor4fv(render_color));
if (detection_id != -1)
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
glsafe(::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0));
if (worldmatrix_id != -1)
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
glsafe(::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data()));
::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr));
::glPushMatrix();
glsafe(::glPushMatrix());
::glMultMatrixd(world_matrix().data());
glsafe(::glMultMatrixd(world_matrix().data()));
if (n_triangles > 0)
{
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id);
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id));
glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4)));
}
if (n_quads > 0)
{
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id);
::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id));
glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4)));
}
::glPopMatrix();
glsafe(::glPopMatrix());
}
void GLVolume::render_legacy() const
@ -467,33 +488,33 @@ void GLVolume::render_legacy() const
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
if (n_triangles + n_quads == 0)
{
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
::glColor4fv(render_color);
glsafe(::glColor4fv(render_color));
render();
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
return;
}
::glColor4fv(render_color);
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3);
::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data());
glsafe(::glColor4fv(render_color));
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3));
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()));
::glPushMatrix();
glsafe(::glPushMatrix());
::glMultMatrixd(world_matrix().data());
glsafe(::glMultMatrixd(world_matrix().data()));
if (n_triangles > 0)
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first);
glsafe(::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first));
if (n_quads > 0)
::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first);
glsafe(::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first));
::glPopMatrix();
glsafe(::glPopMatrix());
}
std::vector<int> GLVolumeCollection::load_object(
@ -705,7 +726,7 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum
if ((type == GLVolumeCollection::Transparent) && (list.size() > 1))
{
Transform3d modelview_matrix;
::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());
glsafe(::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()));
for (GLVolumeWithZ& volume : list)
{
@ -722,18 +743,18 @@ static GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolum
void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface, std::function<bool(const GLVolume&)> filter_func) const
{
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
::glCullFace(GL_BACK);
glsafe(::glCullFace(GL_BACK));
if (disable_cullface)
::glDisable(GL_CULL_FACE);
glsafe(::glDisable(GL_CULL_FACE));
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
GLint current_program_id;
::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id);
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id));
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1;
GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1;
@ -742,13 +763,13 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
GLint print_box_worldmatrix_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
if (print_box_min_id != -1)
::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min);
glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min));
if (print_box_max_id != -1)
::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max);
glsafe(::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max));
if (z_range_id != -1)
::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range);
glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func);
for (GLVolumeWithZ& volume : to_render) {
@ -756,29 +777,29 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool
volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
}
::glBindBuffer(GL_ARRAY_BUFFER, 0);
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
if (disable_cullface)
::glEnable(GL_CULL_FACE);
glsafe(::glEnable(GL_CULL_FACE));
::glDisable(GL_BLEND);
glsafe(::glDisable(GL_BLEND));
}
void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(glEnable(GL_BLEND));
glsafe(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
glCullFace(GL_BACK);
glsafe(glCullFace(GL_BACK));
if (disable_cullface)
::glDisable(GL_CULL_FACE);
glsafe(::glDisable(GL_CULL_FACE));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glsafe(glEnableClientState(GL_VERTEX_ARRAY));
glsafe(glEnableClientState(GL_NORMAL_ARRAY));
GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, std::function<bool(const GLVolume&)>());
for (GLVolumeWithZ& volume : to_render)
@ -787,13 +808,13 @@ void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface)
volume.first->render_legacy();
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glsafe(glDisableClientState(GL_VERTEX_ARRAY));
glsafe(glDisableClientState(GL_NORMAL_ARRAY));
if (disable_cullface)
::glEnable(GL_CULL_FACE);
glsafe(::glEnable(GL_CULL_FACE));
glDisable(GL_BLEND);
glsafe(glDisable(GL_BLEND));
}
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state)
@ -1718,44 +1739,44 @@ void GLModel::render() const
void GLModel::render_VBOs() const
{
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
::glCullFace(GL_BACK);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
glsafe(::glCullFace(GL_BACK));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
GLint current_program_id;
::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id);
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &current_program_id));
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
m_volume.render_VBOs(color_id, -1, -1);
::glBindBuffer(GL_ARRAY_BUFFER, 0);
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
::glDisable(GL_BLEND);
glsafe(::glDisable(GL_BLEND));
}
void GLModel::render_legacy() const
{
::glEnable(GL_LIGHTING);
::glEnable(GL_BLEND);
::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glsafe(::glEnable(GL_LIGHTING));
glsafe(::glEnable(GL_BLEND));
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
::glCullFace(GL_BACK);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
glsafe(::glCullFace(GL_BACK));
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
m_volume.render_legacy();
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
::glDisable(GL_BLEND);
::glDisable(GL_LIGHTING);
glsafe(::glDisable(GL_BLEND));
glsafe(::glDisable(GL_LIGHTING));
}
bool GLArrow::on_init(bool useVBOs)

View File

@ -11,6 +11,19 @@
#include <functional>
#ifndef NDEBUG
#define HAS_GLSAFE
#endif
#ifdef HAS_GLSAFE
extern void glAssertRecentCallImpl();
inline void glAssertRecentCall() { glAssertRecentCallImpl(); }
#define glsafe(cmd) do { cmd; glAssertRecentCallImpl(); } while (false)
#else
inline void glAssertRecentCall() { }
#define glsafe(cmd) cmd
#endif
namespace Slic3r {
class Print;

View File

@ -143,9 +143,11 @@ void Field::get_value_by_opt_type(wxString& str)
break;
}
double val;
// Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false);
if(!str.ToCDouble(&val))
{
show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits")));
show_error(m_parent, _(L("Invalid numeric input.")));
set_value(double_to_string(val), true);
}
if (m_opt.min > val || val > m_opt.max)
@ -163,10 +165,12 @@ void Field::get_value_by_opt_type(wxString& str)
if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%')
{
double val;
// Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false);
if (!str.ToCDouble(&val))
{
show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits")));
set_value(double_to_string(val), true);
show_error(m_parent, _(L("Invalid numeric input.")));
set_value(double_to_string(val), true);
}
else if (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max ||
m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)
@ -334,6 +338,7 @@ void TextCtrl::propagate_value()
boost::any& TextCtrl::get_value()
{
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
// modifies ret_string!
get_value_by_opt_type(ret_str);
return m_value;
@ -727,11 +732,13 @@ boost::any& Choice::get_value()
else if (m_opt.gui_type == "f_enum_open") {
const int ret_enum = static_cast<wxComboBox*>(window)->GetSelection();
if (ret_enum < 0 || m_opt.enum_values.empty() || m_opt.type == coStrings)
// modifies ret_string!
get_value_by_opt_type(ret_str);
else
m_value = atof(m_opt.enum_values[ret_enum].c_str());
}
else
// modifies ret_string!
get_value_by_opt_type(ret_str);
return m_value;

View File

@ -115,7 +115,7 @@ public:
/// subclasses should overload with a specific version
/// Postcondition: Method does not fire the on_change event.
virtual void set_value(const boost::any& value, bool change_event) = 0;
/// Gets a boost::any representing this control.
/// subclasses should overload with a specific version
virtual boost::any& get_value() = 0;
@ -128,6 +128,8 @@ public:
virtual wxString get_tooltip_text(const wxString& default_string);
void field_changed() { on_change_field(); }
// set icon to "UndoToSystemValue" button according to an inheritance of preset
// void set_nonsys_btn_icon(const wxBitmap& icon);

View File

@ -1793,12 +1793,12 @@ static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
Vec3d axis = angle_axis.axis();
double angle = angle_axis.angle();
#ifdef _DEBUG
#ifndef NDEBUG
if (std::abs(angle) > 1e-8) {
assert(std::abs(axis.x()) < 1e-8);
assert(std::abs(axis.y()) < 1e-8);
}
#endif /* _DEBUG */
#endif /* NDEBUG */
return (axis.z() < 0) ? -angle : angle;
}
@ -2786,7 +2786,7 @@ void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length)
{
}
#ifdef _DEBUG
#ifndef NDEBUG
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
{
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
@ -2820,7 +2820,7 @@ static void verify_instances_rotation_synchronized(const Model &model, const GLV
}
}
}
#endif /* _DEBUG */
#endif /* NDEBUG */
void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type)
{
@ -2880,9 +2880,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType s
}
}
#ifdef _DEBUG
#ifndef NDEBUG
verify_instances_rotation_synchronized(*m_model, *m_volumes);
#endif /* _DEBUG */
#endif /* NDEBUG */
}
void GLCanvas3D::Selection::_synchronize_unselected_volumes()
@ -3250,6 +3250,7 @@ bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection)
if (!m_enabled || selection.is_empty())
return false;
EType old_current = m_current;
bool handled = false;
for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
{
@ -3273,7 +3274,12 @@ bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection)
handled = true;
}
}
else
}
if (handled && (old_current != Undefined) && (old_current != m_current))
{
GizmosMap::const_iterator it = m_gizmos.find(old_current);
if (it != m_gizmos.end())
it->second->set_state(GLGizmoBase::Off);
}
@ -3742,17 +3748,12 @@ GLCanvas3D::LegendTexture::LegendTexture()
{
}
bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas, bool use_error_colors)
void GLCanvas3D::LegendTexture::fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas,
std::vector<std::pair<double, double>>& cp_legend_values)
{
reset();
// collects items to render
auto title = _(preview_data.get_legend_title());
std::vector<std::pair<double, double>> cp_legend_values;
if (preview_data.extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint)
{
const auto& config = wxGetApp().preset_bundle->full_config();
auto& config = wxGetApp().preset_bundle->project_config;
const std::vector<double>& color_print_values = config.option<ConfigOptionFloats>("colorprint_heights")->values;
const int values_cnt = color_print_values.size();
if (values_cnt > 0) {
@ -3773,7 +3774,19 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
}
}
}
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, /*color_print_values*/cp_legend_values);
}
bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas, bool use_error_colors)
{
reset();
// collects items to render
auto title = _(preview_data.get_legend_title());
std::vector<std::pair<double, double>> cp_legend_values;
fill_color_print_legend_values(preview_data, canvas, cp_legend_values);
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors, cp_legend_values);
unsigned int items_count = (unsigned int)items.size();
if (items_count == 0)
@ -4160,6 +4173,8 @@ unsigned int GLCanvas3D::get_volumes_count() const
void GLCanvas3D::reset_volumes()
{
_set_current();
if (!m_volumes.empty())
{
m_selection.clear();
@ -4614,6 +4629,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr))
return;
_set_current();
struct ModelVolumeState {
ModelVolumeState(const GLVolume *volume) :
model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
@ -4668,10 +4685,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
if (printer_technology == ptSLA) {
const SLAPrint *sla_print = this->sla_print();
#ifdef _DEBUG
#ifndef NDEBUG
// Verify that the SLAPrint object is synchronized with m_model.
check_model_ids_equal(*m_model, sla_print->model());
#endif /* _DEBUG */
#endif /* NDEBUG */
sla_support_state.reserve(sla_print->objects().size());
for (const SLAPrintObject *print_object : sla_print->objects()) {
SLASupportState state;
@ -4920,6 +4937,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
const Print *print = this->fff_print();
if ((m_canvas != nullptr) && (print != nullptr))
{
_set_current();
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
if (m_volumes.empty())
@ -4957,22 +4976,25 @@ void GLCanvas3D::load_sla_preview()
const SLAPrint* print = this->sla_print();
if ((m_canvas != nullptr) && (print != nullptr))
{
_set_current();
_load_shells_sla();
}
}
void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors)
void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors, const std::vector<double>& color_print_values)
{
const Print *print = this->fff_print();
if (print == nullptr)
return;
_set_current();
_load_print_toolpaths();
_load_wipe_tower_toolpaths(str_tool_colors);
for (const PrintObject* object : print->objects())
{
if (object != nullptr)
_load_print_object_toolpaths(*object, str_tool_colors);
_load_print_object_toolpaths(*object, str_tool_colors, color_print_values);
}
for (GLVolume* volume : m_volumes.volumes)
@ -4982,7 +5004,14 @@ void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors)
_update_toolpath_volumes_outside_state();
_show_warning_texture_if_needed();
reset_legend_texture();
if (color_print_values.empty())
reset_legend_texture();
else {
auto preview_data = GCodePreviewData();
preview_data.extrusion.view_type = GCodePreviewData::Extrusion::ColorPrint;
const std::vector<float> tool_colors = _parse_colors(str_tool_colors);
_generate_legend_texture(preview_data, tool_colors);
}
}
void GLCanvas3D::bind_event_handlers()
@ -5630,7 +5659,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
void GLCanvas3D::on_paint(wxPaintEvent& evt)
{
render();
if (m_initialized)
m_dirty = true;
else
// Call render directly, so it gets initialized immediately, not from On Idle handler.
this->render();
}
void GLCanvas3D::on_key_down(wxKeyEvent& evt)
@ -5681,6 +5714,7 @@ Point GLCanvas3D::get_local_mouse_position() const
void GLCanvas3D::reset_legend_texture()
{
_set_current();
m_legend_texture.reset();
}
@ -5951,6 +5985,9 @@ void GLCanvas3D::set_camera_zoom(float zoom)
if (zoom_min > 0.0f)
zoom = std::max(zoom, zoom_min * 0.7f);
// Don't allow to zoom too close to the scene.
zoom = std::min(zoom, 100.0f);
m_camera.zoom = zoom;
viewport_changed();
_refresh_if_shown_on_screen();
@ -7235,7 +7272,7 @@ void GLCanvas3D::_load_print_toolpaths()
volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
}
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors)
void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors, const std::vector<double>& color_print_values)
{
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
@ -7247,6 +7284,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
bool has_infill;
bool has_support;
const std::vector<float>* tool_colors;
const std::vector<double>* color_print_values;
// Number of vertices (each vertex is 6x4=24 bytes long)
static const size_t alloc_size_max() { return 131072; } // 3.15MB
@ -7264,7 +7302,15 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
int volume_idx(int extruder, int feature) const
{
return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature;
return this->color_by_color_print() ? 0 : this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature;
}
// For coloring by a color_print(M600), return a parsed color.
bool color_by_color_print() const { return color_print_values!=nullptr; }
const float* color_print_by_layer_idx(const size_t layer_idx) const
{
auto it = std::lower_bound(color_print_values->begin(), color_print_values->end(), layers[layer_idx]->print_z + EPSILON);
return color_tool((it - color_print_values->begin()) % number_tools());
}
} ctxt;
@ -7272,6 +7318,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
ctxt.has_infill = print_object.is_step_done(posInfill);
ctxt.has_support = print_object.is_step_done(posSupportMaterial);
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
ctxt.color_print_values = color_print_values.empty() ? nullptr : &color_print_values;
ctxt.shifted_copies = &print_object.copies();
@ -7296,7 +7343,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
//FIXME Improve the heuristics for a grain size.
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
size_t grain_size = ctxt.color_by_color_print() ? size_t(1) : std::max(ctxt.layers.size() / 16, size_t(1));
tbb::spin_mutex new_volume_mutex;
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
auto *volume = new GLVolume(color);
@ -7311,7 +7358,9 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
GLVolumePtrs vols;
if (ctxt.color_by_tool()) {
if (ctxt.color_by_color_print())
vols.emplace_back(new_volume(ctxt.color_print_by_layer_idx(range.begin())));
else if (ctxt.color_by_tool()) {
for (size_t i = 0; i < ctxt.number_tools(); ++i)
vols.emplace_back(new_volume(ctxt.color_tool(i)));
}
@ -7629,11 +7678,15 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
}
case GCodePreviewData::Extrusion::ColorPrint:
{
const size_t color_cnt = tool_colors.size() / 4;
int val = int(value);
while (val >= GCodePreviewData::Range::Colors_Count)
val -= GCodePreviewData::Range::Colors_Count;
while (val >= color_cnt)
val -= color_cnt;
GCodePreviewData::Color color = GCodePreviewData::Range::Default_Colors[val];
GCodePreviewData::Color color;
::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + val * 4), 4 * sizeof(float));
return color;
}
default:
@ -8284,6 +8337,8 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state()
void GLCanvas3D::_show_warning_texture_if_needed()
{
_set_current();
if (_is_any_volume_outside())
{
enable_warning_texture(true);

View File

@ -857,6 +857,8 @@ private:
public:
LegendTexture();
void fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas,
std::vector<std::pair<double, double>>& cp_legend_values);
bool generate(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors, const GLCanvas3D& canvas, bool use_error_colors);
@ -1027,8 +1029,7 @@ public:
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
void load_sla_preview();
void load_preview(const std::vector<std::string>& str_tool_colors);
void load_preview(const std::vector<std::string>& str_tool_colors, const std::vector<double>& color_print_values);
void bind_event_handlers();
void unbind_event_handlers();
@ -1133,7 +1134,8 @@ private:
// Create 3D thick extrusion lines for object forming extrusions.
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
// one for perimeters, one for infill and one for supports.
void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors,
const std::vector<double>& color_print_values);
// Create 3D thick extrusion lines for wipe tower extrusions
void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);

View File

@ -64,12 +64,6 @@ ObjectList::ObjectList(wxWindow* parent) :
init_icons();
// create popup menus for object and part
create_object_popupmenu(&m_menu_object);
create_part_popupmenu(&m_menu_part);
create_sla_object_popupmenu(&m_menu_sla_object);
create_instance_popupmenu(&m_menu_instance);
// describe control behavior
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
selection_changed();
@ -106,8 +100,6 @@ ObjectList::ObjectList(wxWindow* parent) :
ObjectList::~ObjectList()
{
if (m_default_config)
delete m_default_config;
}
void ObjectList::create_objects_ctrl()
@ -141,6 +133,15 @@ void ObjectList::create_objects_ctrl()
wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
}
void ObjectList::create_popup_menus()
{
// create popup menus for object and part
create_object_popupmenu(&m_menu_object);
create_part_popupmenu(&m_menu_part);
create_sla_object_popupmenu(&m_menu_sla_object);
create_instance_popupmenu(&m_menu_instance);
}
void ObjectList::set_tooltip_for_item(const wxPoint& pt)
{
wxDataViewItem item;
@ -310,7 +311,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item)
wxGetApp().plater()->update();
}
void ObjectList::update_name_in_model(const wxDataViewItem& item)
void ObjectList::update_name_in_model(const wxDataViewItem& item) const
{
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
if (obj_idx < 0) return;
@ -421,9 +422,6 @@ void ObjectList::show_context_menu()
if (multiple_selection() && selected_instances_of_same_object())
{
wxGetApp().plater()->PopupMenu(&m_menu_instance);
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
return;
}
@ -442,12 +440,6 @@ void ObjectList::show_context_menu()
append_menu_item_settings(menu);
wxGetApp().plater()->PopupMenu(menu);
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(is_splittable()); }, m_menu_item_split->GetId());
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId());
}
}
@ -755,10 +747,8 @@ void ObjectList::get_settings_choice(const wxString& category_name)
const ConfigOption* option = from_config.option(opt_key);
if (!option) {
// if current option doesn't exist in prints.get_edited_preset(),
// get it from m_default_config
if (m_default_config) delete m_default_config;
m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false));
option = m_default_config->option(opt_key);
// get it from default config values
option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key);
}
m_config->set_key_value(opt_key, option->clone());
}
@ -782,10 +772,8 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name)
const ConfigOption* option = from_config.option(opt_key);
if (!option) {
// if current option doesn't exist in prints.get_edited_preset(),
// get it from m_default_config
if (m_default_config) delete m_default_config;
m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(false));
option = m_default_config->option(opt_key);
// get it from default config values
option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key);
}
m_config->set_key_value(opt_key, option->clone());
}
@ -964,8 +952,30 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
[this](wxCommandEvent&) { split_instances(); }, "", menu);
}
void ObjectList::append_menu_item_rename(wxMenu* menu)
{
append_menu_item(menu, wxID_ANY, _(L("Rename")), "",
[this](wxCommandEvent&) { rename_item(); }, "", menu);
menu->AppendSeparator();
}
void ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu)
{
if (!is_windows10())
return;
append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "",
[this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu);
menu->AppendSeparator();
}
void ObjectList::create_object_popupmenu(wxMenu *menu)
{
#ifdef __WXOSX__
append_menu_item_rename(menu);
#endif // __WXOSX__
append_menu_item_fix_through_netfabb(menu);
// Split object to parts
m_menu_item_split = append_menu_item_split(menu);
menu->AppendSeparator();
@ -973,16 +983,30 @@ void ObjectList::create_object_popupmenu(wxMenu *menu)
// rest of a object_menu will be added later in:
// - append_menu_items_add_volume() -> for "Add (volumes)"
// - append_menu_item_settings() -> for "Add (settings)"
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(is_splittable()); }, m_menu_item_split->GetId());
}
void ObjectList::create_sla_object_popupmenu(wxMenu *menu)
{
#ifdef __WXOSX__
append_menu_item_rename(menu);
#endif // __WXOSX__
append_menu_item_fix_through_netfabb(menu);
// rest of a object_sla_menu will be added later in:
// - append_menu_item_settings() -> for "Add (settings)"
}
void ObjectList::create_part_popupmenu(wxMenu *menu)
{
#ifdef __WXOSX__
append_menu_item_rename(menu);
#endif // __WXOSX__
append_menu_item_fix_through_netfabb(menu);
m_menu_item_split_part = append_menu_item_split(menu);
// Append change part type
@ -991,11 +1015,17 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
// rest of a object_sla_menu will be added later in:
// - append_menu_item_settings() -> for "Add (settings)"
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId());
}
void ObjectList::create_instance_popupmenu(wxMenu*menu)
{
m_menu_item_split_instances = append_menu_item_instance_to_object(menu);
wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
}
wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
@ -2052,6 +2082,66 @@ void ObjectList::split_instances()
instances_to_separated_object(obj_idx, inst_idxs);
}
void ObjectList::rename_item()
{
const wxDataViewItem item = GetSelection();
if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
return ;
const wxString new_name = wxGetTextFromUser(_(L("Enter new name"))+":", _(L("Renaming")),
m_objects_model->GetName(item), this);
if (new_name.IsEmpty())
return;
bool is_unusable_symbol = false;
std::string chosen_name = Slic3r::normalize_utf8_nfc(new_name.ToUTF8());
const char* unusable_symbols = "<>:/\\|?*\"";
for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
if (chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
is_unusable_symbol = true;
}
}
if (is_unusable_symbol) {
show_error(this, _(L("The supplied name is not valid;")) + "\n" +
_(L("the following characters are not allowed:")) + " <>:/\\|?*\"");
return;
}
// The icon can't be edited so get its old value and reuse it.
wxVariant valueOld;
m_objects_model->GetValue(valueOld, item, 0);
PrusaDataViewBitmapText bmpText;
bmpText << valueOld;
// But replace the text with the value entered by user.
bmpText.SetText(new_name);
wxVariant value;
value << bmpText;
m_objects_model->SetValue(value, item, 0);
m_objects_model->ItemChanged(item);
update_name_in_model(item);
}
void ObjectList::fix_through_netfabb() const
{
const wxDataViewItem item = GetSelection();
if (!item)
return;
ItemType type = m_objects_model->GetItemType(item);
if (type & itObject)
wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(item));
else if (type & itVolume)
wxGetApp().plater()->fix_through_netfabb(m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)),
m_objects_model->GetVolumeIdByItem(item));
}
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
{
if (event.GetColumn() == 0)

View File

@ -97,9 +97,6 @@ class ObjectList : public wxDataViewCtrl
} m_dragged_data;
wxBoxSizer *m_sizer {nullptr};
DynamicPrintConfig *m_default_config {nullptr};
wxWindow *m_parent {nullptr};
wxBitmap m_bmp_modifiermesh;
@ -153,6 +150,7 @@ public:
void create_objects_ctrl();
void create_popup_menus();
wxDataViewColumn* create_objects_list_extruder_column(int extruders_count);
void update_objects_list_extruder_column(int extruders_count);
// show/hide "Extruder" column for Objects List
@ -160,7 +158,7 @@ public:
// update extruder in current config
void update_extruder_in_config(const wxDataViewItem& item);
// update changed name in the object model
void update_name_in_model(const wxDataViewItem& item);
void update_name_in_model(const wxDataViewItem& item) const;
void update_extruder_values_for_items(const int max_extruder);
void init_icons();
@ -181,6 +179,8 @@ public:
wxMenuItem* append_menu_item_settings(wxMenu* menu);
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu);
void append_menu_item_rename(wxMenu* menu);
void append_menu_item_fix_through_netfabb(wxMenu* menu);
void create_object_popupmenu(wxMenu *menu);
void create_sla_object_popupmenu(wxMenu*menu);
void create_part_popupmenu(wxMenu*menu);
@ -262,7 +262,8 @@ public:
void instances_to_separated_object(const int obj_idx, const std::set<int>& inst_idx);
void split_instances();
void rename_item();
void fix_through_netfabb() const;
private:
void OnChar(wxKeyEvent& event);
void OnContextMenu(wxDataViewEvent &event);

View File

@ -558,6 +558,7 @@ void Preview::create_double_slider()
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
m_preferred_color_mode = "feature";
}
reload_print();
});
}
@ -728,10 +729,22 @@ void Preview::load_print_as_fff()
m_preferred_color_mode = "tool_or_feature";
}
bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty();
// Collect colors per extruder.
std::vector<std::string> colors;
bool gcode_preview_data_valid = print->is_step_done(psGCodeExport) && ! m_gcode_preview_data->empty();
if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool))
std::vector<double> color_print_values = {};
// set color print values, if it si selected "ColorPrint" view type
if (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint)
{
colors = GCodePreviewData::ColorPrintColors();
if (! gcode_preview_data_valid) {
//FIXME accessing full_config() is pretty expensive.
// Only initialize color_print_values for the initial preview, not for the full preview where the color_print_values is extracted from the G-code.
const auto& config = wxGetApp().preset_bundle->project_config;
color_print_values = config.option<ConfigOptionFloats>("colorprint_heights")->values;
}
}
else if (gcode_preview_data_valid || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool) )
{
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(m_config->option("extruder_colour"));
const ConfigOptionStrings* filamemts_opt = dynamic_cast<const ConfigOptionStrings*>(m_config->option("filament_colour"));
@ -748,8 +761,9 @@ void Preview::load_print_as_fff()
color = "#FFFFFF";
}
colors.push_back(color);
colors.emplace_back(color);
}
color_print_values.clear();
}
if (IsShown())
@ -759,7 +773,7 @@ void Preview::load_print_as_fff()
m_canvas->load_gcode_preview(*m_gcode_preview_data, colors);
else
// Load the initial preview based on slices, not the final G-code.
m_canvas->load_preview(colors);
m_canvas->load_preview(colors, color_print_values);
show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple");
// recalculates zs and update sliders accordingly
std::vector<double> zs = m_canvas->get_current_print_zs(true);

View File

@ -22,6 +22,7 @@
#include "AppConfig.hpp"
#include "PrintHostDialogs.hpp"
#include "wxExtensions.hpp"
#include "GUI_ObjectList.hpp"
#include "I18N.hpp"
#include <fstream>
@ -132,6 +133,8 @@ void MainFrame::init_tabpanel()
wxGetApp().plater_ = m_plater;
m_tabpanel->AddPage(m_plater, _(L("Plater")));
wxGetApp().obj_list()->create_popup_menus();
// The following event is emited by Tab implementation on config value change.
Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this);
@ -236,11 +239,11 @@ void MainFrame::init_menubar()
// File menu
wxMenu* fileMenu = new wxMenu;
{
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open")) + dots + "\tCtrl+O", _(L("Open a project file")),
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png");
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save")) + "\tCtrl+S", _(L("Save current project file")),
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png");
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png");
fileMenu->AppendSeparator();

View File

@ -1031,7 +1031,7 @@ struct Plater::priv
void update_restart_background_process(bool force_scene_update, bool force_preview_update);
void export_gcode(fs::path output_path, PrintHostJob upload_job);
void reload_from_disk();
void fix_through_netfabb(const int obj_idx);
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
void set_current_panel(wxPanel* panel);
@ -1717,6 +1717,8 @@ void Plater::priv::reset()
object_list_changed();
update();
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
this->sidebar->show_sliced_info_sizer(false);
auto& config = wxGetApp().preset_bundle->project_config;
config.option<ConfigOptionFloats>("colorprint_heights")->values.clear();
@ -2104,7 +2106,7 @@ void Plater::priv::reload_from_disk()
remove(obj_orig_idx);
}
void Plater::priv::fix_through_netfabb(const int obj_idx)
void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
{
if (obj_idx < 0)
return;
@ -2438,6 +2440,8 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
}
menu->AppendSeparator();
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
wxMenu* mirror_menu = new wxMenu();
if (mirror_menu == nullptr)
return false;
@ -3148,7 +3152,7 @@ void Plater::changed_object(int obj_idx)
this->p->schedule_background_process();
}
void Plater::fix_through_netfabb(const int obj_idx) { p->fix_through_netfabb(obj_idx); }
void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); }
void Plater::update_object_menu() { p->update_object_menu(); }

View File

@ -147,7 +147,7 @@ public:
void export_3mf(const boost::filesystem::path& output_path = boost::filesystem::path());
void reslice();
void changed_object(int obj_idx);
void fix_through_netfabb(const int obj_idx);
void fix_through_netfabb(const int obj_idx, const int vol_idx = -1);
void send_gcode();
void on_extruders_change(int extruders_count);

View File

@ -323,7 +323,10 @@ const std::vector<std::string>& Preset::print_options()
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "external_fill_pattern",
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed",
"max_volumetric_speed", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative",
"max_volumetric_speed",
#ifdef HAS_PRESSURE_EQUALIZER
"max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative",
#endif /* HAS_PRESSURE_EQUALIZER */
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed",
"top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed",
"bridge_speed", "gap_fill_speed", "travel_speed", "first_layer_speed", "perimeter_acceleration", "infill_acceleration",
@ -531,6 +534,9 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
boost::filesystem::path dir = boost::filesystem::canonical(boost::filesystem::path(dir_path) / subdir).make_preferred();
m_dir_path = dir.string();
std::string errors_cummulative;
// Store the loaded presets into a new vector, otherwise the binary search for already existing presets would be broken.
// (see the "Preset already present, not loading" message).
std::deque<Preset> presets_loaded;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini") &&
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
@ -568,12 +574,13 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
} catch (const std::runtime_error &err) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what());
}
m_presets.emplace_back(preset);
presets_loaded.emplace_back(preset);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
errors_cummulative += "\n";
}
}
m_presets.insert(m_presets.end(), std::make_move_iterator(presets_loaded.begin()), std::make_move_iterator(presets_loaded.end()));
std::sort(m_presets.begin() + m_num_default_presets, m_presets.end());
this->select_preset(first_visible_idx());
if (! errors_cummulative.empty())

View File

@ -1028,8 +1028,10 @@ void TabPrint::build()
optgroup = page->new_optgroup(_(L("Autospeed (advanced)")));
optgroup->append_single_option_line("max_print_speed");
optgroup->append_single_option_line("max_volumetric_speed");
#ifdef HAS_PRESSURE_EQUALIZER
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive");
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative");
#endif /* HAS_PRESSURE_EQUALIZER */
page = add_options_page(_(L("Multiple Extruders")), "funnel.png");
optgroup = page->new_optgroup(_(L("Extruders")));
@ -1587,11 +1589,11 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent e) {
btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent &e) {
BonjourDialog dialog(parent);
if (dialog.show_and_lookup()) {
optgroup->set_value("print_host", std::move(dialog.get_selected()), true);
// FIXME: emit killfocus on the edit widget
optgroup->get_field("print_host")->field_changed();
}
});
@ -1605,7 +1607,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) {
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
if (! host) {
const auto text = wxString::Format("%s",
@ -1646,6 +1648,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (openFileDialog.ShowModal() != wxID_CANCEL) {
optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true);
optgroup->get_field("printhost_cafile")->field_changed();
}
});

View File

@ -1867,8 +1867,10 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc)
return;
}
const std::vector<unsigned char>& clr_bytes = Slic3r::GCodePreviewData::Range::Default_Colors[0].as_bytes();
wxColour clr = wxColour(clr_bytes[0], clr_bytes[1], clr_bytes[2], clr_bytes[3]);
const std::vector<std::string>& colors = Slic3r::GCodePreviewData::ColorPrintColors();
const size_t colors_cnt = colors.size();
wxColour clr(colors[0]);
dc.SetPen(clr);
dc.SetBrush(clr);
dc.DrawRectangle(main_band);
@ -1876,15 +1878,13 @@ void PrusaDoubleSlider::draw_colored_band(wxDC& dc)
int i = 1;
for (auto tick : m_ticks)
{
if (i == Slic3r::GCodePreviewData::Range::Colors_Count)
if (i == colors_cnt)
i = 0;
const wxCoord pos = get_position_from_value(tick);
is_horizontal() ? main_band.SetLeft(SLIDER_MARGIN + pos) :
main_band.SetBottom(pos-1);
const std::vector<unsigned char>& clr_b = Slic3r::GCodePreviewData::Range::Default_Colors[i].as_bytes();
clr = wxColour(clr_b[0], clr_b[1], clr_b[2], clr_b[3]);
clr = wxColour(colors[i]);
dc.SetPen(clr);
dc.SetBrush(clr);
dc.DrawRectangle(main_band);