Skip to content

Commit

Permalink
Merge trunk (#4)
Browse files Browse the repository at this point in the history
* Use the correct LIBPNG

* ENABLE_LAYOUT_NO_RESTART -> Added an extra sizer to Mainframe to avoid hiding the entire application when switching the layout type

* Fixed initial size of features type combo popup when building against wxWidgets 3.1.3

* Fix macos deps

* prusa3d#4492 - Fixed application loosing focus when importing models

* Attempt to fix crash on Mac when rotating an object while layer editing is active

* Support for collecting warnings from the background processing.

Multiple warnigns may be collected per Print / PrintObject milestone
and a status update is sent to the UI immediately after a warning
is issued.

* Update of back-end warnings:
Back-end warnings contain two new members: "current" and "message_id".
A warning is set to "not current" if its milestone is invalidated.

* Fix of previous commit.

* Empty layers check converted to a warning (except for the first layer)

* Pull request prusa3d#4235 - Fix tick/untick ironing feature in preview by rongith

* Empty layer check fix
The test gave false positive in case there were supposed to be both object and support extrusions on the first layer

* Added well-known metadata to 3mf export

* GUI_objectList: fixed typo in assert

* Fixed back-end warning infrastructure: The Print / PrintObject
should have been derived from ObjectBase, not from ObjectID.

* Temporary ironing icon to avoid crashes on GTK
Ironing type and spacing can be set per-object

* Fixed update of the TreeCtrls and "revert to system values" buttons on preset tabs, if application was run in New or Dlg mode

* Fixed a bug in selection from the 3D scene.

Steps to the reproduce a crash:
1. In SLA mode add some object with several instances
2. Slice
3. Back to 3Dview scene, select all using Ctrl+A
4. Press "Delete"

* Hot fix for the last commit

* TriangleSelector: draft of interface

* TriangleSelector: first partially working implementation

* TriangleSelector: Improvements

* TriangleSelector: even more progress

* TriangleSelector: remerging triangles, bugfixes

* TriangleSelector: Reusing of previously calculated triangle divisions, partial garbage collection implementation

* TriangleSelector: Vertices are reference-counted and garbage collected
Garbage collection is triggered automatically when more than half of all triangles are invalid

* TriangleSelector: getting ready for frontend/backend separation

* TriangleSelector: Serialization and deserialization

* TriangleSelector: Separated frontend/backend, support of multiple volumes, etc.

* TriangleSelector: 'Select by angle' and 'reset selection' functions fixed

* TriangleSelector: backend is aware of divided triangles

* TriangleSelector: Schedule restarting background process after edit

* TriangleSelector: Fix of a macOS crash
Calling reset() from constructor relied on uninitialized variable

* TriangleSelector: bugfix - backend did not correctly account for mirrorring

* TriangleSelector: edge limit is derived from cursor size

* TriangleSelector: 3MF loading and saving

* Showing Eject button only after exporting is finished. Fix of prusa3d#4212

* added 's' in https when pointing users to our github

* Deleted default value in Plater::export_gcode(bool prefer_removable). Only place where it is not sure what value should be is in btn_reslice - i chose true

* Added handling of mouse wheel events to ImGuiWrapper

Co-authored-by: bgiot <[email protected]>
Co-authored-by: enricoturri1966 <[email protected]>
Co-authored-by: tamasmeszaros <[email protected]>
Co-authored-by: Vojtech Bubnik <[email protected]>
Co-authored-by: Lukas Matena <[email protected]>
Co-authored-by: YuSanka <[email protected]>
Co-authored-by: rongith <[email protected]>
Co-authored-by: David Kocik <[email protected]>
  • Loading branch information
9 people authored Aug 1, 2020
1 parent 9324a9d commit 7b19e75
Show file tree
Hide file tree
Showing 32 changed files with 1,549 additions and 335 deletions.
2 changes: 2 additions & 0 deletions deps/deps-macos.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ set(DEP_CMAKE_OPTS
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEP_OSX_TARGET}"
"-DCMAKE_CXX_FLAGS=${DEP_WERRORS_SDK}"
"-DCMAKE_C_FLAGS=${DEP_WERRORS_SDK}"
"-DCMAKE_FIND_FRAMEWORK=LAST"
"-DCMAKE_FIND_APPBUNDLE=LAST"
)

include("deps-unix-common.cmake")
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ add_library(libslic3r STATIC
Utils.hpp
Time.cpp
Time.hpp
TriangleSelector.cpp
TriangleSelector.hpp
MTUtils.hpp
VoronoiOffset.cpp
VoronoiOffset.hpp
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
case erOverhangPerimeter : return L("Overhang perimeter");
case erInternalInfill : return L("Internal infill");
case erSolidInfill : return L("Solid infill");
case erIroning : return L("Ironing");
case erTopSolidInfill : return L("Top solid infill");
case erIroning : return L("Ironing");
case erBridgeInfill : return L("Bridge infill");
case erGapFill : return L("Gap fill");
case erSkirt : return L("Skirt");
Expand Down
37 changes: 34 additions & 3 deletions src/libslic3r/Format/3mf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../GCode.hpp"
#include "../Geometry.hpp"
#include "../GCode/ThumbnailData.hpp"
#include "../Time.hpp"

#include "../I18N.hpp"

Expand Down Expand Up @@ -85,6 +86,7 @@ const char* OBJECTID_ATTR = "objectid";
const char* TRANSFORM_ATTR = "transform";
const char* PRINTABLE_ATTR = "printable";
const char* INSTANCESCOUNT_ATTR = "instances_count";
const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";

const char* KEY_ATTR = "key";
const char* VALUE_ATTR = "value";
Expand Down Expand Up @@ -282,6 +284,7 @@ namespace Slic3r {
{
std::vector<float> vertices;
std::vector<unsigned int> triangles;
std::vector<std::string> custom_supports;

bool empty()
{
Expand All @@ -292,6 +295,7 @@ namespace Slic3r {
{
vertices.clear();
triangles.clear();
custom_supports.clear();
}
};

Expand Down Expand Up @@ -1538,6 +1542,8 @@ namespace Slic3r {
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V1_ATTR));
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V2_ATTR));
m_curr_object.geometry.triangles.push_back((unsigned int)get_attribute_value_int(attributes, num_attributes, V3_ATTR));

m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
return true;
}

Expand Down Expand Up @@ -1871,6 +1877,13 @@ namespace Slic3r {
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
volume->calculate_convex_hull();

// recreate custom supports from previously loaded attribute
assert(geometry.custom_supports.size() == triangles_count);
for (unsigned i=0; i<triangles_count; ++i) {
if (! geometry.custom_supports[i].empty())
volume->m_supported_facets.set_triangle_from_string(i, geometry.custom_supports[i]);
}

// apply the remaining volume's metadata
for (const Metadata& metadata : volume_data.metadata)
{
Expand Down Expand Up @@ -1991,7 +2004,7 @@ namespace Slic3r {
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data);
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data);
bool _add_model_file_to_archive(const std::string& filename, mz_zip_archive& archive, const Model& model, IdToObjectDataMap& objects_data);
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets);
bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items);
Expand Down Expand Up @@ -2054,7 +2067,7 @@ namespace Slic3r {
// Adds model file ("3D/3dmodel.model").
// This is the one and only file that contains all the geometry (vertices and triangles) of all ModelVolumes.
IdToObjectDataMap objects_data;
if (!_add_model_file_to_archive(archive, model, objects_data))
if (!_add_model_file_to_archive(filename, archive, model, objects_data))
{
close_zip_writer(&archive);
boost::filesystem::remove(filename);
Expand Down Expand Up @@ -2203,7 +2216,7 @@ namespace Slic3r {
return true;
}

bool _3MF_Exporter::_add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data)
bool _3MF_Exporter::_add_model_file_to_archive(const std::string& filename, mz_zip_archive& archive, const Model& model, IdToObjectDataMap& objects_data)
{
std::stringstream stream;
// https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
Expand All @@ -2214,6 +2227,19 @@ namespace Slic3r {
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n";
stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "</" << METADATA_TAG << ">\n";
std::string name = boost::filesystem::path(filename).stem().string();
stream << " <" << METADATA_TAG << " name=\"Title\">" << name << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"Designer\">" << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"Description\">" << name << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"Copyright\">" << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"LicenseTerms\">" << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"Rating\">" << "</" << METADATA_TAG << ">\n";
std::string date = Slic3r::Utils::utc_timestamp(Slic3r::Utils::get_current_time_utc());
// keep only the date part of the string
date = date.substr(0, 10);
stream << " <" << METADATA_TAG << " name=\"CreationDate\">" << date << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"ModificationDate\">" << date << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"Application\">" << SLIC3R_APP_KEY << "-" << SLIC3R_VERSION << "</" << METADATA_TAG << ">\n";
stream << " <" << RESOURCES_TAG << ">\n";

// Instance transformations, indexed by the 3MF object ID (which is a linear serialization of all instances of all ModelObjects).
Expand Down Expand Up @@ -2369,6 +2395,11 @@ namespace Slic3r {
{
stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" ";
}

std::string custom_supports_data_string = volume->m_supported_facets.get_triangle_as_string(i);
if (! custom_supports_data_string.empty())
stream << CUSTOM_SUPPORTS_ATTR << "=\"" << custom_supports_data_string << "\" ";

stream << "/>\n";
}
}
Expand Down
24 changes: 16 additions & 8 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,15 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec

layers_to_print.emplace_back(layer_to_print);

bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions());

// Check that there are extrusions on the very first layer.
if (layers_to_print.size() == 1u) {
if (! has_extrusions)
throw std::runtime_error(_(L("There is an object with no extrusions on the first layer.")));
}

// In case there are extrusions on this layer, check there is a layer to lay it on.
if ((layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
// Allow empty support layers, as the support generator may produce no extrusions for non-empty support regions.
Expand All @@ -630,18 +639,18 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
// Negative support_contact_z is not taken into account, it can result in false positives in cases
// where previous layer has object extrusions too (https://github.com/prusa3d/PrusaSlicer/issues/2752)

// Only check this layer in case it has some extrusions.
bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions())
|| (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions());

if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON)
throw std::runtime_error(_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) {
const_cast<Print*>(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
_(L("Empty layers detected, the output would not be printable.")) + "\n\n" +
_(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " +
std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is "
"usually caused by negligibly small extrusions or by a faulty model. Try to repair "
"the model or change its orientation on the bed.")));
}

// Remember last layer with extrusions.
last_extrusion_layer = &layers_to_print.back();
if (has_extrusions)
last_extrusion_layer = &layers_to_print.back();
}
}

Expand Down Expand Up @@ -1939,7 +1948,6 @@ void GCode::process_layer(
const size_t single_object_instance_idx)
{
assert(! layers.empty());
// assert(! layer_tools.extruders.empty());
// Either printing all copies of all objects, or just a single copy of a single object.
assert(single_object_instance_idx == size_t(-1) || layers.size() == 1);

Expand Down
86 changes: 71 additions & 15 deletions src/libslic3r/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ModelArrange.hpp"
#include "Geometry.hpp"
#include "MTUtils.hpp"
#include "TriangleSelector.hpp"

#include "Format/AMF.hpp"
#include "Format/OBJ.hpp"
Expand Down Expand Up @@ -1830,28 +1831,25 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
}


std::vector<int> FacetsAnnotation::get_facets(FacetSupportType type) const
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, FacetSupportType type) const
{
std::vector<int> out;
for (auto& [facet_idx, this_type] : m_data)
if (this_type == type)
out.push_back(facet_idx);
TriangleSelector selector(mv.mesh());
selector.deserialize(m_data);
indexed_triangle_set out = selector.get_facets(type);
return out;
}



void FacetsAnnotation::set_facet(int idx, FacetSupportType type)
bool FacetsAnnotation::set(const TriangleSelector& selector)
{
bool changed = true;

if (type == FacetSupportType::NONE)
changed = m_data.erase(idx) != 0;
else
m_data[idx] = type;

if (changed)
std::map<int, std::vector<bool>> sel_map = selector.serialize();
if (sel_map != m_data) {
m_data = sel_map;
update_timestamp();
return true;
}
return false;
}


Expand All @@ -1864,6 +1862,64 @@ void FacetsAnnotation::clear()



// Following function takes data from a triangle and encodes it as string
// of hexadecimal numbers (one digit per triangle). Used for 3MF export,
// changing it may break backwards compatibility !!!!!
std::string FacetsAnnotation::get_triangle_as_string(int triangle_idx) const
{
std::string out;

auto triangle_it = m_data.find(triangle_idx);
if (triangle_it != m_data.end()) {
const std::vector<bool>& code = triangle_it->second;
int offset = 0;
while (offset < int(code.size())) {
int next_code = 0;
for (int i=3; i>=0; --i) {
next_code = next_code << 1;
next_code |= int(code[offset + i]);
}
offset += 4;

assert(next_code >=0 && next_code <= 15);
char digit = next_code < 10 ? next_code + '0' : (next_code-10)+'A';
out.insert(out.begin(), digit);
}
}
return out;
}



// Recover triangle splitting & state from string of hexadecimal values previously
// generated by get_triangle_as_string. Used to load from 3MF.
void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::string& str)
{
assert(! str.empty());
m_data[triangle_id] = std::vector<bool>(); // zero current state or create new
std::vector<bool>& code = m_data[triangle_id];

for (auto it = str.crbegin(); it != str.crend(); ++it) {
const char ch = *it;
int dec = 0;
if (ch >= '0' && ch<='9')
dec = int(ch - '0');
else if (ch >='A' && ch <= 'F')
dec = 10 + int(ch - 'A');
else
assert(false);

// Convert to binary and append into code.
for (int i=0; i<4; ++i) {
code.insert(code.end(), bool(dec & (1 << i)));
}
}


}



// Test whether the two models contain the same number of ModelObjects with the same set of IDs
// ordered in the same order. In that case it is not necessary to kill the background processing.
bool model_object_list_equal(const Model &model_old, const Model &model_new)
Expand Down Expand Up @@ -1935,7 +1991,7 @@ bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject
return true;
}
return false;
};
}

extern bool model_has_multi_part_objects(const Model &model)
{
Expand Down
11 changes: 8 additions & 3 deletions src/libslic3r/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ModelVolume;
class ModelWipeTower;
class Print;
class SLAPrint;
class TriangleSelector;

namespace UndoRedo {
class StackImpl;
Expand Down Expand Up @@ -394,6 +395,7 @@ enum class ModelVolumeType : int {
};

enum class FacetSupportType : int8_t {
// Maximum is 3. The value is serialized in TriangleSelector into 2 bits!
NONE = 0,
ENFORCER = 1,
BLOCKER = 2
Expand All @@ -403,9 +405,12 @@ class FacetsAnnotation {
public:
using ClockType = std::chrono::steady_clock;

std::vector<int> get_facets(FacetSupportType type) const;
void set_facet(int idx, FacetSupportType type);
const std::map<int, std::vector<bool>>& get_data() const { return m_data; }
bool set(const TriangleSelector& selector);
indexed_triangle_set get_facets(const ModelVolume& mv, FacetSupportType type) const;
void clear();
std::string get_triangle_as_string(int i) const;
void set_triangle_from_string(int triangle_id, const std::string& str);

ClockType::time_point get_timestamp() const { return timestamp; }
bool is_same_as(const FacetsAnnotation& other) const {
Expand All @@ -418,7 +423,7 @@ class FacetsAnnotation {
}

private:
std::map<int, FacetSupportType> m_data;
std::map<int, std::vector<bool>> m_data;

ClockType::time_point timestamp;
void update_timestamp() {
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/ObjectID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class ObjectID

// Base for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial to provide a unique ID
// to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject).
// Also base for Print, PrintObject, SLAPrint, SLAPrintObject to provide a unique ID for matching Model / ModelObject
// with their corresponding Print / PrintObject objects by the notification center at the UI when processing back-end warnings.
// Achtung! The s_last_id counter is not thread safe, so it is expected, that the ObjectBase derived instances
// are only instantiated from the main thread.
class ObjectBase
Expand Down
7 changes: 7 additions & 0 deletions src/libslic3r/Print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,13 @@ class Print : public PrintBaseWithState<PrintStep, psCount>
const PrintObjectPtrs& objects() const { return m_objects; }
PrintObject* get_object(size_t idx) { return m_objects[idx]; }
const PrintObject* get_object(size_t idx) const { return m_objects[idx]; }
// PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
// in the notification center.
const PrintObject* get_object(ObjectID object_id) const {
auto it = std::find_if(m_objects.begin(), m_objects.end(),
[object_id](const PrintObject *obj) { return obj->id() == object_id; });
return (it == m_objects.end()) ? nullptr : *it;
}
const PrintRegionPtrs& regions() const { return m_regions; }
// How many of PrintObject::copies() over all print objects are there?
// If zero, then the print is empty and the print shall not be executed.
Expand Down
Loading

0 comments on commit 7b19e75

Please sign in to comment.